diff --git a/README.md b/README.md index 10524a8f..68b888f0 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,14 @@ Playbook:工程规范与代理规则合集,当前覆盖: - `docs/index.md`:文档导航(跨语言 common / TSL / C++ / Python / TypeScript / Markdown)。 - `docs/common/commit_message.md`:提交信息与版本号规范(type/scope/subject/body/footer、可选 Emoji 图例、SemVer)。 +- `docs/tsl/index.md`:TSL canonical 入口(语法 / 金融 / 模块 / 函数检索四层)。 - `docs/tsl/code_style.md`:TSL 代码结构、格式、`begin/end` 代码块、注释与通用最佳实践。 - `docs/tsl/naming.md`:TSL 命名规范(顶层声明、文件同名规则、变量/成员/property、常量、集合命名等)。 -- `docs/tsl/syntax_book/index.md`:TSL 语法手册(整理自原始语法/机制目录册;函数库位于 - `docs/tsl/syntax_book/function/`,按需检索)。 +- `docs/tsl/syntax/index.md`:TSL 语法手册。 +- `docs/tsl/finance/index.md`:TSL 金融业务层入口(指标、选股、回测与业务流程问题)。 +- `docs/tsl/modules/index.md`:TSL 模块层入口(pyTSL、微信消息、Python 互操作、回测框架)。 +- `docs/tsl/reference/index.md`:TSL 函数检索入口(模块目录位于 `docs/tsl/reference/catalog/`)。 - `docs/tsl/toolchain.md`:TSL 工具链与验证命令模板。 - `docs/cpp/code_style.md`:C++ 代码风格(C++23/Modules)。 - `docs/cpp/naming.md`:C++ 命名规范(Google 基线)。 @@ -112,7 +115,6 @@ Layer 1: rulesets/ (≤50 行/语言,模板源) └─ 指向 Skills 和 docs Layer 2: codex/skills/ (按需加载,$skill-name 触发) - ├─ tsl-guide: TSL 渐进式语法教学 ├─ commit-message: 提交信息规范 ├─ style-cleanup: 代码风格整理 └─ bulk-refactor-workflow: 批量重构流程 @@ -162,9 +164,7 @@ Layer 3: docs/ (权威静态文档) 本仓库内置一组 Codex CLI skills(见 `codex/skills/`),用于按需加载的工作流与知识库。 -**核心 Skills**: - -- **`$tsl-guide`**:TSL/TSF 语法完整指南(基础/高级/函数库/最佳实践) +TSL 相关问题直接查阅 `rulesets/tsl/index.md` 与 `docs/tsl/`。 **通用 Skills**: @@ -177,22 +177,29 @@ Layer 3: docs/ (权威静态文档) ## 在其他项目中使用本 Playbook -由于本仓库需要内部权限访问,其他项目**不能仅用外链引用**;推荐把 Playbook 规范 vendoring 到项目内,并用统一入口执行。 +由于本仓库需要内部权限访问,其他项目**不能仅用外链引用**;推荐把 Playbook 规范部署到项目内,并用统一入口执行。 ### 快速决策:我应该用哪种方式? -| 你的情况 | 推荐方式 | 优势 | -| ---------------------------------- | ------------------------------- | ------------------------------- | -| 新项目,需要持续同步更新 | 方式一:git subtree | 可随时拉取最新标准,版本可追溯 | -| 只需要一次性引入,不常更新 | 方式二:手动复制快照 | 简单直接,无需 git subtree 知识 | -| 只需要部分语言(且希望快照也裁剪) | 方式三:CLI 裁剪复制(vendor) | 快照只包含所需语言(更小) | -| **不确定?** | **方式一:git subtree(推荐)** | 最灵活,后续可随时同步更新 | +| 你的情况 | 推荐方式 | 优势 | +| --- | --- | --- | +| 新项目,需要持续同步更新 | 方式一:`git subtree` | 标准留在项目内,后续可拉取更新 | +| 不想把 Playbook 以 subtree 嵌进仓库,但仍要把标准部署到项目内 | 方式二:外部 clone 后执行部署 | Playbook 仓库与业务仓库解耦,部署根目录可配置 | +| **不确定?** | **方式一:`git subtree`(推荐)** | 项目内可见、版本可追溯、使用路径最稳定 | --- ### TL;DR - 30 秒快速开始 -以 TSL 为例: +先区分三个路径概念: + +- `project_root`:目标项目根目录。 +- `deploy_root`:相对于 `project_root` 的项目内目标目录。 +- 外部 clone 出来的 Playbook 路径,例如 `C:/tools/playbook`:只是执行部署脚本的位置,不是外部 clone 出来的 Playbook 仓库路径对应的部署目标。 + +以 TSL 为例,Playbook 在项目内的默认部署根是 `docs/standards/playbook`;如果你把 `deploy_root` 改成 `custom/playbook`,则部署结果会落到 `/custom/playbook`,文档和脚本入口也会跟着变成 `custom/playbook/docs/...`、`custom/playbook/scripts/...`。 + +#### 方式一:`git subtree` ```bash # 1. 引入标准快照 @@ -255,38 +262,51 @@ git commit -m ":package: deps(playbook): add tsl standards" --- -### 方式二:手动复制快照 +### 方式二:外部 clone 后执行部署 -如果不使用 git subtree,也可手动复制快照到目标项目: +如果你不想把 Playbook 以 `git subtree` 嵌进目标项目,可以把 Playbook clone 到项目外部,再由该 clone 直接把标准部署进目标项目。 -1. 创建目录:`docs/standards/playbook/`。 -2. 复制 Playbook 快照内容(建议使用方式三生成裁剪快照)。 -3. 在项目根执行统一入口: +1. 先在任意位置 clone Playbook: ```bash - python docs/standards/playbook/scripts/playbook.py -config playbook.toml + git clone https://git.mytsl.cn/csh/playbook.git C:/tools/playbook ``` ---- +2. 在目标项目根创建 `playbook.toml`,并用 `deploy_root` 指定项目内的部署根。例如: -### 方式三:CLI 裁剪复制(按语言,离线) + - `project_root` 写目标项目根目录。 + - `deploy_root` 写目标项目内的相对路径。 + - 不要把外部 clone 的 `C:/tools/playbook` 这类路径写进 `deploy_root`;那只是你执行脚本的位置。 -当你希望只 vendoring 需要的语言规范(例如只需要 `tsl` + `cpp`)时: + ```toml + [playbook] + project_root = "." + deploy_root = "custom/playbook" -```toml -# playbook.toml -[playbook] -project_root = "/path/to/target-project" + [vendor] + langs = ["tsl"] -[vendor] -langs = ["tsl", "cpp"] -``` + [sync_standards] + langs = ["tsl"] -```bash -python scripts/playbook.py -config playbook.toml -``` + [sync_rules] -该动作仅生成裁剪快照,不会隐式同步 `.agents/` 或 `.gitattributes`;后续请用 `sync_standards` 明确落地。 + [sync_memory_bank] + project_name = "MyProject" + ``` + +3. 在目标项目根执行外部 clone 里的统一入口: + + ```bash + python C:/tools/playbook/scripts/playbook.py -config playbook.toml + ``` + +说明: + +- 这里的 `[vendor]` 是“把 Playbook 快照部署进目标项目”的执行步骤,不是第三种正式部署路线。 +- `deploy_root` 永远表示目标项目内的部署目录;它不是外部 clone 出来的 Playbook 仓库路径。 +- 外部 clone 场景下必须显式填写 `deploy_root`;脚本不会替你补默认部署目录。 +- 如果 `deploy_root = "custom/playbook"`,部署后的项目内入口会是 `custom/playbook/scripts/playbook.py`、`custom/playbook/docs/index.md`。 --- @@ -320,10 +340,12 @@ python scripts/playbook.py -config playbook.toml │ ├── typescript/ # TypeScript/JavaScript 规则集(同上) │ └── markdown/ # Markdown 规则集(仅代码格式化) ├── .gitattributes # 行尾/文本规范 -├── docs/ -│ ├── standards/ -│ │ └── playbook/ # 本 Playbook 快照(git subtree/vendoring) -│ └── project/ # 项目自有文档(架构、ADR、运行方式等) +├── / # 本 Playbook 在项目内的部署根(默认 docs/standards/playbook) +│ ├── docs/ +│ ├── rulesets/ +│ ├── scripts/ +│ └── templates/ +├── docs/project/ # 项目自有文档(架构、ADR、运行方式等) ├── playbook.toml # 统一入口配置 └── src/ # 源码目录(按项目实际情况) ``` diff --git a/SKILLS.md b/SKILLS.md index 9050e422..888990e0 100644 --- a/SKILLS.md +++ b/SKILLS.md @@ -24,7 +24,7 @@ skills = true ## 2. 本仓库的 skills 目录结构 -本 Playbook 以“可 vendoring”的方式提供 skills: +本 Playbook 以“可分发、可安装”的方式提供 skills: ```txt codex/skills/ @@ -79,13 +79,14 @@ agents_home = "./.agents" > 注意:Codex 默认从 `~/.agents/skills` 加载 skills;使用本地安装时,需要确保 Codex 能发现该路径。 -如果你的项目通过 `git subtree` vendoring 本 Playbook(推荐前缀 -`docs/standards/playbook`),则在目标项目里执行: +如果你的项目已经把本 Playbook 部署到项目内(无论来自 `git subtree`,还是外部 clone 后部署到自定义根目录),则在目标项目里执行: ```bash -python docs/standards/playbook/scripts/playbook.py -config playbook.toml +python /scripts/playbook.py -config playbook.toml ``` +其中 `` 默认为 `docs/standards/playbook`,也可以是 `custom/playbook` 等自定义目录。 + 安装后重启 `codex`,即可在运行时看到 `## Skills` 列表。 --- @@ -129,24 +130,19 @@ python docs/standards/playbook/scripts/playbook.py -config playbook.toml - C++:`docs/cpp/code_style.md`、`docs/cpp/naming.md`、`docs/cpp/toolchain.md` - Python:`docs/python/style_guide.md`、`docs/python/tooling.md`、`docs/python/configuration.md` -若你的项目通过 git subtree 引入本 Playbook,常见路径为 -`docs/standards/playbook/docs/...`;把上述 `docs/` 前缀替换为 -`docs/standards/playbook/docs/` 即可。 +若你的项目把本 Playbook 部署到项目内,文档根路径为 +`/docs/...`;其中 `` 默认为 `docs/standards/playbook`,也可以按项目配置改成 `custom/playbook` 等自定义目录。 --- ## 8. 本 Playbook 原生 skills -位于 `codex/skills/`(Playbook 自维护部分),当前共 4 个。 +位于 `codex/skills/`(Playbook 自维护部分),当前共 3 个。 第三方 skills 来源见第 9 节。 ### 语言特定 Skills -- **`tsl-guide`**:TSL/TSF 语法与编码完整指南 - - 渐进式教学体系:基础语法 → 高级特性 → 函数库 → 最佳实践 - - 包含 4 个子文档:primer.md / advanced.md / functions_index.md / common_patterns.md - - 总计约 1000 行,按需加载 - - 触发词:TSL 语法, 写 TSL, TSL 函数, TSL class, 矩阵操作, TS-SQL 等 +当前仓库不再内置语言特定 skill;TSL 相关问题请直接查阅 `rulesets/tsl/index.md` 与 `docs/tsl/`。 ### 通用工作流 Skills diff --git a/data/tsl_reference_catalog_source/README.md b/data/tsl_reference_catalog_source/README.md new file mode 100644 index 00000000..c70293fd --- /dev/null +++ b/data/tsl_reference_catalog_source/README.md @@ -0,0 +1,14 @@ +# TSL Reference Catalog Source + +这里存放 `docs/tsl/reference/catalog/` 的脚本输入源。 + +## 用途 + +- 供 [`scripts/build_tsl_reference_catalog.ps1`](../../scripts/build_tsl_reference_catalog.ps1) 读取并生成 canonical 函数目录页。 +- 保留按模块拆分后的 TSL 函数原始说明,避免脚本依赖 `archive/`。 + +## 边界 + +- 这里不是 AI 新 session 的默认阅读入口。 +- 这里不是 canonical 语法或函数手册,正式入口仍是 [`docs/tsl/reference/index.md`](../../docs/tsl/reference/index.md)。 +- 这里的内容来自历史函数语料拆分结果,主要服务于目录生成与人工回查。 diff --git a/data/tsl_reference_catalog_source/base.md b/data/tsl_reference_catalog_source/base.md new file mode 100644 index 00000000..0aa98a01 --- /dev/null +++ b/data/tsl_reference_catalog_source/base.md @@ -0,0 +1,11065 @@ +#### 基础函数 + +##### 内容 + +- 数字 +- 日期时间 +- 字符串 +- 数组 + +##### 数字 + +###### 内容 + +- FloatN +- FloatToStrEx +- FormatFloatExt +- WebZero +- RoundTo5 +- SimpleRoundTo2 +- DivValue +- Dataisequal + +###### FloatN + +用途:将浮点数按指定小数位数四舍五入。 +参数:value 为输入数值;digits 为保留的小数位数。 +返回:数值。 + +范例 + +```tsl +return FloatN(12.6578, 2); +// 结果:12.66 +``` + +###### FloatToStrEx + +用途:将浮点数格式化为字符串,保留指定小数位数。 +参数:value 为输入数值;digits 为保留的小数位数。 +返回:字符串。 + +范例 + +```tsl +return FloatToStrEx(12.6578, 2); +// 结果:’ 12.66’ +``` + +###### FormatFloatExt + +用途:按扩展格式输出数值字符串,支持千分位与空值处理。 +参数:value 为输入数值;format 为格式参数(可选)。 +返回:字符串。 + +范例 + +```tsl +return FormatFloatExt(12345.67, 1); +// 结果:’ 12,345.67’ + +return FormatFloatExt("123"); +// 结果:’ -’ +``` + +###### WebZero + +用途:当数值为 0 时返回空字符串,否则返回数值字符串。 +参数:value 为输入数值。 +返回:字符串。 + +范例 + +```tsl +return WebZero(0); +// 结果:’’ // 空字串 +``` + +###### RoundTo5 + +用途:将数值按 0.5 的步长进行四舍五入。 +参数:value 为输入数值。 +返回:数值。 + +范例 + +```tsl +return RoundTo5(0.35); +// 结果:0.5 +``` + +###### SimpleRoundTo2 + +用途:按指定小数位数进行四舍五入(对负数同样生效)。 +参数:value 为输入数值;digits 为保留的小数位数。 +返回:数值。 + +范例 + +范例01: + +```tsl +return SimpleRoundTo2(1234.56789654, -2); +// 结果:1234.57 +``` + +范例02: + +```tsl +return SimpleRoundTo2(-1234.5658965, -2); +// 结果:-1234.56 +``` + +###### DivValue + +用途:当除数不为 0 时返回 v1 / v2,否则返回 0。 +参数:v1 为被除数;v2 为除数。 +返回:数值。 + +算法如果v2不为0,则返回v1/v2,否则返回0。范例 + +```tsl +return DivValue(8, 2); +// 返回:4 +``` + +###### Dataisequal + +用途:判断两个数据是否相等。 +参数:a 与 b 为待比较的数据。 +返回:布尔值。 + +##### 日期时间 + +###### 内容 + +- ISO8601 +- GMT时间 +- 常用日期时间函数 +- 简单转换函数 +- 普通日期函数 +- 分解函数 +- 起始结束函数 +- 关系函数 +- 范围判定函数 +- 范围获得函数 +- 范围生成函数 +- 时间推移函数 +- 组合、分解日期函数 +- 日期重组函数 +- 日期格式的转换 +- 宽字节日期格式转换函数 + +###### ISO8601 + +标有ISO8601标准的函数的含义包括以下几点: + +1、对于某一周属于某年(或某月)的认定标准是是否有四天以上属于某年(或某月)。例如,对于某年第一周的认定是此年的第一个星期四所在的周。这保证了这个周至少有4天在这个年份中。 + +这同时意味着一年总的周数必然是52或53。 + +2、一周的开始是星期一,结束是星期天。分别用1到7的数字表示。 + +###### GMT时间 + +GMT时间就是英国格林威治时间,也就是世界标准时间,是本初子午线上的地方时,是0时区的区时,与我国的标准时间北京时间(东八区)相差8小时,即晚8小时。 + +当GMT时间为00:00:00时,北京时间为8:00:00。 + +###### 常用日期时间函数 + +####### 内容 + +- Time +- DecodeTime +- DayOfWeek +- EncodeTime +- Now +- DecodeDate +- Date +- TryEncodeDate +- TryEncodeTime +- DecodeDateFully +- EncodeDate +- TryStrToDate +- StrToDateTimeDef +- DateTimeToInternetStr +- IncAMonth +- StrToTime +- CurrentYear +- TryStrToTime +- StrToDate +- DateTimeGMTToHttpStr +- DateToStr +- StrToTimeDef +- DateTimeToStr +- DateTimeToString +- Strtodatetime2 +- FormatDateTime +- DateTimeGMTToCookieStr +- StrToDateTime +- IsLeapYear +- GMTToLocalDateTime +- TimeToStr +- StrToDateDef +- TryStrToDateTime + +####### Time + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +return Time(); // 输出0.59 +``` + +参考TDateTime + +####### DecodeTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DecodeTime(strtoTime("13:33:45.500"), hour, min, sec, msec); +return array(hour, min, sec, msec); +// 返回 array(13,33,45,500) +``` + +参考TDateTime EncodeDate EncodeTime TryEncodeDate TryEncodeTime DecodeDateFully +DecodeDate + +####### DayOfWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +dow := DayOfWeek(EncodeDate(2011, 8, 8)); +return dow; // 输出:2 +``` + +参考TDateTime + +####### EncodeTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Time1 := EncodeTime(12, 35, 35, 100); +return time1; // 输出:0.52471(12:35:35.1) +``` + +参考TDateTime EncodeDate TryEncodeDate TryEncodeTime DecodeTime DecodeDate +DecodeDateFully + +####### Now + +用途:日期时间相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return Now(); // 输出40763.59 +``` + +参考TDateTime + +####### DecodeDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DecodeDate(inttodate(20140115), year, month, day); +return array(year, month, day ); +// 输出array(2014,1,15) +``` + +参考TDateTime EncodeDate DecodeTime DecodeDateFully EncodeTime TryEncodeDate +TryEncodeTime + +####### Date + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +// 当前的日期 +return Date(); // 输出41656 +``` + +参考TDateTime + +####### TryEncodeDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +if TryEncodeDate(2011, 12, 25, date) then return date; // 输出:40902 +else return "encode error"; +// 输出 encode error + +if TryEncodeDate(2011, 12, 32, date) then return date +else return "encode error"; +// 输出 encode error +``` + +参考TDateTime EncodeDate TryEncodeTime DecodeTime DecodeDate DecodeDateFully +EncodeTime + +####### TryEncodeTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +if TryEncodeTime(12, 20, 30, 200, time) then return time//输出:0.51 +else return "eccode error "; +``` + +参考TDateTime EncodeDate DecodeTime DecodeDate DecodeDateFully EncodeTime +TryEncodeDate + +####### DecodeDateFully + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Flag := DecodeDateFully(inttodate(20140115), year, month, day, dow); +fname := ifthen(1, '闰年', '平年'); +return array(year, month, day, dow, fname); +// 返回:array(2014,1,15,4,'闰年') +``` + +参考TDateTime EncodeDate DecodeTime EncodeTime TryEncodeDate TryEncodeTime +DecodeDate + +####### EncodeDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +date := EncodeDate(2011, 8, 6); +return date; // 输出:40761 +``` + +参考TDateTime EncodeTime TryEncodeDate TryEncodeTime DecodeDate DecodeDateFully +DecodeTime + +####### TryStrToDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +if TryStrToDate("2010-02-04 ", date) then return date; // 输出40213 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### StrToDateTimeDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToDateTimeDef("2011-08-08 16:61:16 ", now()); // 输出当前系统日期时间 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### DateTimeToInternetStr + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := strtodatetime('2014-01-01 10:00:00'); +datetime := DateTimeToInternetStr(EndT, 0); +return datetime; // 输出Wed, 1 Jan 2014 10:00:00 +0800 +``` + +####### IncAMonth + +范例 + +```tsl +year := 2011; +month := 8; +day := 8; +IncAmonth(year, month, day, 4); +return EncodeDate(year, month, day); // 输出40885 +``` + +####### StrToTime + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToTime("15:20:34"); // 输出0.64 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### CurrentYear + +用途:日期时间相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return CurrentYear(); // 输出2011 +``` + +####### TryStrToTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +if TryStrToTime("15:52:35", time) then return time; // 输出0.66 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### StrToDate + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToDate("2010-02-04"); // 输出40213 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### DateTimeGMTToHttpStr + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := strtodatetime('2014-01-01 10:00:00'); +datetime := DateTimeGMTToHttpStr(EndT); +return datetime; // 输出:Wed, 01 Jan 2014 10:00:00 GMT +``` + +####### DateToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +EndT := inttodate(20140117); +return DateToStr(EndT); // 输出 2014-01-17 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### StrToTimeDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +time := StrToTimeDef("15:61:34 ", time()); +return time; // 输出当前系统时间 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### DateTimeToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +EndT := now(); +return DateTimeToStr(EndT); // 输出当前系统日期时间 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### DateTimeToString + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +DateTimeToString(result, 'YYYY-MM-DD HH:NN:SS', now()); +return result; // 输出当期系统日期时间 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +差异说明在不同操作系统中,返回的日期格式会有所差异,差异同FormaTDateTime,FAQ:FormatDateTime + +####### Strtodatetime2 + +范例 + +```tsl +// 字符串2021-8-12 10:31:24:199 转换为日期时间格式(包含毫秒) +s := "2021-8-12 10:31:24:199" +return StrToDateTime2(s); // 结果:44420.4384745255 +``` + +####### FormatDateTime + +用途:按指定格式输出结果。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return FormatDateTime("C", now()); // 输出2011-08-08 16:27:08 +return FormatDateTime("Dddddd", now()); // 输出2011年8月8日 +``` + +参考SetFormatLocalCode GetFormatLocalCode + +差异说明其转换结果依赖运行环境的操作系统的日期时间格式,如表示星期时,有些操作系统上表示方式为“周五”,而有些操作系统上表示为“五”。 + +####### DateTimeGMTToCookieStr + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := strtodatetime('2014-01-01 10:00:00'); +datetime := DateTimeGMTToCookieStr(EndT); +return datetime; // 输出Wed, 01-Jan-2014 10:00:00 GMT +``` + +####### StrToDateTime + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToDateTime("2011-08-08 16:00:16 "); // 输出40763.67 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### IsLeapYear + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +return IsLeapYear(2000); // 输出1 +return IsLeapYear(2011); // 输出0 +``` + +参考IsInLeapYear + +####### GMTToLocalDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +GMT := "Wed, 01 Jan 2014 10:00:00 GMT "; +datetime := GMTToLocalDateTime(GMT); +return datetime; // 输出:41640.75 (时间为2014-01-01 18:00:00) +``` + +####### TimeToStr + +范例 + +```tsl +// 输入时间或者日期时间 +return timeToStr(0.5); +return timetostr(now()); +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### StrToDateDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToDateDef("2010-02-30", date()); // 转换失败输出当前日期40763 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +####### TryStrToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +if TryStrToDateTime("2010-02-04 16:11:35 ", datetime) then return datetime; // 输出40213.67 +``` + +参考TDateTime SetFormatLocalCode GetFormatLocalCode + +###### 简单转换函数 + +####### 内容 + +- DateToInt +- IntToDate +- StrToDateExt +- ExcelIntToDate +- ExcelDateToInt +- FormatStrToDateTime2 + +####### DateToInt + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DateTime := 40559; +return DateToInt(DateTime); +// 结果:20110116 +``` + +####### IntToDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Rdate := 20110116; +return IntToDate(Rdate); +// 结果: 40559 +``` + +####### StrToDateExt + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +S := '16/1/2011'; +StrFormat := 0; +return StrToDateExt(S, StrFormat); +// 结果:40559 +``` + +####### ExcelIntToDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +// 报告期为2010年年报 +RDate := 20101231; +return ExcelIntToDate(RDate); +// 结果:40543 +``` + +####### ExcelDateToInt + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +RDate := 20101231; +return ExcelDateToInt(RDate); +// 结果:20101231 +``` + +####### FormatStrToDateTime2 + +用途:按指定格式输出结果。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +// 字符串2021-8-12 10:31:24:199 转换为日期时间格式(包含毫秒) +s := "2021.01.04T23:00:00.000"; +FormatStr := "yyyy.mm.ddThh:nn:ss.zzz"; +return FormatStrToDateTime2(S, FormatStr); // 结果:44200.9583333333 +``` + +###### 普通日期函数 + +####### 内容 + +- IsInLeapYear +- IsPM +- IsValidDate +- IsValidTime +- IsValidDateTime +- IsValidDateDay +- IsValidDateWeek +- IsValidDateMonthWeek +- WeeksInYear +- WeeksInAYear +- DaysInYear +- DaysInAYear +- DaysInMonth +- DaysInAMonth +- Today +- Yesterday +- Tomorrow +- IsToday +- IsSameDay + +####### IsInLeapYear + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsInLeapYear(date) then return "this year is a leap year " +else return "this year is not a leap year "; +``` + +参考TDateTime IsLeapYear + +####### IsPM + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsPM(Time()) then return "is PM " +else return "is AM "; +``` + +参考TDateTime + +####### IsValidDate + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidDate(2011, 8, 34) then return "right " +else return "wrong "; +// 输出 wrong +``` + +参考IsValidTime IsValidDateTime IsValidDateDay IsValidDateWeek +IsValidDateMonthWeek + +####### IsValidTime + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidTime(17, 48, 45, 678) then return "right time " +else return "wrong time "; // 输出 right time +``` + +参考IsValidDate IsValidDateTime IsValidDateDay IsValidDateWeek +IsValidDateMonthWeek + +####### IsValidDateTime + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidDateTime(2011, 8, 8, 17, 57, 56, 245) then return "right " +else return "wrong "; +// 输出 right +``` + +参考IsValidDate IsValidTime IsValidDateDay IsValidDateWeek IsValidDateMonthWeek + +####### IsValidDateDay + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidDateDay(2010, 345) then return "valid " +else return "not valid "; +// 输出 valid +``` + +参考IsValidDate IsValidTime IsValidDateTime IsValidDateWeek IsValidDateMonthWeek + +####### IsValidDateWeek + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidDateWeek (2010, 15, 4) then return "valid " +else return "not valid "; +// 输出 valid +``` + +参考IsValidDate IsValidTime IsValidDateTime IsValidDateDay IsValidDateMonthWeek + +####### IsValidDateMonthWeek + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +if IsValidDateMonthWeek(2000, 10, 2, 3) then return "valid " +else return "not valid "; +``` + +输出 valid参考IsValidDate IsValidTime IsValidDateTime IsValidDateDay +IsValidDateWeek + +####### WeeksInYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +num := WeeksInYear (Date()); +return num; // 输出52 +``` + +参考TDateTime WeeksInAYear DaysInYear DaysInAYear DaysInMonth DaysInAMonth + +####### WeeksInAYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +num := WeeksInAYear (2010); +return num; // 输出52 +``` + +参考WeeksInYear DaysInYear DaysInAYear DaysInMonth DaysInAMonth + +####### DaysInYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +days := DaysInYear (Date()); +return days; // 输出365 +``` + +参考TDateTime WeeksInYear WeeksInAYear DaysInAYear DaysInMonth DaysInAMonth + +####### DaysInAYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +days := DaysInAYear (2010); +return days; // 输出365 +``` + +参考WeeksInYear WeeksInAYear DaysInYear DaysInMonth DaysInAMonth + +####### DaysInMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +days := DaysInMonth (inttodate(20131201)); +return days; // 输出31 +``` + +参考TDateTime WeeksInYear WeeksInAYear DaysInYear DaysInAYear DaysInAMonth + +####### DaysInAMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +days := DaysInAMonth (2010, 2); +return days; // 输出28 +``` + +参考WeeksInYear WeeksInAYear DaysInYear DaysInAYear DaysInMonth + +####### Today + +用途:日期时间相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +datetime := Today(); +return DateToStr(datetime); // 输出2011-08-08 +``` + +参考TDateTime Yesterday Tomorrow + +####### Yesterday + +用途:日期时间相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +Datetime := Yesterday(); +return DateToStr(datetime); // 输出2011-08-07 +``` + +参考TDateTime Today Tomorrow + +####### Tomorrow + +用途:日期时间相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +Datetime := Tomorrow(); +return DateToStr(datetime); // 输出2011-08-09 +``` + +参考TDateTime Today Yesterday + +####### IsToday + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +Today := today(); +Aday := today + 2; +if istoday(aday) then return "aday is today " +else return "aday is not today "; // 输出aday is not today +``` + +参考TDateTime + +####### IsSameDay + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +Today := today(); +Aday := today + 2; +if isSameDay(aday, today) then return "sameday " +else return " not sam day"; // 输出:not sameday +``` + +参考TDateTime + +###### 分解函数 + +####### 内容 + +- DateOf +- TimeOf +- YearOf +- MonthOf +- DayOf +- HourOf +- MinuteOf +- SecondOf +- MilliSecondOf + +####### DateOf + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateOf(now()); // 返回今天的日期 +``` + +参考TDateTime TimeOf DecodeDate + +####### TimeOf + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return TimeOf (now()); // 返回当前所处的时间点 +// 截取某个日期时间的时间点 +EndT := strtodatetime("2014-01-17 10:00:00"); +return TimeOf(EndT); // 返回0.4167 +``` + +参考TDateTime DecodeTime DateOf + +####### YearOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := Yearof(strToDate('2010-08-08')); +return year; +// 输出: 2010 +``` + +参考TDateTime DecodeDate MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf + +####### MonthOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +month := Monthof(strToDate('2010-08-08')); +return month; // 输出: 8 +``` + +参考TDateTime DecodeDate YearOf DayOf HourOf MinuteOf SecondOf MilliSecondOf + +####### DayOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +hour := dayof(strtodatetime('2011-08-08 11:22:06')); +return hour; // 输出: 8 +``` + +参考TDateTime DecodeDate YearOf MonthOf HourOf MinuteOf SecondOf MilliSecondOf + +####### HourOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +hour := hourof(strtodatetime('2011-08-08 11:22:06')); +return hour; // 输出: 11 +``` + +参考TDateTime DecodeDate YearOf MonthOf DayOf MinuteOf SecondOf MilliSecondOf + +####### MinuteOf + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := minuteof(strtodatetime('2011-08-08 11:22:06')); +return minute; // 输出: 22 +``` + +参考TDateTime DecodeDate YearOf MonthOf DayOf HourOf SecondOf MilliSecondOf + +####### SecondOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := secondof(strtodatetime('2011-08-08 11:22:06')); +return second; // 输出: 6 +``` + +参考TDateTime DecodeDate YearOf MonthOf DayOf HourOf MinuteOf MilliSecondOf + +####### MilliSecondOf + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := Millisecondof(StrToDateTime('2011-08-08 11:22:06.990')); +return millisecond; // 输出: 990 +``` + +参考TDateTime DecodeDate YearOf MonthOf DayOf HourOf MinuteOf SecondOf + +###### 起始结束函数 + +####### 内容 + +- StartOfTheYear +- EndOfTheYear +- StartOfAYear +- EndOfAYear +- StartOfTheMonth +- EndOfTheMonth +- StartOfAMonth +- EndOfAMonth +- StartOfTheWeek +- EndOfTheWeek +- StartOfAWeek +- EndOfAWeek +- StartOfTheDay +- EndOfTheDay +- StartOfADay +- EndOfADay +- StartOfTheHalfYear +- StartOfTheQuarter +- EndOfTheQuarter +- EndOfTheHalfYear + +####### StartOfTheYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +dTime := StartOfTheYear(StrToDateTime('2011-08-08 11:22:06.990')); +return dateTimeToStr(dTime); // 输出: 2011-01-01 +``` + +参考TDateTime EndOfTheYear StartOfAYear EndOfAYear StartOfTheMonth EndOfTheMonth +StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek StartOfAWeek EndOfAWeek +StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### EndOfTheYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfTheYear(StrToDateTime('2011-08-08 11:22:06.990')); +return dateTimeToStr(year); // 输出: 2011-12-31 23:59:59 +``` + +参考TDateTime StartOfTheYear StartOfAYear EndOfAYear StartOfTheMonth +EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek StartOfAWeek +EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfAYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := StartOfAYear(2011); +return datetimetostr(year); // 输出: 2011-01-01 +``` + +参考TDateTime StartOfTheYear EndOfTheYear EndOfAYear StartOfTheMonth +EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek StartOfAWeek +EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### EndOfAYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfAYear(2011); +return datetimetostr(year); // 输出: 2011-12-31 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear StartOfTheMonth +EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek StartOfAWeek +EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfTheMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := StartOfTheMonth(strtodatetime('2011-08-08 12:48:22.990')); +return datetimetostr(year); // 输出: 2011-08-01 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear EndOfTheMonth +StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek StartOfAWeek EndOfAWeek +StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### EndOfTheMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfTheMonth(strtodatetime('2011-08-08 12:48:22.990')); +return DatetimeToStr(year); // 输出: 2011-08-31 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek +StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfAMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +tdate := StartOfAMonth(2011, 08); +return dateTimeToStr(tdate); // 输出: 2011-08-01 +``` + +参考TDateTime + +####### EndOfAMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Ttime := EndOfAMonth(2011, 08); +return datetimetostr(Ttime); // 输出: 2011-08-31 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth StartOfTheWeek EndOfTheWeek +StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := StartOfTheWeek(strtodatetime('2011-08-07')); +return datetimetostr(year); // 输出: 2011-08-01 +// 其中2011-08-07是星期天,2011-08-01是星期一 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth EndOfTheWeek +StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### EndOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfTheWeek(strtodatetime('2011-08-01')); +return datetimetostr(year); // 输出: 2011-08-07 23:59:59 +// 其中2011-08-01是星期一,输出结果2011-08-07是星期天 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek EndOfTheWeek +StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfAWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 取当年的第一个完整周 +year := StartOfAWeek(2011, 1, 1); +return datetimetostr(year); // 输出: 2011-01-03 +``` + +范例二: + +```tsl +year := StartOfAWeek(2011, 2, 1); +return datetimetostr(year); // 输出:2011-01-10 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth EndOfAMonth StartOfTheWeek EndOfTheWeek +StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### EndOfAWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +year := EndOfAWeek(2011, 1, 7); +return datetimetostr(year); // 输出: 2011-01-09 23:59:59 +``` + +范例二: + +```tsl +year := EndOfAWeek (2011, 2, 7); +return datetimetostr(year); // 输出:2011-01-16 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek +EndOfTheWeek StartOfAWeek StartOfTheDay EndOfTheDay StartOfADay EndOfADay + +####### StartOfTheDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := StartOfTheDay(strtodatetime('2011-08-08 23:59:59')); +return datetimetostr(year); // 输出: 2011-08-08 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek +EndOfTheWeek StartOfAWeek EndOfAWeek EndOfTheDay StartOfADay EndOfADay + +####### EndOfTheDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfTheDay(strtodatetime('2011-08-08 01:01:10')); +return datetimetostr(year); // 输出: 2011-08-08 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek +EndOfTheWeek StartOfAWeek EndOfAWeek StartOfTheDay StartOfADay EndOfADay + +####### StartOfADay + +范例 + +```tsl +year := StartofADay(2011, 8, 8); +return datetimetostr(year); // 输出: 2011-08-08 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek +EndOfTheWeek StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay EndOfADay + +####### EndOfADay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +year := EndOfADay(2015, 1, 5); +return datetimetostr(year); // 输出: 2015-01-05 23:59:59 +``` + +参考TDateTime StartOfTheYear EndOfTheYear StartOfAYear EndOfAYear +StartOfTheMonth EndOfTheMonth StartOfAMonth EndOfAMonth StartOfTheWeek +EndOfTheWeek StartOfAWeek EndOfAWeek StartOfTheDay EndOfTheDay StartOfADay + +####### StartOfTheHalfYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := 40599; // 40559表示2011年1月16号 +return StartOfTheHalfYear(EndT); +// 结果:40544 //40544表示2011年1月1号 +``` + +####### StartOfTheQuarter + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := 40540; // 40540表示2010年12月28日 +return StartOfTheQuarter (EndT); +// 结果:40452 //40452表示2010年10月1号 +``` + +####### EndOfTheQuarter + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := 40540; // 40540表示2010年12月28日 +return EndOfTheQuarter (EndT); +// 结果:40543 //40543表示2010年12月31号 +``` + +####### EndOfTheHalfYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := 40540; // 40540表示2010年12月28日 +return EndOfTheHalfYear (EndT); +// 结果:40543 //40543表示2010年12月31号 +``` + +###### 关系函数 + +####### 内容 + +- HourOfTheYear +- HourOfTheMonth +- MonthOfTheYear +- MilliSecondOfTheYear +- WeekOfTheYear +- WeekOfTheMonth +- MinuteOfTheYear +- SecondOfTheYear +- DayOfTheYear +- DayOfTheMonth +- SecondOfTheMinute +- HourOfTheWeek +- SecondOfTheMonth +- DayOfTheWeek +- MinuteOfTheDay +- MilliSecondOfTheSecond +- SecondOfTheWeek +- MinuteOfTheMonth +- MinuteOfTheHour +- MinuteOfTheWeek +- MilliSecondOfTheDay +- MilliSecondOfTheMonth +- HourOfTheDay +- MilliSecondOfTheHour +- SecondOfTheHour +- MilliSecondofTheMinute +- SecondOfTheDay +- MilliSecondOfTheWeek + +####### HourOfTheYear + +范例 + +```tsl +hour := HourOfTheYear(strtodatetime('2011-01-03 10:00:00')); +return hour; // 输出: 58 +``` + +参考TDateTime HourOf MonthOfTheYear WeekOfTheYear DayOfTheYear MinuteOfTheYear +SecondOfTheYear MilliSecondOfTheYear + +####### HourOfTheMonth + +范例 + +```tsl +hour := HourOfTheMonth(strtodatetime('2011-01-22 10:00:00')); +return hour; // 输出: 514 +``` + +参考TDateTime HourOf WeekOfTheMonth DayOfTheMonth MinuteOfTheMonth +SecondOfTheMonth MilliSecondOfTheMonth + +####### MonthOfTheYear + +范例 + +```tsl +month := MonthOfTheYear(strtodate('2011-08-08')); +return month; // 输出: 8 +``` + +参考TDateTime MonthOf WeekOfTheYear DayOfTheYear HourOfTheYear MinuteOfTheYear +SecondOfTheYear MilliSecondOfTheYear + +####### MilliSecondOfTheYear + +范例 + +```tsl +millisecond := MilliSecondOfTheYear(strtodatetime('2011-01-03')); +return millisecond; // 输出: 172800000 +``` + +参考TDateTime MilliSecondOf MonthOfTheYear WeekOfTheYear DayOfTheYear +HourOfTheYear MinuteOfTheYear SecondOfTheYear + +####### WeekOfTheYear + +范例 + +```tsl +week := WeekOfTheYear(strtodate('2011-01-03')); +return week; // 输出: 1 +``` + +参考TDateTime MonthOfTheYear DayOfTheYear HourOfTheYear MinuteOfTheYear +SecondOfTheYear MilliSecondOfTheYear + +####### WeekOfTheMonth + +定义1:WeekOfTheMonth(AValue: TDateTime): Integer; + +说明:返回由参数AValue指定的时间是处于当月的第几个周。 + +注意:使用了ISO8601标准,这意味着可能指定的时间所处的周不属于当前月份,那么返回的将是相对与其他月份的周数。如果当月1号是周四及周四之前,则本周会纳入本月,即本周是本月的第一周,如果当月1号是周四之后,比如是周五,则还属于上月的周期内,即为上月的最后一周。 + +参数: + +- AValue:TDateTime类型,日期时间 +- AYear:整数,年,返回值 +- AMonth:整数,月,返回值 + +返回:整数,值域是[1,6] + +范例: + +```tsl +month := weekOfTheMonth(strtodatetime('2011-01-22')); +return month; // 输出: 3 +``` + +定义2:WeekOfTheMonth(AValue: TDateTime; var AYear, AMonth: Integer): Integer; + +说明:返回由参数AValue指定的时间是处于当月的第几个周。 + +注意:使用了ISO8601标准,这意味着可能指定的时间所处的周不属于当前月份,那么返回的将是相对与其他月份的周数,通过参数Ayear,Amonth将所属的年份和月份返回 + +参数: + +- AValue:TDateTime类型,日期时间 +- AYear:整数,年,返回值 +- AMonth:整数,月,返回值 + +返回:整数,值域是[1,6] + +范例: + +```tsl +week := WeekOfTheMonth(strtodatetime('2011-01-22'), 2011, 1); +return week; // 输出: 3 +``` + +参考:TDateTime,DayOfTheMonth,HourOfTheMonth,MinuteOfTheMonth,SecondOfTheMonth,MilliSecondOfTheMonth + +####### MinuteOfTheYear + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := MinuteOfTheYear(strtodatetime('2011-01-03 10:00:00')); +return minute; // 输出: 3480 +``` + +参考TDateTime MinuteOf MonthOfTheYear WeekOfTheYear DayOfTheYear HourOfTheYear +SecondOfTheYear MilliSecondOfTheYear + +####### SecondOfTheYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheYear(strtodatetime('2011-01-03')); +return second; // 输出: 208800 +``` + +参考TDateTime SecondOf MonthOfTheYear WeekOfTheYear DayOfTheYear HourOfTheYear +MinuteOfTheYear MilliSecondOfTheYear + +####### DayOfTheYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +d := DayOfTheYear(strtodate('2011-01-03')); +return d; // 输出: 3 +``` + +参考TDateTime DayOf MonthOfTheYear WeekOfTheYear HourOfTheYear MinuteOfTheYear +SecondOfTheYear MilliSecondOfTheYear + +####### DayOfTheMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +day := DayOfTheMonth(strtodatetime('2011-01-22')); +return day; // 输出: 22 +``` + +参考TDateTime DayOf WeekOfTheMonth HourOfTheMonth MinuteOfTheMonth +SecondOfTheMonth MilliSecondOfTheMonth + +####### SecondOfTheMinute + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheMinute(strtodatetime('2011-01-05 01:30:01')); +return second; // 输出: 1 +``` + +参考TDateTime SecondOf MilliSecondofTheMinute MilliSecondOfTheSecond + +####### HourOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +hour := HourOfTheWeek(strtodatetime('2011-01-05 10:00:00')); +return hour; // 输出: 58 +``` + +参考TDateTime HourOf DayOfTheWeek MinuteOfTheWeek SecondOfTheWeek +MilliSecondOfTheWeek + +####### SecondOfTheMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheMonth(strtodatetime('2011-01-22 10:00:00')); +return second; // 输出: 1850400 +``` + +参考TDateTime SecondOf WeekOfTheMonth DayOfTheMonth HourOfTheMonth +MinuteOfTheMonth MilliSecondOfTheMonth + +####### DayOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Dayofweek := DayOfTheWeek(strtodatetime('2011-01-03')); +return dayofweek; +// 输出: 1 +``` + +参考TDateTime DayOf HourOfTheWeek MinuteOfTheWeek SecondOfTheWeek +MilliSecondOfTheWeek + +####### MinuteOfTheDay + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := MinuteOfTheDay(strtodatetime('2011-01-05 01:22:22')); +return minute; // 输出: 82 +``` + +参考TDateTime MinuteOf HourOfTheDay SecondOfTheDay MilliSecondOfTheDay + +####### MilliSecondOfTheSecond + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondOfTheSecond(strtodatetime('2011-01-05 01:30:01.990')); +return millisecond; // 输出:990 +``` + +参考TDateTime MilliSecondOf MilliSecondofTheMinute + +####### SecondOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheWeek(strtodatetime('2011-01-05 10:00:00')); +return second; // 输出: 208800 +``` + +参考TDateTime SecondOf DayOfTheWeek HourOfTheWeek MinuteOfTheWeek +MilliSecondOfTheWeek + +####### MinuteOfTheMonth + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := MinuteOfTheMonth(strtodatetime('2011-01-22 10:00:00')); +return minute; // 输出: 30840 +``` + +参考TDateTime MinuteOf WeekOfTheMonth DayOfTheMonth HourOfTheMonth +SecondOfTheMonth MilliSecondOfTheMonth + +####### MinuteOfTheHour + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := MinuteOfTheHour(strtodatetime('2011-01-05 01:30:01')); +return minute; // 输出: 30 +``` + +参考TDateTime MinuteOf MinuteOfTheHour SecondOfTheHour MilliSecondOfTheHour + +####### MinuteOfTheWeek + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minute := MinuteOfTheWeek(strtodatetime('2011-01-05 10:00:00')); +return minute; // 输出: 3480 +``` + +参考TDateTime MinuteOf DayOfTheWeek HourOfTheWeek SecondOfTheWeek +MilliSecondOfTheWeek + +####### MilliSecondOfTheDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondOfTheDay(strtodatetime('2011-01-05 01:30:01')); +return millisecond; // 输出: 5401000 +``` + +参考TDateTime MilliSecondOf HourOfTheDay MinuteOfTheDay SecondOfTheDay + +####### MilliSecondOfTheMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondOfTheMonth(strtodatetime('2011-01-22 10:00:00')); +return millisecond; // 输出: 1850400000 +``` + +参考TDateTime MilliSecondOf WeekOfTheMonth DayOfTheMonth HourOfTheMonth +MinuteOfTheMonth SecondOfTheMonth + +####### HourOfTheDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +hour := HourOfTheDay(strtodatetime('2011-01-05 23:22:22')); +return hour; // 输出: 23 +``` + +参考TDateTime HourOf MinuteOfTheDay SecondOfTheDay MilliSecondOfTheDay + +####### MilliSecondOfTheHour + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondOfTheHour(strtodatetime('2011-01-05 01:30:01')); +return millisecond; // 输出: 1801000 +``` + +参考TDateTime MilliSecondOf MinuteOfTheHour SecondOfTheHour + +####### SecondOfTheHour + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheHour(strtodatetime('2011-01-05 01:30:01')); +return second; // 输出: 1801 +``` + +参考TDateTime SecondOf MinuteOfTheHour MilliSecondOfTheHour + +####### MilliSecondofTheMinute + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondofTheMinute(strtodatetime('2011-01-05 01:30:01')); +return millisecond; // 输出: 1000 +``` + +参考TDateTime SecondOf MilliSecondOf MilliSecondOfTheSecond + +####### SecondOfTheDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +second := SecondOfTheDay(strtodatetime('2011-01-05 01:30:01')); +return second; // 输出: 5401 +``` + +参考TDateTime SecondOf HourOfTheDay MinuteOfTheDay MilliSecondOfTheDay + +####### MilliSecondOfTheWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +millisecond := MilliSecondOfTheWeek(strtodatetime('2011-01-05 10:00:00')); +return millisecond; // 输出: 208800000 +``` + +参考TDateTime MilliSecondOf DayOfTheWeek HourOfTheWeek MinuteOfTheWeek +SecondOfTheWeek + +###### 范围判定函数 + +####### 内容 + +- WithinPastYears +- WithinPastMonths +- WithinPastWeeks +- WithinPastDays +- WithinPastHours +- WithinPastMinutes +- WithinPastSeconds +- WithinPastMilliSeconds + +####### WithinPastYears + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 2010年1月5日至2013年1月4日之间,不足3年,因此,判断为2年内 +flag := WithinPastYears(strtodatetime('2010-01-05'), strtodatetime('2013-01-04'), 2); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +// //2010年1月5日至2013年1月5日之间,相隔 3年,因此,判断为不在2年内 +flag := WithinPastYears(strtodatetime('2010-01-05'), strtodatetime('2013-01-05'), 2); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastMonths WithinPastWeeks WithinPastDays WithinPastHours +WithinPastSeconds WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastMonths + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 2011年1月5日到2011年7月6日的天数是182,而天数必须大于182.62(6*30.4375),才能达到6个月,所以,1月5日还属于7月6日前推5个月范围内。 +flag := WithinPastMonths(strtodatetime('2011-01-05'), strtodatetime('2011-07-06'), 5); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +flag := WithinPastMonths(strtodatetime('2011-01-05'), strtodatetime('2011-07-07'), 5); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastWeeks WithinPastDays WithinPastHours +WithinPastSeconds WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastWeeks + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 2011年1月1日至2011年1月28日之间的天数为27天,不足28天(4*7),所以仍在3周内 +flag := WithinPastWeeks(strtodatetime('2011-01-01'), strtodatetime('2011-01-28'), 3); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +// 2011年1月1日至2011年1月28日之间的天数为27天,不足28天(4*7),所以仍在3周内 +flag := WithinPastWeeks(strtodatetime('2011-01-01'), strtodatetime('2011-01-29'), 3); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastDays WithinPastHours +WithinPastSeconds WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastDays + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +flag := WithinPastDays(strtodate('2011-01-01'), strtodate('2011-01-11'), 10); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +flag := WithinPastDays(strtodate('2011-01-01'), strtodate('2011-01-12'), 10); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastWeeks WithinPastHours +WithinPastSeconds WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastHours + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 不足11个小时 +flag := WithinPastHours(strtodatetime('2011-01-01 00:00:00'), strtodatetime('2011-01-01 10:30:00'), 10); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +flag := WithinPastHours(strtodatetime('2011-01-01 00:00:00'), strtodatetime('2011-01-01 11:00:00'), 10); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastWeeks WithinPastDays +WithinPastSeconds WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastMinutes + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +flag := WithinPastMinutes(strtodatetime('2011-01-01 10:00:00'), strtodatetime('2011-01-01 10:10:00'), 10); +return flag; // 输出: 1 + +flag := WithinPastMinutes(strtodatetime('2011-01-01 10:00:00'), strtodatetime('2011-01-01 10:11:00'), 10); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastWeeks WithinPastDays +WithinPastHours WithinPastSeconds WithinPastMilliSeconds + +####### WithinPastSeconds + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +flag := WithinPastSeconds(strtodatetime('2011-01-01 10:00:00'), strtodatetime('2011-01-01 10:00:10'), 10); +return flag; // 输出: 1 +``` + +范例二: + +```tsl +flag := WithinPastSeconds(strtodatetime('2011-01-01 10:00:00'), strtodatetime('2011-01-01 10:00:11'), 10); +return flag; // 输出: 0 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastWeeks WithinPastDays +WithinPastHours WithinPastMinutes WithinPastMilliSeconds + +####### WithinPastMilliSeconds + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +ANow := strtodatetime('2011-01-01 10:00:00.100'); +AThen := strtodatetime('2011-01-01 10:00:00.200'); +flag := WithinPastMilliSeconds(ANow, AThen , 100); +return flag; // 输出: 1 +``` + +参考TDateTime WithinPastYears WithinPastMonths WithinPastWeeks WithinPastDays +WithinPastHours WithinPastSeconds WithinPastMinutes + +###### 范围获得函数 + +####### 内容 + +- YearsBetween +- MonthsBetween +- WeeksBetween +- DaysBetween +- HoursBetween +- MinutesBetween +- SecondsBetween +- MilliSecondsBetween + +####### YearsBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +years := YearsBetween(strtodatetime('2009-01-01 00:00:00'), strtodatetime('2011-01-01 23:59:59.999')); +return years; // 输出: 2 +``` + +参考TDateTime MonthsBetween WeeksBetween DaysBetween HoursBetween MinutesBetween +SecondsBetween MilliSecondsBetween + +####### MonthsBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +months := MonthsBetween(strtodatetime('2011-05-01'), strtodatetime('2011-08-01')); +return months; // 输出: 3 +``` + +参考TDateTime YearsBetween WeeksBetween DaysBetween HoursBetween MinutesBetween +SecondsBetween MilliSecondsBetween + +####### WeeksBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +weeks := WeeksBetween(strtodatetime('2011-05-01'), strtodatetime('2011-08-01')); +return weeks; // 输出: 13 +``` + +参考TDateTime YearsBetween MonthsBetween DaysBetween HoursBetween MinutesBetween +SecondsBetween MilliSecondsBetween + +####### DaysBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +days := DaysBetween(strtodate('2011-05-01'), strtodate('2011-08-01')); +return days; // 输出: 92 +``` + +范例二: + +```tsl +// 不足完整的一天:39815.04167-39814.08333=0.95834 +// 2009-01-01 02:00:00:日期时间为39814.08333 +// 2009-01-02 01:00:00:日期时间为39815.04167 +days := DaysBetween(strtodatetime('2009-01-01 02:00:00'), strtodatetime('2009-01-02 01:00:00')); +return days; // 输出: 0 +``` + +参考TDateTime YearsBetween MonthsBetween WeeksBetween HoursBetween +MinutesBetween SecondsBetween MilliSecondsBetween + +####### HoursBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Hours := HoursBetween(strtodatetime('2011-08-01 00:00:00'), strtodatetime('2011-08-01 12:00:00')); +return hours; // 输出: 12 +``` + +参考TDateTime YearsBetween MonthsBetween WeeksBetween DaysBetween MinutesBetween +SecondsBetween MilliSecondsBetween + +####### MinutesBetween + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +minutes := MinutesBetween(strtodatetime('2011-08-01 00:00:00'), strtodatetime('2011-08-01 12:00:00')); +return minutes; // 输出: 720 +``` + +参考TDateTime YearsBetween MonthsBetween WeeksBetween DaysBetween HoursBetween +SecondsBetween MilliSecondsBetween + +####### SecondsBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +seconds := SecondsBetween(strtodatetime('2011-08-01 00:00:00'), strtodatetime('2011-08-01 12:00:00')); +return seconds; // 输出: 43200 +``` + +参考TDateTime YearsBetween MonthsBetween WeeksBetween DaysBetween HoursBetween +MinutesBetween MilliSecondsBetween + +####### MilliSecondsBetween + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BegT := strtodatetime('2011-08-01 00:00:00'); +EndT := strtodatetime('2011-08-01 12:00:00'); +milliseconds := MilliSecondsBetween(BegT, EndT); +return milliseconds; // 输出: 43200000 +``` + +参考TDateTime YearsBetween MonthsBetween WeeksBetween DaysBetween HoursBetween +MinutesBetween SecondsBetween + +###### 范围生成函数 + +####### 内容 + +- YearSpan +- MonthSpan +- WeekSpan +- DaySpan +- HourSpan +- MinuteSpan +- SecondSpan +- MilliSecondSpan + +####### YearSpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +years := YearSpan(strtodatetime('2010-08-01 00:00:00'), strtodatetime('2012-08-01 12:00:00')); +return years; // 输出: 2.00274 +``` + +参考TDateTime MonthSpan WeekSpan DaySpan HourSpan MinuteSpan SecondSpan +MilliSecondSpan + +####### MonthSpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +months := MonthSpan(strtodatetime('2010-08-01 00:00:00'), strtodatetime('2012-08-01 12:00:00')); +return months; // 输出: 24.03 +``` + +参考TDateTime YearSpan WeekSpan DaySpan HourSpan MinuteSpan SecondSpan +MilliSecondSpan + +####### WeekSpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BegT := strtodatetime('2010-08-01 00:00:00'); +EndT := strtodatetime ('2012-08-01 12:00:00'); +weeks := WeekSpan(BegT, EndT); +return weeks; // 输出: 104.5 +``` + +参考TDateTime YearSpan MonthSpan DaySpan HourSpan MinuteSpan SecondSpan +MilliSecondSpan + +####### DaySpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BegT := strtodatetime('2010-08-01 00:00:00'); +EndT := strtodatetime('2012-08-01 12:00:00'); +days := DaySpan(BegT, EndT); +return days; // 输出: 731.5 +``` + +参考TDateTime YearSpan MonthSpan WeekSpan HourSpan MinuteSpan SecondSpan +MilliSecondSpan + +####### HourSpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +hours := HourSpan(strtodatetime('2010-08-01 00:00:00'), strtodatetime('2012-08-01 12:00:00')); +return hours; // 输出: 17556 +``` + +参考TDateTime YearSpan MonthSpan WeekSpan DaySpan MinuteSpan SecondSpan +MilliSecondSpan + +####### MinuteSpan + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BegT := strtodatetime('2010-08-01 00:00:00'); +EndT := strtodatetime('2012-08-01 12:00:00'); +minutes := MinuteSpan(BegT, EndT); +return minutes; // 输出: 1053360 +``` + +参考TDateTime YearSpan MonthSpan WeekSpan DaySpan HourSpan SecondSpan +MilliSecondSpan + +####### SecondSpan + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BegT := strtodatetime('2010-08-01 00:00:00'); +EndT := strtodatetime('2012-08-01 12:00:00'); +seconds := SecondSpan(BegT, EndT); +return seconds; // 输出: 63201600 +``` + +参考TDateTime YearSpan MonthSpan WeekSpan DaySpan HourSpan MinuteSpan +MilliSecondSpan + +####### MilliSecondSpan + +范例 + +```tsl +BegT := strtodatetime('2010-08-01 00:00:00'); +EndT := strtodatetime('2012-08-01 12:00:00'); +milliseconds := SecondSpan(BegT, EndT); +return milliseconds; // 输出: 63201600000 +``` + +参考TDateTime YearSpan MonthSpan WeekSpan DaySpan HourSpan MinuteSpan SecondSpan + +###### 时间推移函数 + +####### 内容 + +- IncYear +- IncHalfYear +- IncQuarter +- IncMonth +- IncWeek +- IncDay +- IncHour +- IncMinute +- IncSecond +- IncMilliSecond + +####### IncYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incyears := IncYear(strtodatetime('2010-08-01'), 10); +return datetostr(incyears); // 输出: 2020-08-01 +``` + +参考TDateTime + +####### IncHalfYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Avalue := 40179; // 40179表示2010年1月1号 +Number := 2; +return IncHalfYear(AValue, Number); +// 结果:40544 //40544表示2011年1月1号 +``` + +####### IncQuarter + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Avalue := 40179; // 40179表示2010年1月1号 +Number := 2; +return IncQuarter(AValue, Number); +// 结果:40360 //40360表示2010年7月1号 +``` + +####### IncMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incmonths := IncMonth(strtodatetime('2010-08-01'), 2); +return datetostr(incmonths); // 输出: 2010-10-01 +``` + +参考TDateTime + +####### IncWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incweeks := IncWeek(strtodatetime('2010-08-01'), 1); +return datetostr(incweeks); // 输出: 2010-08-08 +``` + +参考TDateTime + +####### IncDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incdays := IncDay(strtodatetime('2010-08-01'), 10); +return datetostr(incdays); // 输出: 2010-08-11 +``` + +参考TDateTime + +####### IncHour + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +inchours := IncHour(strtodatetime('2010-08-01 00:01:01'), 10); +return datetimetostr(inchours); // 输出: 2010-08-01 10:01:01 +``` + +参考TDateTime + +####### IncMinute + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incminutes := IncMinute(strtodatetime('2010-08-01 00:01:01'), 50); +return datetimetostr(incminutes); // 输出: 2010-08-01 00:51:01 +``` + +参考TDateTime + +####### IncSecond + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incseconds := IncSecond(strtodatetime('2010-08-01 00:01:01'), 50); +return datetimetostr(incseconds); // 输出: 2010-08-01 00:01:51 +``` + +参考TDateTime + +####### IncMilliSecond + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +incmilliseconds := IncMilliSecond(strtodatetime('2010-08-01 00:01:01.950'), 50); +return datetimetostr(incmilliseconds); // 输出: 2010-08-01 00:01:02 +``` + +参考TDateTime + +###### 组合、分解日期函数 + +####### 内容 + +- EncodeDateTime +- DecodeDateTime +- EncodeDateWeek +- DecodeDateWeek +- DecodeDateDay +- EncodeDateMonthWeek +- DecodeDateMonthWeek +- TryEncodeDateTime +- TryEncodeDateWeek +- TryEncodeDateDay +- TryEncodeDateMonthWeek + +####### EncodeDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +timeset := EncodeDateTime(2011, 08, 08, 09, 32, 45, 990); +return datetimetostr(timeset); // 输出: 2011-08-08 09:32:45 +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +DecodeDateTime EncodeDateWeek DecodeDateWeek DecodeDateDay EncodeDateMonthWeek +DecodeDateMonthWeek + +####### DecodeDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := strtodatetime('2011-08-08 12:09:10.990'); +DecodeDateTime(EndT, year, month, day, hour, minute, second, millisecond); +return array(year, month, day, hour, minute, second, millisecond); +// 输出:array(2011,8,8,12,9,10,990) +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime EncodeDateWeek DecodeDateWeek DecodeDateDay EncodeDateMonthWeek +DecodeDateMonthWeek + +####### EncodeDateWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +// 一个自然周至少要有4天属于该年的日期,这一周才属于这年。 +// 1月1日和1月2日所属周只有2天处于2011年,所以,这周属于2010年,2011年的第一周从2011年1月3日算起 +week := EncodeDateWeek(2011, 1, 1); +return datetostr(week); +// 输出: 2011-01-03 +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime DecodeDateTime DecodeDateWeek DecodeDateDay EncodeDateMonthWeek +DecodeDateMonthWeek + +####### DecodeDateWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DecodeDateWeek(strtodatetime('2011-08-08'), year, weekofyear, dayofweek); +return array( year, weekofyear, dayofweek); +// 输出: array(2011, 32,1) +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime DecodeDateTime EncodeDateWeek DecodeDateDay EncodeDateMonthWeek +DecodeDateMonthWeek + +####### DecodeDateDay + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DecodeDateDay(strtodatetime('2011-08-08'), year, dayofyear); +return array(year, dayofyear); +// 输出: array(2011,220) +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime DecodeDateTime EncodeDateWeek DecodeDateWeek EncodeDateMonthWeek +DecodeDateMonthWeek + +####### EncodeDateMonthWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +monthweek := EncodeDateMonthWeek(2011, 8, 2, 1); +return datetimetostr(monthweek); // 输出: 2011-08-08 +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime DecodeDateTime EncodeDateWeek DecodeDateWeek DecodeDateDay +DecodeDateMonthWeek + +####### DecodeDateMonthWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +DecodeDateMonthWeek(strtoDatetime("2011-08-10"), year, month, weekofMonth, dayOfWeek1); +return array(year, month, weekofMonth, dayOfWeek1); // 输出: array(2011,8,2,3) +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +EncodeDateTime DecodeDateTime EncodeDateWeek DecodeDateWeek DecodeDateDay +EncodeDateMonthWeek + +####### TryEncodeDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Flag := TryEncodeDateTime(2011, 8, 10, 10, 01, 01, 999, Atime); +return array(flag, datetimetostr(Atime)); // 输出: array(1,'2011-08-10 10:01:01') +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +TryEncodeDateWeek TryEncodeDateDay TryEncodeDateMonthWeek + +####### TryEncodeDateWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Flag := TryEncodeDateWeek(2011, 1, Atime, 1); +return array(flag, datetimetostr(Atime)); // 输出: array(1,'2011-01-03') +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +TryEncodeDateTime TryEncodeDateDay TryEncodeDateMonthWeek + +####### TryEncodeDateDay + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Flag := TryEncodeDateDay(2011, 1, Atime); +return array(flag, datetimetostr(Atime)); // 输出: array(1,'2011-01-01') +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +TryEncodeDateTime TryEncodeDateWeek TryEncodeDateMonthWeek + +####### TryEncodeDateMonthWeek + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +Flag := TryEncodeDateMonthWeek(2011, 1, 1, 1, Atime); +return array(flag, datetimetostr(Atime)); // 输出: array(1,'2011-01-03') +``` + +参考TDateTime YearOf MonthOf DayOf HourOf MinuteOf SecondOf MilliSecondOf +TryEncodeDateTime TryEncodeDateWeek TryEncodeDateDay + +###### 日期重组函数 + +####### 内容 + +- RecodeYear +- RecodeMonth +- RecodeDay +- RecodeHour +- RecodeMinute +- RecodeSecond +- RecodeMilliSecond +- RecodeDate +- RecodeTime +- RecodeDateTime +- TryRecodeDateTime +- CompareDateTime +- SameDateTime +- CompareDate +- SameDate +- CompareTime +- SameTime +- NthDayOfWeek +- DecodeDayOfWeekInMonth +- EncodeDayOfWeekInMonth +- TryEncodeDayOfWeekInMonth + +####### RecodeYear + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +newTime := RecodeYear(strtoDatetime("2010-08-01"), 2009); +return datetimetostr(newTime); // 输出: 2009-08-01 +``` + +范例二: + +```tsl +// 用try...except...end语句进行异常处理,如果无法替换成有效的日期,则把NewTime设置为0. +try + newTime := RecodeYear(strtoDatetime("2012-02-29"), 2013); +except + newTime := 0; +end; +return newTime; // 输出: 0 +``` + +参考TDateTime + +####### RecodeMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +try + newTime := RecodeMonth(strtodatetime("2011-08-10"), 10); + newTime := datetimetostr(newTime); +except + newTime := 0; +end; +return newTime; // 输出: 2011-10-10 +``` + +范例二: + +```tsl +try + newTime := RecodeMonth(strtodatetime("2013-3-31"), 4); + newTime := datetimetostr(newTime); +except + newTime := 0; +end; +return newTime; // 输出: 0 +``` + +参考TDateTime + +####### RecodeDay + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +try + newTime := RecodeDay(strtodatetime("2011-08-10"), 1); + newTime := datetostr(newTime); +except + newTime := 0; +end; +return newTime; // 输出: 2011-08-01 +``` + +范例二: + +```tsl +try + newTime := RecodeDay(strtodatetime("2011-02-28"), 31); + newTime := datetostr(newTime); +except + newTime := 0; +end; +return newTime; // 输出: 0 +``` + +参考TDateTime + +####### RecodeHour + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +newTime := RecodeHour(strtodatetime("2011-08-10 12:12:12"), 1); +return datetimetostr(newTime); // 输出: 2011-08-10 01:12:12 +``` + +参考TDateTime + +####### RecodeMinute + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +newTime := RecodeMinute (strtodatetime("2011-08-10 12:12:12"), 9); +return datetimetostr(newTime); // 输出: 2011-08-10 12:09:12 +``` + +参考TDateTime + +####### RecodeSecond + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +newTime := RecodeSecond(strtodatetime("2011-08-10 12:12:12"), 9); +return datetimetostr(newTime); // 输出: 2011-08-10 12:12:09 +``` + +参考TDateTime + +####### RecodeMilliSecond + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +newTime := RecodeMilliSecond(strtodatetime("2011-08-10 12:12:12.999"), 100); +return MilliSecondOf (newTime); // 输出: 100 +``` + +参考TDateTime + +####### RecodeDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +newTime := RecodeDate(strtodatetime("2011-08-10 12:12:12"), 2010, 8, 9); +return datetimetostr(newTime); // 输出: 2010-08-09 12:12:12 +``` + +参考TDateTime + +####### RecodeTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +newTime := RecodeTime(strtodatetime("2011-08-10 12:12:12.999"), 10, 8, 9, 100); +return datetimetostr(newTime); // 输出: 2011-08-10 10:08:09 +``` + +参考TDateTime + +####### RecodeDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +newTime := RecodeDateTime(strtodatetime("2011-08-10 12:12:12.999"), 2010, 8, 10, 10, 8, 9, 100); +return datetimetostr(newTime); // 输出: 2010-08-10 10:08:09 +``` + +参考TDateTime + +####### TryRecodeDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +TryRecodeDateTime(strtodatetime("2011-08-10 12:12:12.999"), 2010, 8, 10, 10, 8, 9, 100, Aresult); +return datetimetostr(Aresult); // 输出: 2010-08-10 10:08:09 +``` + +参考TDateTime + +####### CompareDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +result := CompareDateTime(strtodatetime("2011-08-10"), strtodatetime("2011-08-11")); +return result; // 输出: -1 +``` + +参考TDateTime + +####### SameDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +flag := SameDateTime(strtodatetime("2011-08-10"), strtodatetime("2011-08-11")); +return flag; // 输出: 0 +``` + +参考TDateTime + +####### CompareDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +result := CompareDate(strtodatetime("2011-08-10"), strtodatetime("2011-08-11")); +return result; // 输出: -1 +``` + +参考TDateTime + +####### SameDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +flag := SameDate(strtodatetime("2011-08-1001:00:00"), strtodatetime("2011-08-1002:00:00")); +return flag; // 输出: 1 +``` + +参考TDateTime + +####### CompareTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +result := CompareTime(strtodatetime("2011-08-10 01:00:00"), strtodatetime("2011-08-11 01:00:00")); +return result; // 输出: 0 +``` + +参考TDateTime + +####### SameTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +result := SameTime(strtodatetime("2011-08-10 01:00:00"), strtodatetime("2011-08-11 01:00:00")); +return result; // 输出: 1 +``` + +参考TDateTime + +####### NthDayOfWeek + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := strtodatetime("2014-01-06"); +weekNum := NthDayOfWeek(EndT); +WOFM := WeekOfTheMonth(EndT); +return array(weekNum, WOFM); // 输出: array(1,2) +``` + +参考TDateTime + +####### DecodeDayOfWeekInMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +EndT := strtodatetime("2011-08-10 12:10:09"); +DecodeDayOfWeekInMonth(endt, Ayear, Amonth, ANthDayOfWeek, ADayOfWeek); +return array(Ayear, Amonth, ANthDayOfWeek, ADayOfWeek ); +// 输出: array(2011,8,2,3) +``` + +参考TDateTime + +####### EncodeDayOfWeekInMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 2013年10月1日是周二,1日至6日不属于这个月的周,从7日(周一)所属周开始算起 +return EncodeDayOfWeekInMonth(2013, 10, 2, 1); // 输出41561('2013-10-14') +``` + +参考TDateTime + +####### TryEncodeDayOfWeekInMonth + +用途:日期时间相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +TryEncodeDayOfWeekInMonth(2013, 10, 2, 1, newtime); +return datetimetostr(newtime); +// 输出: 2013-10-14 +``` + +参考TDateTime + +###### 日期格式的转换 + +####### 内容 + +- DateTimeToJulianDate +- JulianDateToDateTime +- TryJulianDateToDateTime +- DateTimeToModifiedJulianDate +- ModifiedJulianDateToDateTime +- TryModifiedJulianDateToDateTime +- DateTimeToUnix +- UnixToDateTime +- FileDateToDateTime +- DateTimeToFileDate +- ExcelRDate + +####### DateTimeToJulianDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateTimeToJulianDate(strtodatetime('2014-01-01 10:00:00')); +// 输出2456658.91667 +``` + +参考TDateTime JulianDateToDateTime TryJulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime +TryModifiedJulianDateToDateTime DateTimeToUnix UnixToDateTime + +####### JulianDateToDateTime + +范例 + +```tsl +A := JulianDatetoDateTime(2456658.91667); +return DatetimetoStr(A); // 输出2014-01-01 10:00:00 +``` + +参考TDateTime DateTimeToJulianDate TryJulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime +TryModifiedJulianDateToDateTime DateTimeToUnix UnixToDateTime + +####### TryJulianDateToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +flag := TryJulianDateToDateTime(2456658.91667, T); +if flag then return DatetimetoStr(T); +else return 0; +// 输出2014-01-01 10:00:00 +``` + +参考TDateTime DateTimeToJulianDate JulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime +TryModifiedJulianDateToDateTime DateTimeToUnix UnixToDateTime + +####### DateTimeToModifiedJulianDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +a := DateTimeToModifiedJulianDate(strtodatetime('2014-01-01 10:00:00')); +return a; // 输出56658.41667 +``` + +参考TDateTime DateTimeToJulianDate JulianDateToDateTime TryJulianDateToDateTime +ModifiedJulianDateToDateTime TryModifiedJulianDateToDateTime DateTimeToUnix +UnixToDateTime + +####### ModifiedJulianDateToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +t := ModifiedJulianDateToDateTime(56658.41667); +return datetimetostr(t); // 输出2014-01-01 10:00:00 +``` + +参考TDateTime DateTimeToJulianDate DateTimeToUnix JulianDateToDateTime +TryJulianDateToDateTime UnixToDateTime DateTimeToModifiedJulianDate +TryModifiedJulianDateToDateTime + +####### TryModifiedJulianDateToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +flag := TryModifiedJulianDateToDateTime(56658.41667, t); +if flag then return datetimetostr(t); +else return 0; +// 输出2014-01-01 10:00:00 +``` + +参考TDateTime DateTimeToJulianDate JulianDateToDateTime TryJulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime DateTimeToUnix +UnixToDateTime + +####### DateTimeToUnix + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateTimeToUnix(strtodatetime('2014-01-01 10:00:00')); +// 输出1388570400 +``` + +参考TDateTime DateTimeToJulianDate JulianDateToDateTime TryJulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime +TryModifiedJulianDateToDateTime UnixToDateTime + +####### UnixToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +T := UnixToDateTime(1388570400); +return datetimetostr(T); +// 输出2014-01-01 10:00:00 +``` + +参考TDateTime DateTimeToJulianDate JulianDateToDateTime TryJulianDateToDateTime +DateTimeToModifiedJulianDate ModifiedJulianDateToDateTime +TryModifiedJulianDateToDateTime DateTimeToUnix + +####### FileDateToDateTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := FileDateToDateTime(1143033856); +return datetimetostr(EndT); +// 输出:2014-01-01 10:00:00 +``` + +差异说明依赖运行时操作系统相关API,与DateTimeToFileDate相对。 + +具体差异表现可参考:FAQ:DateTimeToFileDate + +####### DateTimeToFileDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +EndT := strtodatetime('2014-01-01 10:00:00'); +FileEndT := DateTimeToFileDate(EndT); +return array(EndT, FileEndT); +// 比较两种日期输出 +// 输出:array(41640.41667,1143033856) +``` + +差异说明转化的结果依赖运行时操作系统相关API,转换结果会存在差异,但是同一系统中,转换与转回是自恰的。 + +即,通过DateTimeToFileDate转换后的结果,再通过FileDateToDateTime转回,可以得到最初未转换之前的值。 + +如: + +```tsl +fdate := DateTimeToFileDate(20240525.1430T); +echo fdate; // windows下返回:1488548800 Linux中返回:1716618600 +t := FileDateToDateTime(fdate); +return t; // 都返回20240525.1430T +``` + +####### ExcelRDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +RDate := 20101231; +return ExcelRDate(RDate); +// 结果:2010-12-31 +``` + +###### 宽字节日期格式转换函数 + +####### 内容 + +- DateTimeGMTToCookieStrw +- DateTimeGMTToHttpStrw +- DateTimeToInternetStrw +- Datetimetostrw +- TimetoStrw +- DateToStrw + +####### DateTimeGMTToCookieStrw + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateTimeGMTToCookieStrw(20200723.110633T); +// 输出Thu, 23-Jul-2020 11:06:33 GMT +``` + +####### DateTimeGMTToHttpStrw + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateTimeGMTToHttpStrw(20200723.110633T); +// 输出Thu, 23 Jul 2020 11:06:33 GMT +``` + +####### DateTimeToInternetStrw + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateTimeToInternetStrw(20200723.110633T, 0); +// 输出Thu, 23 Jul 2020 11:06:33 +0800 +``` + +####### Datetimetostrw + +范例 + +```tsl +return datetimetostrw(20200720.0930T); +// 输出宽字节字符串:2020-07-20 09:30:00 +``` + +####### TimetoStrw + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return TimetoStrw(9.5 / 24); // 输出宽字节字符串:09:30:00 +return TimetoStrw(20200720.0930T); // 输出宽字节字符串:09:30:00 +``` + +####### DateToStrw + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return datetostrw(20200720T); // 输出宽字节字符串 2020-07-20 +``` + +##### 字符串 + +###### 内容 + +- 常用字符串函数 +- 判定函数 +- 替换以及处理函数 +- 字符串数组相关函数 +- 重复函数 +- 多字节语言支持函数 +- 字节函数 +- 发音相关函数 +- 正则表达式函数 +- 正则表达式 +- 多语言支持函数 +- 文件名以及目录名相关处理函数 +- 其它 + +###### 常用字符串函数 + +####### 内容 + +- StrCmp +- Chr +- WideChr +- Str2Array +- Concat +- Array2Str +- Format +- Ord +- SetLength +- CompareText +- Copy +- UpperCase +- LeftBStr +- RightBStr +- MidBStr +- GetFormatLocalCode +- Str +- RightStr +- CompareStr +- LeftStr +- Trim +- SameText +- SetChar +- AppendStr +- GetChar +- LowerCase +- SetFormatLocalCode +- Val +- Pos +- TrimRight +- AnsiFormat +- TrimLeft +- StrToIntDef +- FormatFloat +- StrToCurrDef +- Booltostr2 +- StrToFloatDef +- Tostring +- IntToHex +- TryStrToInt +- FloatToStr +- TryStrToFloat +- FormatCurr +- TryStrToCurr +- StrToInt +- BoolToStr +- CurrToStr +- TryStrToBool +- SpaceByNumber +- IsValidIdent +- StrToBool +- StrToFloat +- StrToBoolDef +- IntToStr +- StrToCurr +- AnsiStr2Array +- TryUppercase +- TryLowercase +- SysEncodecryptStr +- Letters +- DecToInt64 +- DecToInt64def +- TryDecToInt64 +- DecToInt32 +- DecToInt32def +- TryDecToInt32 +- StrToInt64 +- StrToInt64Def +- TryStrToInt64 +- StrToInt32 +- StrToInt32Def +- TryStrToInt32 +- DecToInt +- DecToIntDef +- TryDecToInt + +####### StrCmp + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +a := StrCmp("arr", "arry"); +return a; // +// 输出;-1 +``` + +差异说明返回值的绝对值大小无实际意义,在不同操作系统中,其绝对值大小也表现不一。 + +比如,对比字符或ASCII码的比较,在Linux中,返回ASCII码相差的值,Windows中只返回-1,0,1等代表大小,但是符号是一致的。 + +如strcmp(#97,#100);// Windows返回-1,Linux中返回-3。 + +####### Chr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +aValue := Chr(50); +return aValue; +// 输出:字符串'2' +``` + +参考Ord + +####### WideChr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +aValue := WideChr(25105); +return aValue; +// 输出:Unicode字符串L'我' +``` + +参考Ord + +####### Str2Array + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +r := Str2Array("SZ000001;SZ000002;SH600000", ";"); // 以分号分隔 +return r; +// 输出:array("SZ000001","SZ000002","SH600000") +``` + +参考Array2Str + +####### Concat + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01: + +```tsl +arr := Concat("thank-", "you-", "very-", "much! "); +return arr; // 输出:thank-you-very-much! +``` + +范例02:Unicode字符串的合并 + +```tsl +s1 := multibytetounicodew('天软', 936); +s2 := Inttostrw(2020); +return concat(s1, s2); +// 输出宽字节字符串:天软2020 +``` + +####### Array2Str + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +var arr := array("thank", "you", "very", "much! "); +a := Array2Str(arr, "-"); +return a; +// 输出:thank-you-very-much! +``` + +参考Str2Array + +####### Format + +用途:按指定格式输出结果。 +参数: + +返回:字符串。 + +范例 + +1、把两个数字格式化为字符串:Format('First %d, Second %d', n1, n2); + +其中n1和n2是两个整数值,第一个占位符由第一个值替代,第二个占位符由第二个值替代,以此类推。 + +2、Format ('%-8d', n1); + +该句把数字n1转换成有长度是8个字符的字符串,并通过填充空白使文本左对齐,左对齐用减号(-) + +范例01:(D 和X的使用范例) + +```tsl +// 指定前2个数值转化为十进制数字字符串,第3个整数转化成十六进制字符串,3个数值必须是整数。 +// 第2个转化%-5d:由于3只有1位,需要左对齐,则在右边添加4位空格 +return Format('%d,%-5d,%X', 4, 3, 12); +// 输出字符串:4,3 ,C +``` + +范例02:(E的使用范例) + +```tsl +// .1表示后面的小数位的精度。注意,v必须是一个浮点数,比如1234400.0,如果是1234400则被认为是整数,执行函数报错 +return format("%.1E", 1234400.0); +// 输出字符串:1.2E+006 +``` + +范例03:(F的使用范例) + +```tsl +return format("%.1f", 1234400.56789); +// 输出字符串: 1234400.6 +``` + +范例04:(G的使用范例) + +```tsl +return format("%G", 1.2E + 006); +// 输出字符串:1200000 +``` + +范例05:(N的使用范例) + +```tsl +return format("%.1N", 1234400.56789); +// 输出字符串:1,234,400.6 +``` + +范例06:(M的使用范例) + +```tsl +return format("%.1M", 1234400.56789); +// 输出字符串:¥1,234,400.6 +``` + +范例七:(参数的索引) + +```tsl +return Format('%2:d,%1:5d,%0:X', 14, 3, 12); +// 输出字符串:12, 3,E +``` + +参考SetFormatLocalCode GetFormatLocalCode AnsiFormat + +####### Ord + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +r := Ord("2"); +return r; // 输出:50 +``` + +参考Chr + +####### SetLength + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 相当于截取了源串S的前NewLength个字符 +S := 'thankyou'; +SetLength(S, 5); +return S; +// 输出字符串:thank +``` + +####### CompareText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return CompareText("SZ000002", "SZ000001"); // 输出:1 +return CompareText("SZ000001", "sz000001"); // 输出:0 +return CompareText("万科A", "万科A"); // 输出:-65248 +``` + +参考CompareStr + +差异说明返回值的绝对值大小无实际意义,仅符号有效。不同操作系统中,返回的绝对值会存在差异,但是在同一个操作系统中,结果是确定的。 + +如执行:return CompareText("Tinysoft","tsl"); + +在Windows下返回-1,在Linux中返回:-10 + +####### Copy + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +a := Copy('thank you', 3, 6); +return a; // 输出字符串:ank yo +``` + +参考Concat + +####### UpperCase + +用途:进行大小写转换。 +参数: + +返回:字符串。 + +范例 + +```tsl +return UpperCase("sz000001"); +// 输出:SZ000001 +``` + +参考LowerCase + +####### LeftBStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +arr := LeftBStr("i am a student", 4); +return arr; // 输出字符串:i am +``` + +####### RightBStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +arr := RightBStr("i am a student", 4); +return arr; // 输出:dent +``` + +####### MidBStr + +范例 + +```tsl +arr := midBStr("i am a student", 6, 6); +return arr; // 输出: a stud +``` + +####### GetFormatLocalCode + +用途:按指定格式输出结果。 +参数:无。 +返回:字符串。 + +范例 + +```tsl +SetFormatLocalCode(0); +return GetFormatLocalCode(); // 输出:0 +``` + +参考SetFormatLocalCode Format AnsiFormat + +####### Str + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +Str(114, s); +return s; // 输出:1.14000000000000E+0002 +``` + +参考Val + +####### RightStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +return RightStr('abccccdddd', 2); +// 结果:’dd’ +``` + +####### CompareStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return CompareStr("万科A", "万科A"); +// 输出:-65248 +``` + +参考CompareText + +差异说明返回值的绝对值大小无实际意义,仅符号有效。不同操作系统中,返回的绝对值会存在差异,但是在同一个操作系统中,结果是确定的。 + +如执行:return CompareStr("Tinysoft","tsl"); + +在Windows下返回-1,在Linux中返回:-2099710 + +####### LeftStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +return LeftStr('abccccdddd', 2); +// 结果:'ab' +``` + +####### Trim + +用途:去除字符串首尾空白字符(空格、换行等)。 +参数:s(字符串)。 +返回:字符串。 + +范例 + +```tsl +return Trim(" Hello! \r\n Tinysoft "); +``` + +结果: + +```text +Hello! + Tinysoft +``` + +参考TrimLeft TrimRight + +####### SameText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return SameText("SZ000001", "sz000001"); // 输出: 1 +``` + +####### SetChar + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +var arr := "I am a student"; +SetChar(arr, 10, 116); +return arr; // 输出: I am a sttdent +``` + +####### AppendStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +s := "申万"; +AppendStr(s, "采掘"); +return s; // 输出:申万采掘 +``` + +####### GetChar + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +arr := GetChar("i am a student", 9); +return arr; // 输出: 116 +``` + +####### LowerCase + +用途:进行大小写转换。 +参数: + +返回:字符串。 + +范例 + +```tsl +return LowerCase("万科A"); +// 输出: 万科a +``` + +参考UpperCase + +####### SetFormatLocalCode + +用途:按指定格式输出结果。 +参数: + +返回:字符串。 + +范例 + +```tsl +SetFormatLocalCode(0); +return GetFormatLocalCode(); // 输出:0 +``` + +参考GetFormatLocalCode Format AnsiFormat + +####### Val + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例一: + +```tsl +Val("1.1424E+0002", v, Code); +return v; // 输出:114.24 +``` + +范例二: + +```tsl +// 返回错误信息:在转换到第6位字符时不成功。 +Val("1.142aE+0002", v, Code); +return array(v, code); // 输出:array(1.142,6) +``` + +参考Str + +####### Pos + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +a := Pos('a', 'thank you'); +return a; // 输出: 3 + +return Pos('fg', 'adcfgvbhj'); +// 结果:4 +``` + +参考Copy Concat + +####### TrimRight + +用途:去除字符串末尾空白字符。 +参数:s(字符串)。 +返回:字符串。 + +范例 + +```tsl +return TrimRight("Hello! \r\n Tinysoft "); +``` + +结果: + +```text +Hello! + Tinysoft +``` + +参考Trim TrimLeft + +####### AnsiFormat + +参考GetFormatLocalCode SetFormatLocalCode Format + +####### TrimLeft + +用途:去除字符串开头空白字符。 +参数:s(字符串)。 +返回:字符串。 + +范例 + +```tsl +return TrimLeft(" Hello! \r\n Tinysoft "); +``` + +结果: + +```text +Hello! + Tinysoft +``` + +参考Trim TrimRight + +####### StrToIntDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例01 + +```tsl +return StrToIntDef("12", 1); // 输出: 12 +return StrToIntDef("test", 1); // 输出: 1 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return StrToIntDef("0x12", 1); // 输出:18 +// 输出:18 +``` + +参考StrToInt IntToHex StrToBool IntToStr TryStrToInt StrToBoolDef TryStrToBool +BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr + +####### FormatFloat + +用途:按指定格式输出结果。 +参数: + +返回:字符串。 + +范例 + +| 格式串 | 1234 | -1234 | 0.5 | 0 | +| ------------------------- | --------- | ------------ | --------- | --------- | +| 无 | | -1234 | 0.5 | 0 | +| 0 | 1234 | -1234 | 1 | 0 | +| 0.00 | 1234.00 | -1234.00 | 0.50 | 0.00 | +| #######.## | 1234 | -1234 | .5 | | +| #######,##0.00 | 1,234.00 | 1,234.00 | 0.50 | 0.00 | +| #######,##0.00;(#,##0.00) | 1,234.00 | (1,234.00) | 0.50 | 0.00 | +| #######,##0.00;;Zero | 1,234.00 | -1,234.00 | 0.5 | Zero | +| 0.000E+00 | 1.234E+03 | -1.234E+03 | 5.000E-01 | 0.000E+00 | +| #######.###E-0 | 1.234E3 | -1.234E3 | 5E-1 | 0E0 | + +```tsl +return FormatFloat('0.000E+00', 23224); +// 输出字符串:"2.322E+04" +return FormatFloat('##,###.00', 123); +// 输出字符串:"123.00" +return FormatFloat('00,000.00', 123); +// 输出字符串:"00,123.00" +``` + +参考SetFormatLocalCode GetFormatLocalCode + +####### StrToCurrDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToCurrDef('1321.233', 3); +// 输出:1321.233 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurr TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### Booltostr2 + +范例 + +```tsl +return booltostr2(2 > 1); // 返回’ True’ +``` + +####### StrToFloatDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToFloatDef('a', 2); +// 输出:2 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### Tostring + +####### IntToHex + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return IntToHex(43, 1); +// 输出: 2B(二进制时候为:101011) +``` + +参考StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurr StrToCurrDef TryStrToCurr + +####### TryStrToInt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryStrToInt("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12 +``` + +范例02:转换失败 + +```tsl +ret := TryStrToInt("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryStrToInt("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef StrToBoolDef TryStrToBool +BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr + +####### FloatToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return FloatToStr(23.4); +// 输出字符串:"23.4" +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat +StrToCurr StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### TryStrToFloat + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +TryStrToFloat('321.23', s); +return s; // 输出:321.23 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef StrToCurr +StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### FormatCurr + +用途:按指定格式输出结果。 +参数: + +返回:字符串。 + +范例 + +```tsl +return FormatCurr('0.000E+00', 232.24); +// 输出:2.322E+02 +``` + +参考SetFormatLocalCode GetFormatLocalCode + +####### TryStrToCurr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +TryStrToCurr('1321.2333', s); +return s; +// 输出:1321.2333 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurr StrToCurrDef SetFormatLocalCode GetFormatLocalCode + +####### StrToInt + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例一: + +```tsl +return StrToInt("12"); +// 输出: 12 +``` + +范例二:支持16进制字符串的转换 + +```tsl +return StrToInt("0xC"); +// 输出: 12 +``` + +参考StrToInt IntToHex StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurr StrToCurrDef TryStrToCurr + +####### BoolToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return BoolToStr(1 > 2, 0); +// 输出:0 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat +StrToCurr StrToCurrDef TryStrToCurr + +####### CurrToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return CurrToStr(23.24); +// 输出字符串:"23.24" +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr StrToFloat StrToFloatDef TryStrToFloat +StrToCurr StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### TryStrToBool + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +TryStrToBool("12", s); +return s; // 输出: 1 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr + +####### SpaceByNumber + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return write('---', SpaceByNumber(2), '---'); +``` + +运行信息打印结果: + +####### IsValidIdent + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +return IsValidIdent('a0ffh2'); +// 输出: 1 +``` + +####### StrToBool + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToBool("12"); // 输出: 1 +return StrToBool("0"); // 输出: 0 +``` + +参考IntToHex StrToInt IntToStr StrToIntDef TryStrToInt StrToBoolDef TryStrToBool +BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr + +####### StrToFloat + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToFloat('3434.244'); +// 输出实数:3434.24 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloatDef TryStrToFloat +StrToCurr StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### StrToBoolDef + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToBoolDef("12", 3); +// 输出: 1 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt TryStrToBool +BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef TryStrToFloat StrToCurr +StrToCurrDef TryStrToCurr + +####### IntToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +return IntToStr(43); +// 输出:"43" +``` + +参考IntToHex StrToInt StrToBool StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurr StrToCurrDef TryStrToCurr + +####### StrToCurr + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +return StrToCurr('1321.23333'); +// 输出实数:1321.2333 +``` + +参考IntToHex StrToInt StrToBool IntToStr StrToIntDef TryStrToInt StrToBoolDef +TryStrToBool BoolToStr FloatToStr CurrToStr StrToFloat StrToFloatDef +TryStrToFloat StrToCurrDef TryStrToCurr SetFormatLocalCode GetFormatLocalCode + +####### AnsiStr2Array + +范例 + +```tsl +r := ansiStr2Array("和顺电气退和顺电气", "退"); // 以中文分隔 +return r; // 输出:array("和顺电气","和顺电气") +``` + +参考str2array + +####### TryUppercase + +用途:进行大小写转换。 +参数: + +返回:字符串。 + +范例 + +```tsl +return TryUppercase("abc"); +// 结果:"ABC" +``` + +####### TryLowercase + +范例 + +```tsl +return TryUppercase("ABC"); +// 结果:"abc" +``` + +####### SysEncodecryptStr + +范例 + +```tsl +s := "Server=127.0.0.1;Database=tsBase;Uid=TinySoft;Pwd=admin;"; +encodeS := sysencodecryptstr(s, 0); +return encodeS; +``` + +返回字符串:\_ENCODE_3A364432572518291B2C02321C2C0233084C2D59385A3B482D10641755344722194C25417C28412F56056A0C78431364003D5C38553C5269 + +####### Letters + +范例 + +```tsl +return letters(1, 0); +// 结果:a +``` + +####### DecToInt64 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01: + +```tsl +return DecToInt64("12"); // 输出: 12L +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToInt64("0x12"); // 报错 +return StrToInt64("0x12"); // 输出:18L +``` + +####### DecToInt64def + +范例 + +范例01 + +```tsl +return DecToInt64Def("12", 1); // 输出: 12L +return DecToInt64Def("test", 1); // 输出: 1L +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToInt64Def("0x12", 1); // 输出: 1L +return StrToInt64Def("0x12", 1); // 输出:18L +``` + +####### TryDecToInt64 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryDecToInt64("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12L +``` + +范例02:转换失败 + +```tsl +ret := TryDecToInt64("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryDecToInt64("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +ret := TryStrToInt64("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18L +``` + +####### DecToInt32 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01 + +```tsl +return DecToInt32("12"); // 输出: 12 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToInt32("0x12"); // 报错 +return StrToInt32("0x12"); // 输出:18 +``` + +####### DecToInt32def + +范例 + +范例01 + +```tsl +return DecToInt32Def("12", 1); // 输出: 12 +return DecToInt32Def("test", 1); // 输出: 1 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToInt32Def("0x12", 1); // 输出: 1 +return StrToInt32Def("0x12", 1); // 输出:18 +``` + +####### TryDecToInt32 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryDecToInt32("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12 +``` + +范例02:转换失败 + +```tsl +ret := TryDecToInt32("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryDecToInt32("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +ret := TryStrToInt32("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18 +``` + +####### StrToInt64 + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例01: + +```tsl +return StrToInt64("12"); // 输出: 12L +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return StrToInt64("0x12"); // 输出:18L +``` + +####### StrToInt64Def + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例01 + +```tsl +return StrToInt64Def("12", 1); // 输出: 12L +return StrToInt64Def("test", 1); // 输出: 1L +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return StrToInt64Def("0x12", 1); // 输出:18L +``` + +####### TryStrToInt64 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryStrToInt64("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12L +``` + +范例02:转换失败 + +```tsl +ret := TryStrToInt64("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryStrToInt64("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18L +``` + +####### StrToInt32 + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例01: + +```tsl +return StrToInt32("12"); // 输出: 12 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return StrToInt32("0x12"); // 输出:18 +``` + +####### StrToInt32Def + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +范例01 + +```tsl +return StrToInt32Def("12", 1); // 输出: 12 +return StrToInt32Def("test", 1); // 输出: 1 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return StrToInt32Def("0x12", 1); // 输出:18 +``` + +####### TryStrToInt32 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryStrToInt32("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12 +``` + +范例02:转换失败 + +```tsl +ret := TryStrToInt32("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryStrToInt32("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18 +``` + +####### DecToInt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01 + +```tsl +return DecToInt("12"); // 输出: 12 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToInt("0x12"); // 报错 +return StrToInt("0x12"); // 输出:18 +``` + +####### DecToIntDef + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01 + +```tsl +return DecToIntDef("12", 1); // 输出: 12 +return DecToIntDef("test", 1); // 输出: 1 +``` + +范例02:十六进制格式字符串的转换 + +```tsl +return DecToIntDef("0x12", 1); // 输出: 1 +return StrToIntDef("0x12", 1); // 输出:18 +``` + +####### TryDecToInt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:转换成功 + +```tsl +ret := TryDecToInt("12", value); +if ret then return value; +else return "转换失败!"; +// 输出: 12 +``` + +范例02:转换失败 + +```tsl +ret := TryDecToInt("test", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +``` + +范例03:十六进制格式字符串的转换 + +```tsl +ret := TryDecToInt("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出: "转换失败!" +ret := TryStrToInt("0x12", value); +if ret then return value; +else return "转换失败!"; +// 输出:18 +``` + +###### 判定函数 + +####### 内容 + +- AnsiContainsText +- AnsiStartsText +- AnsiEndsText +- AnsiMatchText +- AnsiContainsStr +- AnsiStartsStr +- AnsiEndsStr +- AnsiMatchStr +- FormatStrExt + +####### AnsiContainsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return AnsiContainsText(text, 'Abcd'); +// 输出:1,包含 +``` + +参考AnsiContainsStr + +####### AnsiStartsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return AnsiStartsText('Abc', text); +// 输出:1 +``` + +参考AnsiStartsStr + +差异说明对于空字符串,windows系统中判定为1,Linux中判定为0。其它表现无差别。 + +如:return AnsiStartsText("","A"); //windows中返回1,而Linux中返回0。 + +####### AnsiEndsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return AnsiEndsText('Efg', text); +// 输出:1 +``` + +参考AnsiEndsStr + +差异说明对于空字符串,windows系统中判定为1,Linux中判定为0。其它表现无差别。 + +如:return AnsiEndsText("","A"); //windows中返回1,而Linux中返回0。 + +####### AnsiMatchText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := 'ABZ'; +AValues := array(); +AValues[0] := 'abcdefg'; +AValues[1] := 'abz'; +return AnsiMatchText(AText, AValues); +// 输出:1 +// ab不能完全匹配Avalues数组中的值 +return AnsiMatchText('ab', AValues); +// 输出:0 +``` + +参考AnsiMatchStr + +####### AnsiContainsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := 'abcdefg'; +return AnsiContainsStr(AText, 'Bcd'); +// 输出:1 +``` + +参考AnsiContainsText + +####### AnsiStartsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +Atext := 'abcdefg'; +return AnsiStartsStr('abcd', Atext); +// 输出:1 +``` + +参考AnsiStartsText + +####### AnsiEndsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return AnsiEndsStr('efg', text); +// 输出:1 +``` + +参考AnsiEndsText + +####### AnsiMatchStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := 'ABZ'; +AValues := array(); +AValues[0] := 'abcdefg'; +AValues[1] := 'abz'; +return AnsiMatchStr(AText, AValues); +// 输出:0 ,大小写敏感 +``` + +参考AnsiEndsText + +####### FormatStrExt + +用途:按指定格式输出结果。 +参数: + +返回:字符串。 + +范例 + +```tsl +return FormatStrExt('aaaaa'); +// 结果:’aaaaa’ + +return FormatStrExt(123); +// 结果:’-’ +``` + +###### 替换以及处理函数 + +####### 内容 + +- StuffString +- AnsiReplaceText +- AnsiReplaceStr +- ReplaceText +- ReplaceStr +- WrapText +- AdjustLineBreaks +- ReverseString +- SeprateStrToTotal +- TotalStrToSeprate +- DateStrToArr +- RdateStrToArr + +####### StuffString + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +Atext := "Here will be instead by \'HERE\'"; +ASubText := "HERE"; +return StuffString(Atext, 1, 4, ASubText); +// 输出:HERE will be instead by ‘HERE’ +``` + +####### AnsiReplaceText + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := "First will be instead by \'Final\'"; +AFromText := "First"; +AToText := "FINAL"; +return AnsiReplaceText(AText, AFromText, AToText); +// 输出字符串:FINALwill be instead by 'Final' +``` + +输出:Final will be instead by F参考AnsiReplaceStr + +####### AnsiReplaceStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := "Big will be replaced by \'BIG\', but big won\'t be replaced by \'BIG\'."; +AFromText := "Big"; +AToText := "BIG"; +return AnsiReplaceStr(AText, AFromText, AToText); +// 输出:BIG will be replaced by 'BIG', but big won't be replaced by 'BIG'. +``` + +参考AnsiReplaceText + +####### ReplaceText + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := "The first letter will be replaced by \'one\', but the second letter won't."; +AFromText := "letter"; +AToText := "one"; +return ReplaceText(AText, AFromText, AToText); +// 输出:The first one will be replaced by 'one', but the second one won't.n +``` + +####### ReplaceStr + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +AText := "The First LETTER in uppercase won\'t be replaced by \'one\', but the Second letter in lowercase will."; +AFromText := "letter"; +AToText := "one"; +return ReplaceStr(AText, AFromText, AToText); +// 输出:The First LETTER in uppercase won't be replaced by 'one', but the Second one in lowercase will. +``` + +####### WrapText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +ConstLine := "Separate this sentence to two lines."; +return WrapText(ConstLine, 20); +{输出: +(自动换行时考虑字词的完整性) +Separate this +sentence to two +lines. +} +``` + +####### AdjustLineBreaks + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +范例01:调整字符串的换行模式 + +```tsl +r := AdjustLineBreaks("Tinysoft \r\n Statistical \r\nanalysis Language", 1); +return r; +{输出字符串: +Tinysoft +Statistical +analysis Language +} +``` + +范例02:数组中的应用-批量操作 + +```tsl +r := adjustlinebreaks(array("Tinysoft \n Statistical \nanalysis Language", "aa\r\nbb"), 1); +return r; +``` + +输出结果:字符串中的换行符统一转换成\r\n + +####### ReverseString + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ReverseString('abcde1234'); +// 返回字符串:4321edcba +``` + +ho tostn(r);//输出:"Tinysoft\n Statistical \nanalysis Language" + +####### SeprateStrToTotal + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return SeprateStrToTotal('债券型;现金型;配置型;股票型;保本型'); +// 结果:’债券型#现金型#配置型#股票型#保本型’ +``` + +####### TotalStrToSeprate + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return TotalStrToSeprate ('债券型#现金型#配置型#股票型#保本型'); +// 结果:’债券型;现金型;配置型;股票型;保本型’ +``` + +####### DateStrToArr + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return DateStrToArr('2007-9-10;2007-9-10', '$', ';'); // '$'表示结束位置 +``` + +####### RdateStrToArr + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return RDateStrToArr('20070331;20070630'); +``` + +###### 字符串数组相关函数 + +####### 内容 + +- AnsiIndexText +- AnsiIndexStr + +####### AnsiIndexText + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +egStr := "ansiIndexText"; +strArr := array("Tinysoft", "Statistical", "analysis", "Language", "ansiIndexText"); +result := ansiIndexText(egStr, strArr); +return result; +// 4 +``` + +参考AnsiIndexStr + +####### AnsiIndexStr + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 大小写敏感,没有找到相应的字符串,返回-1 +egStr := "ansiIndexstr"; +strArr := array("Tinysoft", "Statistical", "analysis", "Language", "ansiIndexStr"); +result := ansiIndexStr(egStr, strArr); +return result; +// 输出:-1 +``` + +参考AnsiIndexText + +###### 重复函数 + +####### 内容 + +- DupeString + +####### DupeString + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +S := DupeString('Ha', 5); +return s; +// 输出:表示将S的值变为'HaHaHaHaHa' +``` + +###### 多字节语言支持函数 + +####### 内容 + +- LengthW +- MidStr + +####### LengthW + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +testStr := "Tinysoft lengthW:汉字当成一个字符"; +return lengthW(testStr); +// 输出:25(包括空格和:) +``` + +参考LeftStr RightStr MidStr + +####### MidStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +testStr := "Tinysoft midStr:支持多字节语言,汉字当成一个字符"; +return midStr(testStr, 10, 30); +// 输出字符串:“midStr:支持多字节语言,汉字当成一个字符” +``` + +参考LeftStr RightStr LengthW + +###### 字节函数 + +字节函数,处理非MBCS的原始字符串,本身存在非B或者ANSI版本。 + +####### 内容 + +- ContainsText +- StartsText +- EndsText +- ContainsStr +- StartsStr +- EndsStr +- StuffbString +- ReversebString + +####### ContainsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +a := L'2020Tinysoft 天软'; +b := L'tinysoft'; +return ContainsText(a, b); // 返回1,包含 +``` + +####### StartsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return StartsText('Abc', text); +// 输出:1 +``` + +差异说明对于空字符串,windows系统中判定为1,Linux中判定为0。其它表现无差别。 + +如:return StartsText("","A"); //windows中返回1,而Linux中返回0。 + +####### EndsText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return EndsText('Efg', text); +// 输出:1 +``` + +差异说明对于空字符串,windows系统中判定为1,Linux中判定为0。其它表现无差别。 + +如:return EndsText("","A"); //windows中返回1,而Linux中返回0。 + +####### ContainsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +a := '2020Tinysoft 天软'; +b := 'tinysoft'; +c := 'Tinysoft'; +return array(ContainsStr(a, b), ContainsStr(a, c)); +// 输出:array(0,1) +``` + +####### StartsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +Atext := 'abcdefg'; +return StartsStr('abcd', Atext); +// 输出:1 +``` + +####### EndsStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +text := 'abcdefg'; +return EndsStr('efg', text); +// 输出:1 +``` + +####### StuffbString + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +Atext := "Here will be instead by \'HERE\'"; +ASubText := "HERE"; +return StuffbString(Atext, 1, 4, ASubText); +// 输出:HERE will be instead by ‘HERE’ +``` + +####### ReversebString + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +a := L'2020Tinysoft 天软'; // 宽字节字符串的表达方式 +return ReversebString(a); +// 返回字符串:软天 tfosyniT0202 +``` + +###### 发音相关函数 + +####### 内容 + +- SoundEx +- SoundexInt +- DecodeSoundexInt +- SoundexWord +- DecodeSoundexWord +- SoundexSimilar +- SoundexCompare +- SoundexProc +- AnsiResemblesText + +####### SoundEx + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +testStr1 := "sun"; +s1 := SoundEx(testStr1, 4); +testStr2 := "sum"; +s2 := SoundEx(testStr2, 4); +testStr3 := "test"; +s3 := SoundEx(testStr3, 4); +return array(s1, s2, s3); +// 输出:array("S500","S500","T230") +``` + +####### SoundexInt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +testStr1 := "sun"; +s1 := SoundexInt(testStr1, 4); +testStr2 := "sum"; +s2 := SoundexInt(testStr2, 4); +testStr3 := "test"; +s3 := SoundexInt(testStr3, 4); +return array(s1, s2, s3); +// 输出:array(208597,208597,218929) +``` + +参考DecodeSoundexInt + +####### DecodeSoundexInt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +testStr := "Tinysoft SoundexInt:返回表示AText的发音的整数"; +testStr := DecodeSoundexInt(SoundexInt(testStr, 4)); +return testStr; +// T521 +``` + +参考SoundexInt + +####### SoundexWord + +范例 + +```tsl +testStr := "Tinysoft SoundexInt:返回表示AText的发音的整数"; +testStr := soundexWord(SoundEx(testStr, 4)); +return testStr; +// 24206 +``` + +参考DecodeSoundexWord + +####### DecodeSoundexWord + +范例 + +```tsl +testStr := "Tinysoft SoundexInt:返回表示AText的发音的整数"; +testStr := decodesoundexWord(soundexWord(SoundEx(testStr, 4))); // 24206 +return testStr; +// T000 +``` + +参考SoundexWord + +####### SoundexSimilar + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return SoundexSimilar("sun", "sum"); +// 输出:1 +return SoundexSimilar("sun", "fun"); +// 输出:0 +return SoundexSimilar("return ", "result"); +// 输出:0 +``` + +####### SoundexCompare + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return SoundexCompare("sun", "sum"); +// 输出:0 +return SoundexCompare("sun", "fun"); +// 输出:1 +return SoundexCompare("result", "return "); +// 输出:-1 +``` + +####### SoundexProc + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return SoundexProc("sun", "sum"); +// 输出:1 +return SoundexProc("sun", "fun"); +// 输出:0 +return SoundexProc("transaction", "transact"); +// 输出:1 +``` + +####### AnsiResemblesText + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return AnsiResemblesText("sun", "sum"); +// 输出:1 +return AnsiResemblesText("sun", "fun"); +// 输出:0 +return AnsiResemblesText("transaction", "transact"); +// 输出:1 +``` + +###### 正则表达式函数 + +####### 内容 + +- ParseRegExpr +- ParseRegExpr:替换功能 +- GetLikeFlag +- SetLikeFlag +- ReplaceStrByReg +- ReplaceTextByReg +- ParseRegExpr3 + +####### ParseRegExpr + +范例 + +范例01:匹配数字、指定字符串 + +```tsl +source := "ParseRegExpr 2011 ShenZhenTinysoft (TSL)"; +ParseRegExpr("(\\d+).*(Tinysoft)", source, "", result, MPos, Mlen); +return result; +// 输出:array(("2011 ShenZhenTinysoft","2011","Tinysoft")) +``` + +说明: + +结果中返回匹配的源串"2011 ShenZhenTinysoft"以及匹配出来的串"2011"和"Tinysoft" + +1、在匹配串中加中括号()是表示将匹配的结果返回,下面的例子中,要返回的匹配串的内容是(\\d+)和(tinysoft)匹配出来的结果。 + +2、\本身就是转义字符,所以要用\\d来表示\d是一个元字符(表示匹配一个数字字符)。\\d+表示匹配多个数字字符。 + +3、.表示匹配任意单个字符,除'\n'外。.*表示匹配任意多个单个字符。由于.*没有中括号(),所以匹配的字符不返回。 + +4、(Tinysoft)匹配字符串Tinysoft,并将匹配的字符返回。注意,字符大小写敏感。 + +范例02:匹配数字、字符串、带括号的字符串 + +```tsl +source := "ParseRegExpr 2011 ShenZhenTinysoft (TSL)"; +ParseRegExpr("(\\d+).*(Tinysoft) (\\(\\w+\\))", source, "", result, MPos, Mlen); +return result; +// 输出:array(("2011 ShenZhenTinysoft (TSL)","2011","Tinysoft","(TSL)")) +``` + +说明: + +与范例01相比,新增了对()的匹配。 + +结果中返回匹配的源串"2011 ShenZhenTinysoft +(TSL)"以及匹配出来的串"2011"、"Tinysoft"和"(TSL)"。 + +1、\\(和\\)是对中括号()的匹配。 + +2、\\w表示\w是一个元字符,匹配包括下划线的任何单词字符。\\w+表示匹配多个任意单词字符。 + +范例03:处理Unicode串-匹配汉字 + +```tsl +source := L"hello 你好!123"; // unicode串 +reg := L"[\u4E00-\u9FA5]+"; // 匹配汉字的正则表达式->也是unicode串 +ret := ParseRegExpr(reg, source, "", result, MPos, Mlen); +return result; +``` + +返回结果:array((L"你好")) + +范例04:通过控制符"u"设置为非贪婪模式 + +```tsl +source := "hello tiny tiny tiny tiny tiny"; +reg := "hello.*(tiny)"; +ret := ParseRegExpr(reg, source, "u", result, MPos, Mlen); +return result; +``` + +返回:array(("hello tiny","tiny")) + +####### ParseRegExpr:替换功能 + +范例 + +范例三:求值宏 + +```tsl +// 求值宏,将数字后的字母替换到数字前 +source := "ddd2011a uuuu 2012b zzzz 2013c xxx"; +ParseRegExpr("(\\d+)(\\w+)", source, "r", "$2$1", s ); +return s; +``` + +ddda2011 uuuu b2012 zzzz c2013 xxx + +范例四:回调函数 + +```tsl +// 回调函数,替换匹配串第1位+匹配串+匹配串第二位 +Source := "ParseRegExpr 2011 ShenZhenTinysoft (TSL)"; +ParseRegExpr("(\\d+).*(Tinysoft)", source, "r", function(a) begin return a[1] + a[0] + a[2];end, s); +return s; +``` + +参考正则表达式 + +####### GetLikeFlag + +范例 + +```tsl +s := "ParseRegExpr 2011 \r\n ShenZhenTinysoft (TSL)"; +reg := "(\\d+).*(tinysoft)"; +SetLikeFlag(0b0001 + 0x0010); // 大小写无关+使 '.' 特殊字符匹配任意字符 +r := s like reg; +return getlikeflag(); // 获取当前正则控制符状态 +// 返回17 +``` + +####### SetLikeFlag + +范例 + +```tsl +s := "ParseRegExpr 2011 \r\n ShenZhenTinysoft (TSL)"; +reg := "(\\d+).*(tinysoft)"; +SetLikeFlag(0b0001 + 0x0010); // 大小写无关+使 '.' 特殊字符匹配任意字符 +return s like reg; +``` + +返回:1 + +####### ReplaceStrByReg + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ReplaceStrByReg("abcdeak", "A", "kkkk"); +// 结果:abcdeak +``` + +####### ReplaceTextByReg + +用途:进行字符串提取或替换处理。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ReplaceTextByReg("abcdeak", "a", "kkkk"); +// 结果:kkkkbcdekkkkk +``` + +####### ParseRegExpr3 + +用途:解析输入并返回结果。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ParseRegExpr3("abcdeak", "ab", "kkkk", "ir"); +// 结果:kkkkcdeak +``` + +###### 正则表达式 + +####### 内容 + +- 什么是正则表达式 +- 正则表达式基础 +- 正则表达式中的元字符 + +####### 什么是正则表达式 + +一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用,不过,经过学习之后这些复杂的表达式其实相当简单,而且,一旦弄懂了,你就能把难处理而且容易出错的文本处理工作压缩在几分钟(甚至几秒钟)内完成。正则表达式被各种语言、编辑工具、脚本工具广泛的支持,TSL语言也支持它。 + +但是,由于正则表达式本身缺少一个规范,因此,各个系统对正则表达式的实现也不同,TSL语言中采用了PERL兼容的正则表达式。 + +####### 正则表达式基础 + +正则表达式由一些普通字符和一些元字符组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。 + +在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式"testing"中没有包含任何元字符,,它可以匹配"testing"和"123testing"等字符串,但是不能匹配"Testing"。 + +####### 正则表达式中的元字符 + +要想真正的用好正则表达式,正确的理解元字符是最重要的事情。下表列出了所有的元字符和对它们的一个简短的描述。 + +注:由于TSL语言的字符串常量中\本身就是转义字符,因此,只要牵涉到\的,就要用\\来描述,因而象\s的TSL常量表述则为’\\s’。 + +| 字符 | 描述 | +| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| \ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\' 匹配 "" 而 "\(" 则匹配 "("。 | +| ^ | 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。 | +| $ | 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。 | +| \* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 *
等价于{0,}。 | +| + | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 | +| | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。 | +| {n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 | +| {n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o\*'。 | +| {n,m} | m 和 n 均为非负整数,其中n <=
m。最少匹配 n 次且最多匹配 m 次。如:"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 | +| | 当该字符紧跟在任何一个其他限制符 (\*, +, ?, {n}, {n,},
{n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。 | +| . | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 | +| (pattern) | 匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到。要匹配圆括号字符,请使用 '\(' 或 '\)'。 | +| (?:pattern) | 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (\|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y\|ies) 就是一个比 'industry\|industries' 更简略的表达式。 | +| (?=pattern) | 正向预查,在任何未来符合匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, 'Windows
(?=95\|98\|NT\|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows
3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 | +| (?!pattern) | 负向预查,在任何不匹配未来符合匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows
(?!95\|98\|NT\|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows
2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始 | +| x\|y | 匹配 x 或 y。例如,'z\|food' 能匹配 "z" 或 "food"。'(z\|f)ood' 则匹配 "zood" 或"food"。 | +| [xyz] | 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。 | +| [^xyz] | 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。 | +| [a-z] | 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。 | +| [^a-z] | 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。 | +| \b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 | +| \B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 | +| \cx | 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 | +| \d | 匹配一个数字字符。等价于 [0-9]。 | +| \D | 匹配一个非数字字符。等价于 [^0-9]。 | +| \f | 匹配一个换页符。等价于 \x0c和 \cL。 | +| \n | 匹配一个换行符。等价于 \x0a和 \cJ。 | +| \r | 匹配一个回车符。等价于 \x0d 和 \cM。 | +| \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 | +| \S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 | +| \t | 匹配一个制表符。等价于 \x09 和 \cI。 | +| \v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 | +| \w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 | +| \W | 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 | +| \xn | 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如, '\x41' 匹配 "A"。'\x041' 则等价于 '\x04'
& "1"。正则表达式中可以使用ASCII 编码。. | +| \num | 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)' 匹配两个连续的相同字符。 | +| \n | 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 | +| \nm | 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least
nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 | +| \nml | 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。 | +| \un | 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (?)。 | + +###### 多语言支持函数 + +####### 内容 + +- NextCharIndex +- AnsiToUTF8 +- UTF8ToAnsi +- CharToByteIndex +- ByteToCharLen +- AnsiQuotedStr +- AnsiPos +- AnsiDequotedStr +- CharToByteLen +- CharLength +- ByteToCharIndex +- ByteType +- Booltostrw +- UnicodeESC +- unUnicodeESC2 +- UnicodeToMultiByte +- FloattoStrw +- UnicodeESC2 +- unUnicodeESCw +- UnicodetoUTF8 +- CurrtoStrw +- Inttostrw +- MultibyteToUnicode +- Booltostrw2 +- Strw +- Inttohexw +- LCMapString +- MultibytetoUnicodew +- UTF8toUnicode +- Exportjsonstring +- unUnicodeESC2w +- unUnicodeESC +- Ifwstring +- MakeLCID +- Importjsonstring +- ExportJsonStringUTF8 +- ExportJSONStringMBCS + +####### NextCharIndex + +范例 + +```tsl +// ‘软’的开始字节是3,下一个字符是‘T’,‘T’的开始字节位置是5 +S := "天软Tinysoft Statistical analysis Language"; +return nextCharIndex(s, 3); +// 返回:5 +``` + +####### AnsiToUTF8 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return AnsiToUTF8('2011 tinysoft天软科技'); +// 返回字符串:2011 tinysoft澶╄蒋绉戞妧 +``` + +####### UTF8ToAnsi + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return UTF8ToAnsi ('2011 tinysoft澶╄蒋绉戞妧'); +// 返回字符串:2011 tinysoft天软科技 +``` + +####### CharToByteIndex + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 返回第30字符对应的字节位置 +// 其中‘天软’占有4个字节,其余每个字符占1个字节 +S := "天软Tinysoft Statistical analysis Language"; +return CharToByteIndex(s, 30); +// 返回:32 +``` + +####### ByteToCharLen + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 指定最多字节为30后,查找S中30个字节中有多少个字符, +// 其中‘天软’占有4个字节,所以30个字节中,S有28个字符。 +S := "天软Tinysoft Statistical analysis Language"; +b1 := ByteToCharLen(S, 30); +return b1; +// 返回:28 +``` + +####### AnsiQuotedStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +S := "天软Tinysoft Statistical analysis Language"; +return AnsiQuotedStr(s, "'"); +// 返回字符串:'天软Tinysoft Statistical analysis Language' +``` + +####### AnsiPos + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +return AnsiPos("tinysoft", "2011 tinysoft"); +// 6 +``` + +####### AnsiDequotedStr + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +S := "'天软Tinysoft Statistical analysis Language'"; +return AnsiDequotedStr(s, "'"); +// 返回字符串:天软Tinysoft Statistical analysis Language +``` + +####### CharToByteLen + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 在S字符串中取30个字符,统计其所占的字节数。 +// 其中‘天软’占有4个字节,其余每个字符占1个字节,由此,30个字符占有32个字节 +S := "天软Tinysoft Statistical analysis Language"; +b1 := CharToByteLen(S, 30); +return b1; +// 返回:32 +``` + +####### CharLength + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 第2个字符‘软’的字节数 +S := "天软Tinysoft Statistical analysis Language"; +return CharLength(s, 2); +// 返回:2 +``` + +####### ByteToCharIndex + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 返回第30字节位置时,是第几个字符位置 +// 其中‘天软’占有4个字节,其余每个字符占1个字节 +S := "天软Tinysoft Statistical analysis Language"; +return ByteToCharIndex(s, 30); +// 返回:28 +``` + +####### ByteType + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +// 单字节字符‘t’ +return ByteType("2011 tinysoft", 6); +// 0 +// 多字节字符‘天’ +return ByteType("2011 tinysoft天软", 14); +// 1 +// 多字节字符‘软’,且为最后一个字符 +return ByteType("2011 tinysoft天软", 15); +// 2 +// 单字节字符‘1’,最后一个字符 +return ByteType("2011 ", 4); +// 0 +``` + +####### Booltostrw + +范例 + +```tsl +return booltostrw(2 > 1); +// 返回宽字节字符串:-1 +``` + +####### UnicodeESC + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return echo UnicodeESC('2011 tinysoft天软科技'); +// 返回字符串:2011%20tinysoft%u5929%u8F6F%u79D1%u6280 +``` + +####### unUnicodeESC2 + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return unUnicodeESC2(%%g 2011 tinysoft\u5929\u8F6F\u79D1\u6280%%g); +// 返回字符串:2011 tinysoft天软科技 +// 注:其中\uxxxx编码方式中的\是一个转义字符,所以需要用非转义字符串%%方式进行表达。 +``` + +####### UnicodeToMultiByte + +####### FloattoStrw + +范例 + +```tsl +return floattostrw(1234.1234); +// 输出宽字节字符串:“1234.1234” +``` + +####### UnicodeESC2 + +范例 + +```tsl +return UnicodeESC('2011 tinysoft天软科技'); +// 返回字符串:2011 tinysoft\u5929\u8F6F\u79D1\u6280 +``` + +####### unUnicodeESCw + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return unUnicodeESCw('2011%20tinysoft%u5929%u8F6F%u79D1%u6280'); +// ’ 2011 tinysoft天软科技’ +``` + +####### UnicodetoUTF8 + +范例 + +```tsl +return unicodetoutf8(L'2020 Tinysoft 天软科技'); +// 返回:2020 Tinysoft 澶╄蒋绉戞妧 +``` + +####### CurrtoStrw + +范例 + +```tsl +return CurrToStrw(23.24); +// 输出字符串:"23.24" +``` + +####### Inttostrw + +范例 + +```tsl +s := inttostrw(2); +return array(ifstring(s), ifwstring(s)); +// 返回:array(0,1) 说明返回结果串s为宽字节串,而非多字节字符串。 +``` + +####### MultibyteToUnicode + +####### Booltostrw2 + +范例 + +```tsl +return booltostrw2(2 > 1); +// 返回宽字节字符串:True +``` + +####### Strw + +范例 + +```tsl +v := strw(123.123, s); +return s; +// 返回宽字节字符串:1.23123000000000E+0002 +``` + +####### Inttohexw + +范例 + +```tsl +return inttohexw(43, 5); +// 返回宽字符串字符串:0002B +``` + +####### LCMapString + +范例 + +lcmapstring(s,0x0804,0x2000000);//可以把繁体转换为简体字符集 + +```tsl +return lcmapstring("亞洲", 0x0804, 0x2000000); +``` + +返回:亚洲 + +差异说明由于根据windowsAPI的开发,所以Linux中不支持。 + +####### MultibytetoUnicodew + +范例 + +```tsl +return multibytetounicodew('2020 Tinysoft 天软科技', 936); +// 返回宽字节字符串:2020 Tinysoft 天软科技 即L’ 2020 Tinysoft 天软科技’ +``` + +####### UTF8toUnicode + +范例 + +```tsl +return UTF8ToUnicode ('2011 tinysoft澶╄蒋绉戞妧'); +// 返回双字节字符串:2011 tinysoft天软科技 +``` + +####### Exportjsonstring + +范例 + +范例01:将天软含中文的字符串转化为json串 + +```tsl +s := stockname('SZ000002'); // 万 科A +return exportjsonstring(s); +// 返回字符串:"\u4E07 \u79D1\uFF21" +``` + +范例02:将数组转化为json串 + +```tsl +s := array((1, 'a'), ('Tinysoft天软', '天软科技')); +return exportjsonstring(s); +// 返回字符串:[[1,"a"],["Tinysoft\u5929\u8F6F","\u5929\u8F6F\u79D1\u6280"]] +``` + +####### unUnicodeESC2w + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return unUnicodeESC2w(%%g 2011 tinysoft\u5929\u8F6F\u79D1\u6280%%g); +// 返回宽字节字符串:2011 tinysoft天软科技 +// 注:其中\uxxxx编码方式中的\是一个转义字符,所以需要用非转义字符串%%方式进行表达。 +``` + +####### unUnicodeESC + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return unUnicodeESC('2011%20tinysoft%u5929%u8F6F%u79D1%u6280'); +// ’ 2011 tinysoft天软科技'‘ +``` + +####### Ifwstring + +范例 + +范例一: + +```tsl +// 判断是否为宽字节字符串类型 +r1 := IfWString(1); +r2 := IfWString("A"); +r3 := IfWString(L"C"); +r4 := IfWString(array(1, "A", L"C")); +return array(r1, r2, r3, r4); +// 结果:array(0,0,1,0) +``` + +范例二: + +```tsl +// 对数组第一维度数据进行类型判断 +t := array(L"C", 3.56, "A", (1, L"C", 3), nil); +return IfWString(t, -1); +// 结果:array(1,0,0,0,0) +``` + +范例三: + +```tsl +// 对数组中每一数据进行类型判断 +t := array(L"C", 3.56, "A", (nan, 2.14, L"C"), nil); +return IfWString(t, 1); +// 结果:array(1,0,0,(0,0,1),0) +``` + +####### MakeLCID + +####### Importjsonstring + +范例 + +范例01:将json串转换成天软字符串 + +```tsl +json := %%g"\u4E07 \u79D1\uFF21"%%g; +// 注:在上述语句中,原串存在转义字符,需要用到非转义字符串%%表示该字符串,不能用引号进行表示。 +return importjsonstring(json); +// 返回字符串:万 科A +``` + +范例02:将exportjsonstring转化的json串转为天软数据结构 + +```tsl +s := array((1, 'a'), ('Tinysoft天软', '天软科技')); +json := exportjsonstring(s); +return importjsonstring(json); +// 返回 +0 +1 +1 +a +Tinysoft天软 +// 天软科技 +``` + +范例03: + +```tsl +arr := array(("code":"PFTSDEMO0004", "name":"商品跨期"), +("代码":"PFTSDEMO0003", "name":"债券组合")); +return importJsonString(Utf8toAnsi(exportJsonStringUTF8(arr))); +``` + +返回 + +| code | name | 代码 | +| ------------ | -------- | ------------ | +| PFTSDEMO0004 | 商品跨期 | | +| | 债券组合 | PFTSDEMO0003 | + +范例04:将大的无符号数字转为int64 + +```tsl +json := %%g 4611686018427387904 %%g; +return importjsonstring(json); +``` + +####### ExportJsonStringUTF8 + +范例 + +范例01: + +```tsl +a := select ['StockID'], ['StockName'], datetostr(['date']) as'date', ['close'] +from markettable datekey 20200901T +to 20200902T of'SZ000002'end; +return exportjsonstringutf8(a); +``` + +返回字符串 + +[{"StockID":"SZ000002","StockName":"涓 +绉戯肌","date":"2020-09-01","close":27.22},{"StockID":"SZ000002","StockName":"涓 +绉戯肌","date":"2020-09-02","close":27.52}] + +范例02:与python交互中的应用 + +pythonCode + +```tsl +import sys +sys.path.append('C:\Program Files\Tinysoft\Analyse.NET') +import TSLPy3 +s := """ +a := select ['StockID'], ['StockName'], datetostr(['date']) as'date', ['close'] +from markettable datekey 20200901T +to 20200902T of'SZ000002'end; +return exportjsonstringutf8(a); +""" +data := TSLPy3.RemoteExecute(s, {}) +print(data[1].decode('utf8')) +``` + +python中返回: + +[{"StockID":"SZ000002","StockName":"万 +科A","date":"2020-09-01","close":27.22},{"StockID":"SZ000002","StockName":"万 +科A","date":"2020-09-02","close":27.52}] + +####### ExportJSONStringMBCS + +用途:将字符串或数组序列化为 JSON 字符串,保留中文原码(MBCS),不转义为 \\uXXXX。 +参数: + +返回:JSON 字符串。 + +范例 + +范例01:将天软含中文的字符串转化为json串 + +```tsl +s := stockname('SZ000002'); // 万 科A +return ExportJSONStringMBCS(s); +// 返回字符串:"\"万 科A\"" +``` + +范例02:将数组转化为json串 + +```tsl +s := array((1, 'a'), ('Tinysoft天软', '天软科技')); +return ExportJSONStringMBCS(s); +// 返回字符串:"[[1,\"a\"],[\"Tinysoft天软\",\"天软科技\"]]" +``` + +###### 文件名以及目录名相关处理函数 + +文件相关处理函数包括了对文件名、目录以及扩展名等等相关处理函数,以及文件时间以及和TDatetime之间的转换函数。 + +####### 内容 + +- ChangeFileExt +- ExtractFilePath +- ExtractFileDir +- ExtractFileDrive +- ExtractFileName +- ExtractFileExt +- ExtractRelativePath +- IsPathDelimiter +- IsDelimiter +- IncludeTrailingPathDelimiter +- IncludeTrailingBackslash +- ExcludeTrailingPathDelimiter +- ExcludeTrailingBackslash +- LastDelimiter +- AnsiCompareFileName +- SameFileName +- AnsiLowerCaseFileName +- AnsiUpperCaseFileName + +####### ChangeFileExt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +// 实际D盘的test.tsl没有改变 +return ChangeFileExt("D:\\test.tsl", ".txt"); +// D:\test.txt +``` + +####### ExtractFilePath + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExtractFilePath("D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// D:\Tinysoft\tslweb\web\ +``` + +####### ExtractFileDir + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExtractFileDir("D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// D:\Tinysoft\tslweb\web +``` + +差异说明对于路径的处理,在不同系统中存在差异。如Linux中就没有驱动的概念,因此,在处理带驱动的路径时: + +如对于根目录的处理extractfiledir("C:\\abc.txt"),Windows中返回”C:\”而Linux中返回”C:” + +####### ExtractFileDrive + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExtractFileDrive("D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// 输出:D: +``` + +####### ExtractFileName + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +return ExtractFileName("D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// 输出:test.tsl +``` + +####### ExtractFileExt + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExtractFileExt("D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// 输出:.tsl +``` + +####### ExtractRelativePath + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExtractRelativePath("D:\\test.tsl", "D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// 输出:Tinysoft\tslweb\web\test.tsl +``` + +差异说明由于Linux系统中无盘符概念,所以不支持该功能。 + +####### IsPathDelimiter + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +return IsPathDelimiter("D:\\Tinysoft\\tslweb\\web\\test.tsl", 3); +// 输出:1 +``` + +####### IsDelimiter + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +return IsDelimiter("tinysoft", "2011 tinysoft", 6); +// 输出:1 +``` + +####### IncludeTrailingPathDelimiter + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return IncludeTrailingPathDelimiter("D:\\Tinysoft\\tslweb\\web"); +// 输出: D:\Tinysoft\tslweb\web\ +``` + +差异说明与路径中存在的路径分割符保持一致,当路径中不存在分割符时,则Windows中默认增加"\",在Linux中,则默认结路径路径加上”/”结尾。 + +如在Linux中:return IncludeTrailingPathDelimiter("/Tinysoft"); + +则返回字符串:/Tinysoft/ + +####### IncludeTrailingBackslash + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return IncludeTrailingBackslash ("D:\\Tinysoft\\tslweb\\web"); +// 输出: D:\Tinysoft\tslweb\web\ +``` + +差异说明与路径中存在的路径分割符保持一致,当路径中不存在分割符时,则Windows中默认增加"\",在Linux中,则默认结路径路径加上”/”结尾。 + +如在Linux中:return IncludeTrailingBackslash ("/Tinysoft"); + +则返回字符串:/Tinysoft/ + +####### ExcludeTrailingPathDelimiter + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExcludeTrailingPathDelimiter("D:\\Tinysoft\\tslweb\\web\\"); +// 输出: D:\Tinysoft\tslweb\web +``` + +####### ExcludeTrailingBackslash + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return ExcludeTrailingBackslash("D:\\Tinysoft\\tslweb\\web\\"); +// 输出: D:\Tinysoft\tslweb\web +``` + +####### LastDelimiter + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return LastDelimiter('\\', "D:\\Tinysoft\\tslweb\\web\\test.tsl"); +// 输出:23 +``` + +####### AnsiCompareFileName + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +return AnsiCompareFileName('index.tsl', "test.tsl"); +// 输出:-11 +``` + +差异说明返回值的绝对值大小无实际意义,在不同操作系统中,其结果也表现不一。 + +在Linux中,由于文件名会区分大小写,而Windows中文件名不区分大小写,所以对比结果会有差异。 + +如: + +在Windows中: + +return AnsiCompareFileName("D:\\test\\file1.txt","D:\\Test\\File1.txt"); + +结果为0,因为不区分大小写,两文件名一致。 + +在Linux中: + +return AnsiCompareFileName("/tinysoft/file1.txt","/Tinysoft/File1.txt"); + +结果为32,因为区分大小写,两文件名不相等。 + +####### SameFileName + +用途:字符串相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +return SameFileName('index.tsl', "test.tsl"); +// 输出:0 +``` + +####### AnsiLowerCaseFileName + +用途:进行大小写转换。 +参数: + +返回:整数。 + +范例 + +```tsl +return AnsiLowerCaseFileName("TEST.tsl"); +// 输出:test.tsl +``` + +####### AnsiUpperCaseFileName + +用途:进行大小写转换。 +参数: + +返回:整数。 + +范例 + +```tsl +return AnsiUpperCaseFileName("test.tsl"); +// 输出:TEST.TSL +``` + +###### 其它 + +####### 内容 + +- GetPYStringList +- HztoPY +- DataUnitConversion + +####### GetPYStringList + +用途:字符串相关函数。 +参数:无。 +返回:字符串。 + +范例 + +```tsl +sl := GetPYStringList(); +return sl.values("明"); +// 返回:M +``` + +####### HztoPY + +用途:字符串相关函数。 +参数: + +返回:字符串。 + +范例 + +```tsl +return HztoPY("华夏优势"); // HXYS +return HztoPY("华夏盛势"); // HXCS HXSS +``` + +####### DataUnitConversion + +- GetPYStringList +- HztoPY +- DataUnitConversion + +##### 数组 + +###### 内容 + +- 基本 +- 数组下标以及长度相关函数 +- 排序函数 +- 增删改查 +- 数组操作 +- 数组取值 +- 集合运算 +- 统计函数 +- 重构函数 +- 稀疏矩阵 +- 数据比较 +- 表格显示 +- 数组下标 + +###### 基本 + +####### 内容 + +- FieldCount +- FieldExist +- FieldNames +- FieldName +- IsTable +- MagicSetArray +- NoRecordTable +- MagicGetArray +- RecordExist +- RecordExist2 +- RecordExist3 +- FieldNamesOfStrSubscript +- StrSubscriptTableToNormal +- FieldCountOfStrSubscript +- argmax +- Argmin +- PasswordGen + +####### FieldCount + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +return FieldCount(t1); +// 结果:2 +``` + +####### FieldExist + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +return FieldExist(t1, 'b'); +// 结果:1 +``` + +####### FieldNames + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3));return FieldNames(t1); +``` + +####### FieldName + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +return FieldName(t1, 0); +// 结果:’a’ +``` + +####### IsTable + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +return IsTable(t1); +// 结果:1 +``` + +####### MagicSetArray + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +a := array((1, 2, 3), (4, 5, 6)); +MagicsetArray(a, 1, 2, 10); // a[1][2] := 10 +return a; +``` + +范例02: + +```tsl +a := array((1, 2, 3), (4, 5, 6)); +MagicSetArray(a, array(1, 2), "b"); // a[1][2] := "b" +return a; +``` + +参考MagicGetArray + +####### NoRecordTable + +用途:数组相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return NoRecordTable(); +// 结果:Array() +``` + +####### MagicGetArray + +范例 + +范例01: + +```tsl +a := array((1, 2, 3), (4, 5, 6)); +return MagicgetArray(a, 1, 2); // 返回a[1][2]的数据 +``` + +结果:6 + +范例02: + +```tsl +a := array((1, 2, 3), (4, 5, array(3, 4))); +return MagicgetArray(a, array(1, 2)); // 返回a[1][2]的数据 +``` + +参考MagicSetArray + +####### RecordExist + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(1, 2, 12, 3, 14); +return RecordExist(t, 12); +// 结果:2 +``` + +####### RecordExist2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +return RecordExist2(t1, 'b', 3); +// 结果:2 +``` + +####### RecordExist3 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(1, 2, 12, 3, 14); +return RecordExist3(t, 3); +// 结果:1 +``` + +####### FieldNamesOfStrSubscript + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := `array('a':(1, 2, 3, 4, 5), 'b': (2, 3, 4, 5, 6), 'c': (3, 4, 5, 6, 7), 'd': (4, 5, 6, 7, 8)); +return FieldNamesOfStrSubscript(s); +``` + +返回: + +####### StrSubscriptTableToNormal + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 把字符串行标变成自然数序列的行标 +t := array("a":(1, 2, 3), "b":(4, 5, 6), "c":(7, 8, 9)); +return StrSubscriptTableToNormal(t, '序号'); +``` + +把字符串行标 + +变成自然数序列行标,原行标值放在fn对应的列中: + +####### FieldCountOfStrSubscript + +用途:进行字符串提取或替换处理。 +参数: + +返回:整数。 + +范例 + +```tsl +s := `array('a':(1, 2, 3, 4, 5), 'b':(2, 3, 4, 5, 6), 'c':(3, 4, 5, 6, 7), 'd':(4, 5, 6, 7, 8)); +return FieldCountOfStrSubscript(s); +// 返回:4 +``` + +####### argmax + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(9, 8, 10); +return argmax(x); // 2 +``` + +####### Argmin + +范例 + +```tsl +x := array(3, 1, 9, 2); +return argmin(x); // 1 +``` + +####### PasswordGen + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return rdo2 PasswordGen(8, 5, 'ts', 3); +``` + +返回: + +###### 数组下标以及长度相关函数 + +####### 内容 + +- GetStrIndexNum +- GetStrIndexs +- GetIntIndexs +- GetAllIndexs +- DeleteIndex +- DeleteField +- Length + +####### GetStrIndexNum + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +arr := array("a1":1, "a2":2, 1:3); +return GetStrIndexNum(arr); +// 输出:2 +``` + +####### GetStrIndexs + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +arr := array("a1":1, "a2":2, "a3":3); +return GetStrIndexs(arr); +// 输出:array(“a1”,”a2”,”a3”)。 +``` + +参考GetIntIndexs GetAllIndexs + +####### GetIntIndexs + +范例 + +```tsl +arr := array(1:"p1", 2:"p2", 3:"p3", "a4":"p4"); +return Getintindexs(arr); +// 输出:array(1,2,3) +``` + +参考GetStrIndexs GetAllIndexs + +####### GetAllIndexs + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +arr := array("p1":1, "p2":2, "p3":3); +return GetAllIndexs(arr); // 输出:array(“p1”,”p2”,”p3”) +``` + +参考GetStrIndexs GetIntIndexs + +####### DeleteIndex + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +arr := array("p1":1, "p2":2, "p3":3); +result := DeleteIndex(arr, "p2", 1); +return result; // true +return arr; +// array(“p1”:1,”p3”:3) +``` + +参考DeleteField + +####### DeleteField + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +arr := array(("p1":1, "p2":2, "p3":3), ("p1":4, "p2":5, "p3":6)); +result := DeleteField(arr, "p2", 1); +return arr; // array(("p1":1,"p3":3), ("p1":4"p3":6)) +``` + +参考DeleteIndex + +####### Length + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +arr := array(("p1":1, "p2":2, "p3":3), ("p1":4, "p2":5, "p3":6)); +return length(arr); +// 2 +``` + +###### 排序函数 + +####### 内容 + +- RankIt +- RankIt2 +- RPSIt +- SortTableByFieldExt +- RankValue +- SortArray +- SortTableByField +- argsort + +####### RankIt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33)); +RankIt(t2, 'c', 1); +return t2; +``` + +####### RankIt2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33)); +RankIt2(t2, 'c', '名次', 1); +return t2; +``` + +####### RPSIt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +获得沪深300的成分股,并计算EndT的涨幅,对涨幅排序后返回其排序百分比。 + +```tsl +Endt := inttodate(20140401); +SetSysParam(PN_Date(), EndT); +stockArr := GetBKByDate('SH000300', EndT); +r := array(); +n := 0; +for nI := 0 to length(StockArr) - 1 do +begin + stockID := StockArr[nI]; + setsysparam(pn_stock(), StockID); + if not istradeday(EndT) then continue; + r[n]['StockID'] := StockID; + r[n]['StockName'] := StockName(StockID); + r[n]['StockZF'] := stockzf3(); + n++; +end; +return RPSIt(r, 'StockZF', 1); +``` + +部分结果截图: + +####### SortTableByFieldExt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := `array('a':(1, 2, 3, 4, 5), 'b':(-2, -3, -4, 5, 6), 'c':(3, 4, 5, 6, 7), 'd':(4, 5, 6, 7, 8)); +return SortTableByFieldExt(s, 'b'); +``` + +返回: + +####### RankValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例取上证50的成分股,获得涨幅之后,对涨幅进行排名 + +```tsl +stockArr := getbkbydate('SH000016', 20190201T); +s := select ['StockID'] as'代码', +["StockName"] as"名称", +['price'] as'收盘', +stockzf(['date'], ['date']) as'涨幅(%)' +from markettable datekey 20190201T to 20190201T of stockArr end; +RankValue(s, '涨幅(%)'); +return s; +``` + +结果: + +####### SortArray + +范例 + +```tsl +arr := array(1, 6, 3); +sortArray(arr); +return arr; +// array(1,3,6) +``` + +参考SortTableByField + +####### SortTableByField + +范例 + +```tsl +arr := array(("p1":1, "p2":2, "p3":3), +("p1":4, "p2":5, "p3":6), +("p1":66, "p2":200, "p3":36), +("p1":30, "p2":500, "p3":40)); +sortTableByField(arr, "p1", 1); +// sortdi=1按”p1”正序,sortdi=0反序 +return arr; +// 结果如图所示 +``` + +参考SortArray + +####### argsort + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +value := array(4, 8, 2, 3, 9); +return argsort(value); // 返回:array(2,3,0,1,4) +``` + +###### 增删改查 + +####### 内容 + +- AppendArray +- SeekPosInArray +- StockAmount +- DeleteNILValueByField +- FilterIn +- FilterNotIn +- IN1 +- searchsorted +- argconfirst +- DeleteColumnByField +- Inserttablebyrno +- GetValuesByFieldValue +- Arrayextend +- Arrayinsert +- Frameinsert + +####### AppendArray + +范例 + +```tsl +a := array(1, 2, 3); +AppendArray(a, 4); +return a; +``` + +返回: + +####### SeekPosInArray + +算法 + +确定查找范围L=0,H=N-1,计算中项J=(L+H)/2。 + +若arr[mid]=r或L>=H,则结束查找;否则,向下继续。 + +若arr[mid]r,说明待查找的元素值只可能在比中项元素小的范围内,则把mid-1的值赋给H,并重新计算mid,转去执行步骤2。范例 + +```tsl +return SeekPosInArray(4, array(1, 2, 3, 4, 5)); +// 返回:3 +``` + +####### StockAmount + +范例 + +```tsl +// 平安银行2011年6月30日流通A股发生变动 +SetSysParam(PN_Stock(), 'SZ000001'); +t := InfoArray(16); // 股票.股本结构表 +r1 := StockAmount(t, 20110630, 0, '变动日', '流通A股'); // Date当天 +r2 := StockAmount(t, 20110630, 1, '变动日', '流通A股'); // Date之前 +return array(r1, r2); +``` + +结果:array(3105358672.0,3105358511.0) + +####### DeleteNILValueByField + +算法对数组T字段fields的值进行遍历,如果检索到nil值,删除该行数据。范例 + +```tsl +Tdata := array(array('time':1, 'price':7.78), array('time':2)); +DeleteNILValueByField(Tdata, 'price'); +return tdata; +``` + +返回: + +####### FilterIn + +范例 + +范例01: + +```tsl +// 过滤表a中列’a’的值在array(1,2,5)集中的结果 +a := array( +("a":0, "b":0, "c":0), +("a":1, "b":0, "c":2), +("a":2, "b":1, "c":4), +("a":3, "b":1, "c":6), +("a":4, "b":2, "c":8), +("a":5, "b":2, "c":10), +("a":6, "b":3, "c":12)); +return filterin(a, array(1, 2, 5), 'a'); +``` + +范例02: + +```tsl +// 筛选满足过滤集中整行数据的子集 +a := array(); +for i := 0 to 15 do +begin + a[i]["a"] := i; + a[i]["b"] := i div 2; + a[i]["c"] := i * 2; +end; +return filterin(a, array(("a":2, "b":1, "c":4), ("a":3, "b":1, "c":4)), nil); +``` + +范例03: + +```tsl +// 筛选满足过滤集中指定列数据的子集 +a := array(); +for i := 0 to 15 do +begin + a[i]["a"] := i; + a[i]["b"] := i div 2; + a[i]["c"] := i * 2; +end; +return filterin(a, array(("a":2, "b":1), ("a":3, "b":1)), array('a', 'b')); +``` + +范例04: + +```tsl +// 返回符合过滤集中指定列数据的行下标 +a := array(); +for i := 0 to 15 do +begin + a[i]["a"] := i; + a[i]["b"] := i div 2; + a[i]["c"] := i * 2; +end; +return filterin(a, array(("a":2, "b":1), ("a":3, "b":1)), array('a', 'b'), false); +``` + +范例05: + +一维数组的过滤: + +```tsl +return FilterIn(array(1, -5, 10, 2, 10, 14, -5), array(2, 3, 10), nil); +``` + +返回结果:array(10,2,10) + +####### FilterNotIn + +范例用法同FilterIn + +```tsl +a := array(); +for i := 0 to 5 do +begin + a[i]["a"] := i; + a[i]["b"] := i div 2; + a[i]["c"] := i * 2; +end; +b := array(1, 3, 5); +c1 := FilterNotIn(a, b, "a"); // 过滤结果 +c2 := FilterNotIn(a, b, "a", false); // 过滤仅返回下标 +return array(c1, c2); +``` + +c1结果: + +c2结果: + +二维数组中,过滤行运算示例: + +```tsl +t := array( +("a":0, "b":0, "c":0), +("a":1, "b":0, "c":2), +("a":2, "b":1, "c":4), +("a":2, "b":1, "c":4), +("a":4, "b":2, "c":8), +("a":4, "b":2, "c":8), +("a":6, "b":3, "c":12)); +return filternotin(t, array(("a":2, "b":1, "c":4)), nil); +``` + +返回结果:过滤后保留重复行。 + +一维数组的过滤: + +```tsl +return FilterNotIn(array(1, -5, 10, 2, 10, 14, -5), array(2, 3, 10), nil); +``` + +返回结果:array(1,-5,14,-5) + +####### IN1 + +范例 + +```tsl +a := array(1, 2, 3, 4); +return in1(a, 3); +// 结果:1 +``` + +####### searchsorted + +范例 + +```tsl +// 数字插入 +v := array(1, 2, 3, 4, 5, 6); +return searchsorted(v, 3.5); // 返回:3 +// 字符串插入 +v := array("SH600001", "SH600004", "SH600050", "SH600305"); +return searchsorted(v, "SH600049"); // 返回:2 +``` + +####### argconfirst + +范例 + +```tsl +// 实数对比 +a := 0 - > 9; +return argconfirst(a, 3.5, 1); // 返回:4 +// 数组对比 +a := array(("a", "A"), ("b", "B"), ("c", "C"), ("d", "D")); +v := array("b", "B"); +return argconfirst(a, v, 6); // 返回:1 +``` + +####### DeleteColumnByField + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':8, 'c':5)); +return DeleteColumnByField(t1, 'a;b'); +``` + +####### Inserttablebyrno + +范例 + +范例1: + +```tsl +// 向一维数组指定位置插入一个字符串’aaa’ +t := 43456 - > 43460; +Index := 2; +rData := 'aaa'; +return InsertTablebyRno(t, Index, rData); +// 结果:array(43456,43457,"aaa",43458,43459,43460) +``` + +范例2: + +```tsl +// 向一维数组第3行插入多行的数据 +t := 44000 - > 44004; +Index := 3; +rData := array('a', 'b', 'c'); +return InsertTablebyRno(t, Index, rData); +// 结果: +array(44000, 44001, 44002, "a", "b", "c", 44003, 44004) +``` + +范例3: + +```tsl +// 向二维数组第3行插入多行的数据 +t := array(('a':10, 'b':'i', 'c':datetostr(20200319T)), +('a':50, 'b':'i', 'c':datetostr(20200318T)), +('a':60, 'b':'i', 'c':datetostr(20200317T)), +('a':40, 'b':'o', 'c':datetostr(20200316T)), +('a':20, 'b':'o', 'c':datetostr(20200313T))); +Index := 3; +rData := array(('c':0, 'b':44000, 'a':'2020-03-20')); +return InsertTablebyRno(t, Index, rData); +// 结果: +``` + +范例4: + +```tsl +// 向二维数组第1行插入多行的数据 +t := array(('a':10, 'b':'i', 'c':datetostr(20200319T)), +('a':50, 'b':'i', 'c':datetostr(20200318T)), +('a':60, 'b':'i', 'c':datetostr(20200317T)), +('a':40, 'b':'o', 'c':datetostr(20200316T)), +('a':20, 'b':'o', 'c':datetostr(20200313T))); +Index := 1; +rData := array(('c':'2020', 'b':'AAA', 'a':44456), +('c':'2020', 'b':'BBB', 'a':44566)); +return InsertTablebyRno(t, Index, rData); +// 结果: +``` + +####### GetValuesByFieldValue + +范例 + +```tsl +t := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':4)); +return GetValuesByFieldValue(t, 'b', 4); // 返’b’列值为4的所有记录 +``` + +####### Arrayextend + +范例 + +```tsl +a := Letters(1 - > 6); +return arrayextend(a, 2, array('d', 'e')); +``` + +返回:array("A","B","d","e","C","D","E","F") + +####### Arrayinsert + +范例 + +```tsl +a := Letters(1 - > 6); +return Arrayinsert(a, 2, 3); +``` + +返回:array("A","B",3,"C","D","E","F") + +####### Frameinsert + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := load_dataset_iris(); +return frameInsert(data, 1, '新列', 0); +``` + +###### 数组操作 + +####### 内容 + +- OutPutTableToCanBeUnderstood +- SeperateTable +- Unitary +- Reverse +- DescartesJoin +- TableVectorizeArray +- DataProcess_MF +- AbnormalData +- QKsplit_Trailing +- QKsplit_Resampling +- WebFormatToRung +- RPSValue +- ZValue +- QKsplit_ToDate +- GroupByFieldValue +- FilterOneDimEx2 +- GroupRankIt +- ElementWhere +- Histogram +- FrameGetSubByReg +- Factorize +- GroupPercentrankIt +- SparseMatFill +- ArrayAddGap +- dumies_decode +- GroupTransformByFunc +- Framedrop_duplicates +- Field_ReSortCols +- Framedrop_na +- Framemerge +- Frameqcut +- Frameupdate +- GroupZscoreIt +- get_dummies +- get_dummies2 +- framePivot_table +- framecut +- frameMelt +- GroupDemeanIt +- ArrDropDuplicate + +####### OutPutTableToCanBeUnderstood + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return OutPutTableToCanBeUnderstood(array(1, 2, 3)); +``` + +返回: + +####### SeperateTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +依据字段SepField排序,若字段不存在则返回空数组。 + +若分割数大于行数,则每行单独生产一个子表;若分割数小于行数,则按int(行数/分割数)去合并表行数,超出部分单作为一个子表。范例 + +```tsl +t := `array('a':(1, 2, 3, 4), 'b':(2, 3, 4, 5), 'c':(3, 4, 5, 6), 'd':(4, 5, 6, 7), 'e':(5, 6, 7, 8), 'f':(7, 8, 9, 10)); +return SeperateTable(t, 'a', 2); +``` + +返回: + +####### Unitary + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := `array('a':(1, 2, 3, 4), 'b':(2, 3, 4, 5), 'c':(3, 4, 5, 6), 'd':(4, 5, 6, 7), 'e':(5, 6, 7, 8), 'f':(7, 8, 9, 10)); +Unitary(t, 'b', 0, 10); +return t; +``` + +返回: + +####### Reverse + +范例 + +```tsl +// 倒置数组 +setsysparam(pn_stock(), "SZ000002"); +setsysparam(pn_date(), 20210601t); +arr := nday(10, "date", datetostr(sp_time()), "close", close()); +return reverse(arr); +``` + +####### DescartesJoin + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return DescartesJoin(1 - > 3, 21 - > 22, 3); +``` + +####### TableVectorizeArray + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := ones(10, 3); +s := array(1, 2, 3); +return TableVectorizeArray(t, s, '-'); +``` + +####### DataProcess_MF + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +四分位法:上边界=中位数+5.2*medianof(abs(yi-中位数)),下边界=中位数-5.2*medianof(abs(yi-中位数)),其中medianof表示求序列中位数。超出上边界的数改为上边界,低于下边界的数改为下边界。 + +3倍标准差法:上边界=μ+3σ,下边界=μ-3σ,其中u表示均值,σ表示标准差。超出上边界的数改为上边界,低于下边界的数改为下边界。范例 + +```tsl +t := `array(array(1, 100, 101, 102, 103, 1000), array(2, 200, 201, 202, 203, 2000)); +return DataProcess_MF(t, 'median'); +``` + +返回: + +####### AbnormalData + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +中位数法:上边界=中位数+5.2*medianof(abs(yi-中位数)),下边界=中位数-5.2*medianof(abs(yi-中位数)),其中medianof表示求序列中位数。超出上边界的数改为上边界,低于下边界的数改为下边界。 + +3倍标准差法:上边界=μ+3σ,下边界=μ-3σ,其中u表示均值,σ表示标准差。超出上边界的数改为上边界,低于下边界的数改为下边界。 + +四分位法:左边界=14位数-1.5*(中位数-14位数),下边界=34位数+1.5*(34位数-中位数),。超出右边界的数改为右边界,低于左边界的数改为左边界。 + +范例 + +范例01:返回奇异值的位置及处理后的结果。 + +```tsl +t := array(1, 100, 101, 102, 103, 1000); +AbnormalData(t, "median", r); +return r; +``` + +返回: + +其中,0和5为修改的行,1和1000是对应的原值,93.7和109.3是修改后的值 + +范例02:对源数据列增加一列奇异值处理后的结果 + +```tsl +col := 'SH000001'; +setsysparam(pn_stock(), col); +setsysparam(pn_date(), 20240930T); +setsysparam(pn_cycle(), cy_day()); +days := 100; +// SH000001在20240930最近100天的行情数据中设置三个奇异值 +t := Nday(days, '日期', datetostr(sp_time()), col, close()); +t[29, col] := 1500; +t[59, col] := 4500; +t[79, col] := 6000; +// 找到数组指定列奇异值,以中位数法为例 +tyc := AbnormalData(t[:, col], "median", abn); +t[:, col$"_奇异值处理"] := tyc; +return t; +``` + +返回结果:增加列"SH000001\_奇异值处理" + +####### QKsplit_Trailing + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return QKsplit_Trailing(20100101T, 20110101T); +``` + +####### QKsplit_Resampling + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return QKsplit_Resampling(20100101T, 20110101T, cy_year()); +``` + +####### WebFormatToRung + +用途:按指定格式输出结果。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array('a':('b':('c':(nil, nan, 3), 'd':2), 'e':nan)); +return WebFormatToRung(a); // array("a":("b":("c":("-","-",3),"d":2),"e":"-")) +``` + +####### RPSValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +指定字段从大到小排序。 + +RPS=100-100/(数据总数量-1)\*所在行标。范例 + +```tsl +stockArr := getbkbydate('SH000016', 20190201T); +s := select ['StockID'] as'代码', +["StockName"] as"名称", +['price'] as'收盘', +stockzf(['date'], ['date']) as'涨幅(%)' +from markettable datekey 20190201T to 20190201T of stockArr end; +RPSValue(s, '涨幅(%)'); +return s; +``` + +返回: + +####### ZValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +z=(x-μ)/σ;其中z为标准分数;x为某一具体分数,μ为平均数,σ为标准差。范例 + +```tsl +stockArr := getbkbydate('SH000016', 20190201T); +s := select ['StockID'] as'代码', +["StockName"] as"名称", +['price'] as'收盘', +stockzf(['date'], ['date']) as'涨幅(%)' +from markettable datekey 20190201T to 20190201T of stockArr end; +ZValue(s, '涨幅(%)'); +return s +``` + +返回: + +####### QKsplit_ToDate + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +return QKsplit_ToDate(20220704T); +``` + +####### GroupByFieldValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +依据字段GroupField值进行排序 + +划分四个区间,小于等于最小值,最小值到最大值之间的每一个步长区间(包括步长末值),临近最大值不足一个步长的区间(包括最大值),大于最大值区间。用FilterTableEx函数来统计指定区间的数量。范例 + +```tsl +data := select * from tradetable datekey 20180903t to 20180904T of'sz000001'end; +return GroupByFieldValue(data, 'close', 1, 20, 0.1); +``` + +返回: + +####### FilterOneDimEx2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := array(1, 2, 3, 4, 5, 6); +return FilterOneDimEx2(s, 4); +// 返回:4 +``` + +####### GroupRankIt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +T := array( +("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +return GroupRankIt(T, 'G', 'V1'); // array(1,1,2,2,3,3) +``` + +####### ElementWhere + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +con := array(1, 0, 1, 1, 1, 0); +x := array(1, 2, 3, 4, 5, 6); +y := array(11, 12, 13, 14, 15, 16); +return ElementWhere(con, x, y); // array(1,12,3,4,5,16) +``` + +####### Histogram + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +return Histogram(Randn(0, 1, 1000), array(-3, 0.5) - > 3, '0.00'); +``` + +范例二: + +```tsl +data := randn(0, 1, 1000, array('a', 'b')); +return Histogram(data, array(-3, 0.5) - > 3, '0.00'); +``` + +####### FrameGetSubByReg + +范例 + +```tsl +T := array((13:1, "V1":1, "V2":11, 12:21, 'R1w':1), +(13:0, "V1":2, "V2":12, 12:22, 'R1w':1), +(13:1, "V1":3, "V2":13, 12:23, 'R1w':1), +(13:0, "V1":4, "V2":14, 12:24, 'R1w':1), +(13:1, "V1":5, "V2":15, 12:25, 'R1w':1), +(13:0, "V1":6, "V2":16, 12:26, 'R1w':1)); +return frameGetSubByReg(T, '1'); +``` + +array( + +(21,1,"V1":1,"R1w":1), + +(22,0,"V1":2,"R1w":1), + +(23,1,"V1":3,"R1w":1), + +(24,0,"V1":4,"R1w":1), + +(25,1,"V1":5,"R1w":1), + +(26,0,"V1":6,"R1w":1)) + +####### Factorize + +范例 + +```tsl +value := array('a', 'd', 'c', 'a', 'b'); +labels := factorize(value, true, -1, uniques); +echo uniques; // array("a","b","c","d") +return labels; // array(0,3,2,0,1); +``` + +####### GroupPercentrankIt + +用途:进行大小写转换。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +T := array(("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +return GroupPercentrankIt(T, 'G', 'V1'); // array(0.0,0.0,0.5,0.5,1.0,1.0) +``` + +####### SparseMatFill + +用途:解析输入并返回结果。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array((3:4), ('A':2)); +SparseMatFill(a, -1); +return a; // array((3:4,"A":-1),(3:-1,"A":2)) +``` + +####### ArrayAddGap + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array('alpha(%)':3); +ArrayAddGap(a, '风险'); +a['beta'] := 3; +return a; // array("alpha(%)":3,"-----风险-----":"----------","beta":3) +``` + +####### dumies_decode + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := array( +("申万房地产":1, "申万有色金属":0, "申万银行":0), +("申万房地产":1, "申万有色金属":0, "申万银行":0), +("申万房地产":0, "申万有色金属":1, "申万银行":0), +("申万房地产":0, "申万有色金属":0, "申万银行":1), +("申万房地产":0, "申万有色金属":1, "申万银行":0)); +return dumies_decode(data); +// array("申万房地产","申万房地产","申万有色金属","申万银行","申万有色金属") +``` + +####### GroupTransformByFunc + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +T := array(("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +fp := function (v, g); +begin + return rankof([v], [v]); +end; +return GroupTransformByFunc(T, 'G', 'V1', fp); // array(3,3,2,2,1,1) +``` + +####### Framedrop_duplicates + +范例 + +```tsl +data := load_dataset_iris(); +return frameDrop_duplicates(data, 'Species', 'f', '原下标'); +``` + +####### Field_ReSortCols + +范例 + +范例01 + +```tsl +data := TSUT_Data_ZSZF(); +colpriority := array('截止日':-1, "中证500":100); +return field_resortcols(data, colpriority); +``` + +####### Framedrop_na + +范例 + +```tsl +data := array((nan, 8), (1, 3, 3)); +return frameDrop_Na(data, 1, 0); +``` + +####### Framemerge + +范例 + +范例1: + +```tsl +left := `array('a':3 - > 5, 'b':rand(3)); +right := `array('a':1 - > 4, 'b':rand(4), 'c':rand(4) * 10); +return frameMerge(left, right, 'a'); +``` + +范例2 + +```tsl +// 多字段merge +left := `array('a':3 - > 5, 'b':rand(3)); +left[:, 'c'] := left[:, 'a']; +right := `array('a':1 - > 4, 'b':rand(4), 'c':rand(4) * 10); +right[:, 'c'] := right[:, 'a']; +names := array('a', 'c'); +return frameMerge(left, right, name, 'lfet', nil, true); +``` + +范例3 + +```tsl +// 只更名right +left := `array('a':3 - > 5, 'b':rand(3)); +right := `array('a':1 - > 4, 'b':rand(4), 'c':rand(4) * 10); +return frameMerge(left, right, 'a', 'full', array(nil, '_x')); +``` + +####### Frameqcut + +- OutPutTableToCanBeUnderstood +- SeperateTable +- Unitary +- Reverse +- DescartesJoin +- TableVectorizeArray +- AbnormalData +- DataProcess_MF +- ZValue +- RPSValue +- FilterOneDimEx2 +- GroupByFieldValue +- WebFormatToRung +- QKsplit_Trailing +- QKsplit_ToDate +- QKsplit_Resampling +- Factorize +- dumies_decode +- SparseMatFill +- ElementWhere +- ArrayAddGap +- GroupPercentrankIt +- GroupRankIt +- GroupTransformByFunc +- FrameGetSubByReg +- Histogram +- Framedrop_duplicates +- Field_ReSortCols +- Framedrop_na +- Framemerge +- Frameqcut +- Frameupdate +- GroupZscoreIt +- get_dummies +- get_dummies2 +- framePivot_table +- framecut +- frameMelt +- GroupDemeanIt +- ArrDropDuplicate + +####### Frameupdate + +范例 + +```tsl +left := `array('a':3 - > 5, 'b':rand(3)); +right := `array('a':1 - > 4, 'b':rand(4), 'c':rand(4) * 10); +return frameUpdate(left, right, 'a'); +``` + +####### GroupZscoreIt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +T := array( +("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +return GroupZscoreIt(T, 'G', 'V1');?// array(-1.0,-1.0,0.0,0.0,1.0,1.0) +``` + +####### get_dummies + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array('a', 'b', 'c', 'a', nan, nil); +t := get_dummies(a, uniques); +echo tostn(uniques); // array(NIL,"a","b","c",NAN) +return t; +``` + +####### get_dummies2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +b := array("申万房地产", "申万房地产", "申万有色金属", "申万银行", "申万有色金属"); +return get_dummies2(b); +``` + +####### framePivot_table + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 指定条件,首列为申万行业,后续列标为日期,按平均值汇总值为涨幅、振幅的的数据透视表数据 +stocks := GetBKByDate("SH000010", 20210525t); +begt := 20210515T; +endt := 20210525T; +t := select ['StockID'] as"代码", +["StockName"] as"名称", +datetostr(['date']) as"日期", +["close"] as"收盘价", +spec(specdate(stockzf3(), ['date']), ['StockID']) as"涨幅", +spec(specdate(stockzdf3(), ['date']), ['StockID']) as"振幅", +spec(base(10029), ['StockID']) as"申万行业" +from markettable datekey begt to endt of stocks end; +index := "申万行业"; +colunms := "日期"; +vals := array("涨幅", "振幅"); +aggfunc := "avg"; +return framePivot_table(t, index, colunms, vals, aggfunc); +``` + +####### framecut + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例1: + +```tsl +a := array(0, 59, 60, 70, 80, 99, 100); +bins := array(60, 80); +return framecut(a, bins, 0); +// array(0,0,1,1,2,2,2) +``` + +范例2 + +```tsl +a := array(0, 59, 60, 70, 80, 99, 100); +bins := 5; +return framecut(a, bins, 0); +// array(0,2,3,3,4,4,4) +``` + +####### frameMelt + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array( +('截止日':20210101, 'SH000300':1, 'SH000301':3), +('截止日':20210102, 'SH000300':9, 'SH000301':2), +); +ID_names := array('截止日'); +return frameMelt(t, '截止日', nil, '代码', '得分'); +``` + +####### GroupDemeanIt + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例1: + +```tsl +T := +array( +("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +return GroupDemeanIt(T, 'G', 'V1'); // array(-2.0,-2.0,0.0,0.0,2.0,2.0) +``` + +范例2 + +```tsl +T := array( +("G":1, "V1":1, "V2":11, "V3":21), +("G":0, "V1":2, "V2":12, "V3":22), +("G":1, "V1":3, "V2":13, "V3":23), +("G":0, "V1":4, "V2":14, "V3":24), +("G":1, "V1":5, "V2":15, "V3":25), +("G":0, "V1":6, "V2":16, "V3":26)); +return GroupDemeanIt(T, 'G', array('V1', 'V2')); +``` + +####### ArrDropDuplicate + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := array(("A":1, "B":NAN), ("A":1, "B":2), ("A":1, "B":NAN), ("A":1, "B":2)); +return ArrDropDuplicate(data); +// 结果:array(("A":1,"B":NAN),("A":1,"B":2)) +``` + +###### 数组取值 + +####### 内容 + +- ColumnValue +- GetSubTableByField +- GetTopN +- FilterTableEx +- ColumnValue2 +- GetBottomN +- FilterOneDimEx +- GetDistinctValue +- GetMiddleN +- FilterTable +- GetSubField +- GetSubTable +- Arraygetdefault +- Arraysetdefault +- Arraysetdefault2 +- Randomchoice + +####### ColumnValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := select ['StockID'] as'代码', +["StockName"] as"名称", +['price'] as'收盘' +from markettable datekey 20190101T to 20190201T of'SZ000001'end; +return ColumnValue(s, '收盘'); +``` + +返回: + +####### GetSubTableByField + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +setsysparam(pn_stock(), 'SZ000001'); +r := nday(10, 'time', datetostr(sp_time()), 'close', close(), 'open', open(), 'high', high()); +return GetSubTableByField(r, 'time;close'); +// 功能相当于使用子矩阵取数 +return r[:, array('time', 'close')]; +``` + +返回: + +####### GetTopN + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':33)); +return GettopN(t2, 2); +``` + +####### FilterTableEx + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33)); +return FilterTableEx(t2, 'c', 'IN', 13, 30); // 取13<=[ 'c']<=30 +``` + +####### ColumnValue2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'b':2, 'c':13), ('a':3, 'c':33, 'b':3), ('a':3, 'b':6, 'c':43), ('a':5, 'c':53, 'b':5)); +return ColumnValue2(t2, 'a;c'); +``` + +####### GetBottomN + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':33)); +return GetBottomN(t2, 2); +``` + +####### FilterOneDimEx + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(1, 2, 12, 3.7, 14); +return FilterOneDimEx(t, 'IN', 2, 7); +``` + +####### GetDistinctValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return GetDistinctValue(t2, 'a'); +``` + +####### GetMiddleN + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':4, 'c':33), ('a':5, 'c':33)); +return GetMiddleN(t2, 2, 3); +``` + +####### FilterTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 'SZ002664'在20211231时的分红送股数据 +setsysparam(pn_stock(), 'SZ002664'); +return FilterTable(Infoarray(18), 20211231); +``` + +####### GetSubField + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(('a':8, 'b':7), ('a':6, 'b':9)); +return GetSubField(a, 'a'); // 从a表中取第’a列’ +``` + +####### GetSubTable + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array((1, 2, 4), (11, 12, 14)); +b := array(0, 2); +return GetSubTable(a, b); +``` + +####### Arraygetdefault + +- ColumnValue +- GetSubTableByField +- FilterTableEx +- GetBottomN +- GetMiddleN +- GetTopN +- FilterOneDimEx +- GetDistinctValue +- ColumnValue2 +- FilterTable +- GetSubField +- GetSubTable +- Arraygetdefault +- Arraysetdefault +- Arraysetdefault2 +- Randomchoice + +####### Arraysetdefault + +- ColumnValue +- GetSubTableByField +- FilterTableEx +- GetBottomN +- GetMiddleN +- GetTopN +- FilterOneDimEx +- GetDistinctValue +- ColumnValue2 +- FilterTable +- GetSubField +- GetSubTable +- Arraygetdefault +- Arraysetdefault +- Arraysetdefault2 +- Randomchoice + +####### Arraysetdefault2 + +- ColumnValue +- GetSubTableByField +- FilterTableEx +- GetBottomN +- GetMiddleN +- GetTopN +- FilterOneDimEx +- GetDistinctValue +- ColumnValue2 +- FilterTable +- GetSubField +- GetSubTable +- Arraygetdefault +- Arraysetdefault +- Arraysetdefault2 +- Randomchoice + +####### Randomchoice + +- ColumnValue +- GetSubTableByField +- FilterTableEx +- GetBottomN +- GetMiddleN +- GetTopN +- FilterOneDimEx +- GetDistinctValue +- ColumnValue2 +- FilterTable +- GetSubField +- GetSubTable +- Arraygetdefault +- Arraysetdefault +- Arraysetdefault2 +- Randomchoice + +###### 集合运算 + +####### 内容 + +- MergeArray +- FilterIntersectionPart +- FilterIntersectionPart2 +- DistinctStr +- IntersectionPart +- QuickIntersectionPart +- Frameconcat + +####### MergeArray + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('b':12, 'a':1, 'c':13, 'd':'d')); +t2 := array(('a':2, 'b':22, 'c':23, 'e':'ee')); +t3 := array(('a':2, 'b':22, 'd':23, 'e':'ee')); +return MergeArray(t1, t2, t3); // 将数组t1,t2,t3合并 +``` + +####### FilterIntersectionPart + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':10, 'c':13), ('a':2, 'b':17, 'c':13)); +t2 := array(('a':2, 'b':22, 'c':23), ('a':1, 'b':14, 'c':13), ('a':3, 'b':12, 'c':13)); +return FilterIntersectionPart(t1, t2, 'a', 'IN'); // t1 与t2的交集 +``` + +####### FilterIntersectionPart2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(1, 2, 3, 4); +t2 := array(3, 4, 5, 6); +return FilterIntersectionPart2(t1, t2, 'IN'); // t1 与t2的交集 +``` + +####### DistinctStr + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array('w', 'd', 'f', 'd', 'e'); +return DistinctStr(a); // 保留不相同的,相同的只保留一个 +``` + +####### IntersectionPart + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(1.00, 3.00, 2.00, 9.00, 8.00); +t2 := array(3.00, 0.00, 7.00, 8.00, 1.00, 5.00); +return IntersectionPart(t1, t2); +``` + +####### QuickIntersectionPart + +范例 + +```tsl +t1 := array(1.00, 3.00, 2.00, 9.00, 8.00); +t2 := array(3.00, 0.00, 7.00, 8.00, 1.00, 5.00); +return IntersectionPart(t1, t2); +``` + +####### Frameconcat + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := ones(3, 3); +b := ones(2, 3); +return frameConCat(array(a, b)); +``` + +###### 统计函数 + +####### 内容 + +- GeoMeanByColumn +- SumValueByColumn +- AverageValueByColumn +- PercentValueByField +- MedianByColumn +- VarByColumn +- SumValueByColumn2 +- SkewByColumn +- AveDevByColumn +- SumValueByRow2 +- MaxValueByColumn +- DevsqByColumn +- KurtByColumn +- SumValueByRow +- HarMeanByColumn +- StatByColumn +- AverageByColumn +- StdevByColumn +- MinValueByColumn +- Describe +- Framecorrel +- Framecov +- Framehhi +- Framelag_zf +- Framepct_change +- Framevaluecounts +- Simpledescribe + +####### GeoMeanByColumn + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':5, 'c':5)); +return GeoMeanByColumn(t1, 'b'); +// 结果:4.47 +``` + +####### SumValueByColumn + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':8, 'c':5)); +return SumValueByColumn(t1, 'b'); +// 结果:12 +``` + +####### AverageValueByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return AverageValueByColumn(t2, 'c', 1, 3); +// 结果:43 +``` + +####### PercentValueByField + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return PercentValueByField(t2, 'c', 0.1); +// 结果:19 +``` + +####### MedianByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return MedianByColumn(t2, 'c'); +// 结果:38 +``` + +####### VarByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return VarByColumn(t2, 'c'); +// 结果:291.67 +``` + +####### SumValueByColumn2 + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return SumValueByColumn2(t2, 'c', 1, 2); +// 结果:76 +``` + +####### SkewByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return SkewByColumn(t2, 'c'); +// 结果:-0.75 +``` + +####### AveDevByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return AveDevByColumn(t2, 'c'); +// 结果:12.5 +``` + +####### SumValueByRow2 + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return SumValueByRow2(t2, 1, 0, 1); +// 结果:36 +``` + +####### MaxValueByColumn + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return MaxValueByColumn(t2, 'c'); +// 结果:53 +``` + +####### DevsqByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':5, 'c':5)); +return DevsqByColumn(t1, 'b'); +// 结果:0.5 +``` + +####### KurtByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return KurtByColumn(t2, 'c'); +// 结果:0.34 +``` + +####### SumValueByRow + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return SumValueByRow(t2, 2); +// 结果:46 +``` + +####### HarMeanByColumn + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':5, 'c':5)); +return HarMeanByColumn(t1, 'b'); +// 结果:4.44 +``` + +####### StatByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := `array('a':(1, 2, 3, 4, 5), 'b': (-2, -3, -4, 5, 6), 'c': (3, 4, 5, 6, 7), 'd': (4, 5, 6, 7, 8)); +return StatByColumn(s, 'a', 'MAX'); +// 返回a列最大值:5 +``` + +####### AverageByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':8, 'c':5)); +return AverageByColumn(t1, 'b'); +// 结果:6 +``` + +####### StdevByColumn + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return StdevByColumn(t2, 'c'); +// 结果:17.08 +``` + +####### MinValueByColumn + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t2 := array(('a':2, 'c':13), ('a':3, 'c':33), ('a':3, 'c':43), ('a':5, 'c':53)); +return MinValueByColumn(t2, 'c'); +// 结果:13 +``` + +####### Describe + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +load_dataset_iris(data); +return Describe(data); +``` + +范例02: + +```tsl +return Describe(randn(0, 1, 1000), array(0.05, 0.1) - > 0.95); +``` + +####### Framecorrel + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := TSUT_Data_ZSZF()[:, 1:]; +return frameCorrel(data); +``` + +####### Framecov + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := TSUT_Data_ZSZF()[:, 1:]; +return frameCov(data); +``` + +####### Framehhi + +- SumValueByColumn +- SumValueByColumn2 +- SumValueByRow +- SumValueByRow2 +- MaxValueByColumn +- MinValueByColumn +- AverageValueByColumn +- AverageByColumn +- HarMeanByColumn +- GeoMeanByColumn +- DevsqByColumn +- KurtByColumn +- MedianByColumn +- SkewByColumn +- StdevByColumn +- VarByColumn +- AveDevByColumn +- PercentValueByField +- StatByColumn +- Describe +- Framecorrel +- Framecov +- Framehhi +- Framelag_zf +- Framepct_change +- Framevaluecounts +- Simpledescribe + +####### Framelag_zf + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(10, 5, 8, 2); +return frameLag_ZF(t); // array(INF,-50.0,60.0,-75.0) +return frameLag_ZF(t, -1); // array(-50.0,60.0,-75.0,INF) +``` + +####### Framepct_change + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(10, 5, 8, 2); +return framePct_change(t); // array(INF,-50.0,60.0,-75.0) +return framePct_change(t, -1); // array(100.0,-37.5,300.0,INF); // 注意此时并不是未来涨幅 +``` + +####### Framevaluecounts + +- SumValueByColumn +- SumValueByColumn2 +- SumValueByRow +- SumValueByRow2 +- MaxValueByColumn +- MinValueByColumn +- AverageValueByColumn +- AverageByColumn +- HarMeanByColumn +- GeoMeanByColumn +- DevsqByColumn +- KurtByColumn +- MedianByColumn +- SkewByColumn +- StdevByColumn +- VarByColumn +- AveDevByColumn +- PercentValueByField +- StatByColumn +- Describe +- Framecorrel +- Framecov +- Framehhi +- Framelag_zf +- Framepct_change +- Framevaluecounts +- Simpledescribe + +####### Simpledescribe + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01 + +```tsl +load_dataset_iris(data); +return SimpleDescribe(data); +``` + +范例02 + +```tsl +return SimpleDescribe(randn(0, 1, 1000), array(0.05, 0.1) - > 0.95); +``` + +###### 重构函数 + +####### 内容 + +- NormalTabletoStrSubscript +- RenameField +- Field_AddSuffix +- RenameFieldByFormat +- Field_AddPrefix +- ReIndex +- ReIndexCopy +- Reshape +- Frame_addprefix +- Frame_addsuffix + +####### NormalTabletoStrSubscript + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +s := nday(10, 'time', datetostr(sp_time()), 'close', close()); +return NormalTabletoStrSubscript(s, 'time'); +``` + +把 time列的数据变为行标 + +---变为--》 + +####### RenameField + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4, 'c':9), ('a':7, 'b':8, 'c':5)); +return RenameField(t1, 'a', 'aaa'); // 将t1中的字段’a’改为’aaa’ +// 结果:1 +``` + +####### Field_AddSuffix + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 给随机数组批量加后缀 +T := rand(10, 10); +Suffix := "@A"; +Ifcopy := true; +return Field_AddSuffix(t, Suffix, Ifcopy); +``` + +####### RenameFieldByFormat + +用途:按指定格式输出结果。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 给随机数组批量加后缀 +T := rand(10, 10); +Suffix := '%s'$"@A"; +Ifcopy := true; +return RenameFieldByFormat(t, Suffix, Ifcopy); +``` + +####### Field_AddPrefix + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 给随机数组批量加前缀 +T := rand(10, 10); +Suffix := "A"; +Ifcopy := true; +return Field_AddPrefix(t, Suffix, Ifcopy); +``` + +####### ReIndex + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 修改数字列名数组为字符串列名数组,即将0,1,2(自增数字)列名重构为"a","b","c"列名的数组 +A := rand(10, 3); +s := array("a", "b", "c"); +ReIndex(A, nil, s); +return A; + +// 修改数字行标数组为字符串行标数组,即将0,1,2(自增数字)行标重构为"a","b","c"行标的数组 +A := rand(3, 3); +s := array("a", "b", "c"); +ReIndex(A, s); +return A; + +// 通过设置行标为nil进行删除该行记录 +A := array("A":0, "B":1, "D":2, "E":3); +ReIndex(A, array("A":"A1", "D":nil)); +return A; +// 返回:array("A1":0,"B":1,"E":3); + +// 如果我们要对多维数组进行处理 +A := rand(10, array("A", "B", "D", "E"); // 初始化一个四列的二维矩阵 +ReIndex(A, nil, array("A":"A1", "D":nil)); +return A; +// 说明,第2个参数为nil表示对第一维的下标不进行变动,因此我们修改列"A"为"A1",并删除"D"列。 + +// 利用Reindex做列的交换 +A := array(1, 2, 3, 4, 5); +reIndex(A, array(0:4, 4:0)); +return A; +// 结果为array(5,2,3,4,1); +``` + +####### ReIndexCopy + +参考ReIndex + +范例 + +实现:将指定列下标转为数组的行下标--可用于快速建立哈希表 + +```tsl +setsysparam(pn_stock(), "SH000001"); +setsysparam(pn_date(), 20240822T); +t := nday(10, 'time', datetostr(sp_time()), 'close', close()); +return reindexcopy(t, t[:, "time"]); +``` + +转化结果: + +====》转变为: + +####### Reshape + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 默认拉伸为一个一维数组 +A := Rand(3, 6); +return B := Reshape(A); + +// A 是一个4*3的矩阵,拉伸为一个2*6的矩阵 +A := array((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)); +return Reshape(A, 2, 6); +``` + +####### Frame_addprefix + +- RenameField +- ReIndex +- ReIndexCopy +- Reshape +- NormalTabletoStrSubscript +- RenameFieldByFormat +- Field_AddSuffix +- Field_AddPrefix +- Frame_addprefix +- Frame_addsuffix + +####### Frame_addsuffix + +- RenameField +- ReIndex +- ReIndexCopy +- Reshape +- NormalTabletoStrSubscript +- RenameFieldByFormat +- Field_AddSuffix +- Field_AddPrefix +- Frame_addprefix +- Frame_addsuffix + +###### 稀疏矩阵 + +####### 内容 + +- Sparse1 +- Sparse2 +- Speye +- Sprand1 +- Sprand2 +- Sprandn1 +- Sprandn2 +- Sprandsym1 +- Sprandsym2 +- Sparsefull +- Spones +- Spnnz +- Spnonzeros +- Ifsparse +- Spdiags1 +- Spdiags2 +- Spdiags3 +- Spdiags4 + +####### Sparse1 + +范例 + +```tsl +// 将矩阵S由满矩阵格式转化为稀疏格式 +S := array((0, 0, 4, 0, 0), +(0, 1, 0, 0, 0), +(0, 0, 0, 0, 0), +(3, 0, 0, 0, 0), +(0, 0, 0, 0, 5)); +return sparse1(S); +``` + +####### Sparse2 + +范例 + +```tsl +// 根据i,j,v三元组生成稀疏格式矩阵 +i := array(0, 1, 2, 3); +j := array(3, 1, 4, 2); +v := array(5, 3, 2, 4); +return sparse2(i, j, v, 5, 5); +``` + +####### Speye + +范例 + +```tsl +// 创建m*m稀疏单位矩阵 +A := speye(4); +return A; +``` + +####### Sprand1 + +范例 + +```tsl +// 创建与矩阵S相同结构的稀疏均匀随机矩阵 +S := array((0, 0, 3, 0, 0), +(0, 0, 0, 0, 0), +(0, 0, 0, 5, 0), +(0, 2, 0, 0, 0), +(0, 0, 0, 0, 4)); +return sprand1(S); +``` + +####### Sprand2 + +范例 + +```tsl +// 创建10*10稀疏均匀随机矩阵 +A := sprand2(10, 10, 0.3); +return A; +``` + +####### Sprandn1 + +范例 + +```tsl +// 创建与矩阵S相同结构的稀疏正态随机矩阵 +S := array((0, 0, 0, 0, 0), +(0, 0, 0, 5, 0), +(3, 0, 0, 0, 0), +(0, 0, 2, 0, 0), +(0, 0, 0, 0, 4)); +return sprandn1(S); +``` + +####### Sprandn2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建10*10稀疏正态随机矩阵 +A := sprandn2(10, 10, 0.2); +return A; +``` + +####### Sprandsym1 + +范例 + +```tsl +// 创建与矩阵S相同结构的对称稀疏正态随机矩阵 +S := array((6, 1, 0, 14, 0), +(0, 7, 0, 0, 15), +(1, 0, 8, 0, 0), +(0, 2, 0, 9, 0), +(0, 0, 3, 0, 10)); +return sprandsym1(S); +``` + +####### Sprandsym2 + +范例 + +```tsl +// 创建10*10对称稀疏正态随机矩阵 +A := sprandnsym2(10, 0.2); +return A; +``` + +####### Sparsefull + +范例 + +```tsl +// 将S由稀疏格式矩阵转化为5*5满矩阵格式 +S := array(0:(0:1), 2:(2:3), 3:(3:4)); +return sparsefull(S, 5, 5); +``` + +####### Spones + +范例 + +```tsl +// 将S中非零元素替换为1 +S := array(0:(0:1), 2:(2:3), 3:(3:4)); +return spones(S, 1); +``` + +####### Spnnz + +范例 + +```tsl +// 稀疏正态随机矩阵A中非零元素数目 +A := Sprandn2(5, 5, 0.2); +return spnnz(A); // 返回4(随机) +``` + +####### Spnonzeros + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 提取稀疏正态随机矩阵A中非零元素 +A := Sprandn2(5, 5, 0.2); +return Spnonzeros(A); +``` + +####### Ifsparse + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +// 判断矩阵S是否为稀疏矩阵 +S := array(3:2, "B":3); +return ifsparse(S); // 返回0 +``` + +####### Spdiags1 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 提取矩阵A中非零对角线 +A := array((6, 0, 13, 0, 0), +(0, 7, 0, 14, 0), +(1, 0, 8, 0, 15), +(0, 2, 0, 9, 0), +(0, 0, 3, 0, 10)); +return spdiags1(A); +``` + +####### Spdiags2 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 提取矩阵A中第-2,0,2条对角线,按列排列 +A := array((6, 0, 13, 0, 0), +(0, 7, 0, 14, 0), +(1, 0, 8, 0, 15), +(0, 2, 0, 9, 0), +(0, 0, 3, 0, 10)); +d := array(-2, 0, 2); +return spdiags2(A, d); +``` + +####### Spdiags3 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 将矩阵A中d指定的对角线替换为B中的列 +B := array((5, 10, 15), +(4, 9, 14), +(3, 8, 13), +(2, 7, 12), +(1, 6, 11)); +d := array(-2, 0, 2); +A := array((6, 0, 13, 0, 0), +(0, 7, 0, 14, 0), +(1, 0, 8, 0, 15), +(0, 2, 0, 9, 0), +(0, 0, 3, 0, 10)); +return spdiags3(B, d, A); +``` + +####### Spdiags4 + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 根据对角矩阵B创建稀疏带状矩阵 +B := array((5, 10, 15), +(4, 9, 14), +(3, 8, 13), +(2, 7, 12), +(1, 6, 11)); +d := array(-2, 0, 2); +m := 5; +n := 5; +return spdiags4(B, d, m, n); +``` + +###### 数据比较 + +####### 内容 + +- TwoRDateCompare_M1 +- CompareDataOfDifferentDataProvider + +####### TwoRDateCompare_M1 + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +// 返回板块申万数字媒体机构持股情况及变化 +BkName := "申万数字媒体"; +RDate := 20220331; +RDate2 := 20210331; +t1 := Stocks_SharesByOrgan_Call(BkName, RDate, -1, 0); +t2 := Stocks_SharesByOrgan_Call(BkName, RDate2, -1, 0); +return TwoRDateCompare_M1(t1, t2, RDate, RDate2, "代码", 0, +FieldCountOfStrSubscript(t1) - 2, true, false); +``` + +####### CompareDataOfDifferentDataProvider + +- TwoRDateCompare_M1 +- CompareDataOfDifferentDataProvider + +###### 表格显示 + +####### 内容 + +- Pivot +- Pivot_table +- Show3DTable +- Show2DTable +- ShowTableByField +- ShowTableByUnit +- ShowTableByInverse +- QuickRecordExist +- RotateTable +- NonIntersectionPart +- FooterValue +- FooterAverage +- FooterSum +- SetRowDefaultValue +- InverseTable +- GetSubTableByKey +- TableSelect +- TableType +- GetSubTableFreeParam +- ExpandTable + +####### Pivot + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 指定条件,行标为日期,列标为名称,值为收盘价、涨幅、振幅的数据透视表 +stocks := array("SZ000001", "SZ000002", "SH600050", "SZ300775"); +begt := 20210515T; +endt := 20210525T; +t := select ['StockID'] as"代码", +["StockName"] as"名称", +datetostr(['date']) as"日期", +["close"] as"收盘价", +spec(specdate(stockzf3(), ['date']), ['StockID']) as"涨幅", +spec(specdate(stockzdf3(), ['date']), ['StockID']) as"振幅", +spec(base(10029), ['StockID']) as"申万行业" +from markettable datekey begt to endt of stocks end; +index := "日期"; +colunms := "名称"; +vals := array("收盘价", "涨幅", "振幅"); +return Pivot(t, index, colunms, vals); +``` + +####### Pivot_table + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 指定条件,行标为申万行业,列标为日期,按平均值汇总值为涨幅、振幅的的数据透视表数据 +stocks := GetBKByDate("SH000010", 20210525t); +begt := 20210515T; +endt := 20210525T; +t := select ['StockID'] as"代码", +["StockName"] as"名称", +datetostr(['date']) as"日期", +["close"] as"收盘价", +spec(specdate(stockzf3(), ['date']), ['StockID']) as"涨幅", +spec(specdate(stockzdf3(), ['date']), ['StockID']) as"振幅", +spec(base(10029), ['StockID']) as"申万行业" +from markettable datekey begt to endt of stocks end; +index := "申万行业"; +colunms := "日期"; +vals := array("涨幅", "振幅"); +aggfunc := "avg"; +return Pivot_table(t, index, colunms, vals, aggfunc); +``` + +####### Show3DTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 生成数据表t +t := array(("代码":"SH600006", "名称":"东风汽车", "2004.10-12@主营业务收入":151953.06, "2004.10-12@主营业务利润":30559.66, "2004.10-12@营业费用":10112.75, "2004.10-12@管理费用":10666.36, "2004.10-12@财务费用":-894.46, "2004.10-12@营业利润":10693.23, "2004.10-12@投资收益":-151.01, "2004.10-12@利润总额":9904.7, "2004.10-12@所得税":2413.81, "2004.10-12@净利润":7873.08, "2004.10-12@货币资金":-11664.28, "2004.10-12@短期投资":-5370.7, "2004.7-9@主营业务收入":167855.56, "2004.7-9@主营业务利润":31127.95, "2004.7-9@营业费用":4452.79, "2004.7-9@管理费用":10541.15, "2004.7-9@财务费用":-1013.26, "2004.7-9@营业利润":17162.48, "2004.7-9@投资收益":150.81, "2004.7-9@利润总额":17246.26, "2004.7-9@所得税":2629.5, "2004.7-9@净利润":14574.03, "2004.7-9@货币资金":532.5, "2004.7-9@短期投资":4962.47), ("代码":"SH600007", "名称":"中国国贸", "2004.10-12@主营业务收入":19715.3, "2004.10-12@主营业务利润":10383.2, "2004.10-12@营业费用":238.4, "2004.10-12@管理费用":1422.7, "2004.10-12@财务费用":1304.4, "2004.10-12@营业利润":7417.7, "2004.10-12@投资收益":81.1, "2004.10-12@利润总额":6404.6, "2004.10-12@所得税":2433.4, "2004.10-12@净利润":3971.2, "2004.10-12@货币资金":2964.5, "2004.10-12@短期投资":0.00, "2004.7-9@主营业务收入":17727.7, "2004.7-9@主营业务利润":9989.1, "2004.7-9@营业费用":165.5, "2004.7-9@管理费用":1151.3, "2004.7-9@财务费用":-18.2, "2004.7-9@营业利润":8690.5, "2004.7-9@投资收益":186.2, "2004.7-9@利润总额":9208.6, "2004.7-9@所得税":2977.1, "2004.7-9@净利润":6231.5, "2004.7-9@货币资金":-8101.2, "2004.7-9@短期投资":0.00), ("代码":"SH600004", "名称":"白云机场", "2004.7-9@主营业务收入":37934.65, "2004.7-9@主营业务利润":15725.54, "2004.7-9@营业费用":2623.82, "2004.7-9@管理费用":4662.1, "2004.7-9@财务费用":1789.5, "2004.7-9@营业利润":6650.11, "2004.7-9@投资收益":-15.38, "2004.7-9@利润总额":6685.16, "2004.7-9@所得税":2350.15, "2004.7-9@净利润":4000.51, "2004.7-9@货币资金":-5054.06, "2004.7-9@短期投资":101.00)); +return Show3DTable(t, '名称', '代码', 3); +``` + +返回: + +####### Show2DTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 生成数据表t +t := array(("代码":"SH600006", "名称":"东风汽车", "主营业务收入":151953.06, "主营业务利润":30559.66, "营业费用":10112.75, "管理费用":10666.36, "财务费用":-894.46, "营业利润":10693.23, "投资收益":-151.01, "利润总额":9904.7, "所得税":2413.81, "净利润":7873.08, "货币资金":-11664.28, "短期投资":-5370.7, "主营业务收入":167855.56, "主营业务利润":31127.95, "营业费用":4452.79, "管理费用":10541.15, "财务费用":-1013.26, "营业利润":17162.48, "投资收益":150.81, "利润总额":17246.26, "所得税":2629.5, "净利润":14574.03, "货币资金":532.5, "短期投资":4962.47), ("代码":"SH600007", "名称":"中国国贸", "主营业务收入":19715.3, "主营业务利润":10383.2, "营业费用":238.4, "管理费用":1422.7, "财务费用":1304.4, "营业利润":7417.7, "投资收益":81.1, "利润总额":6404.6, "所得税":2433.4, "净利润":3971.2, "货币资金":2964.5, "短期投资":0.00, "主营业务收入":17727.7, "主营业务利润":9989.1, "营业费用":165.5, "管理费用":1151.3, "财务费用":-18.2, "营业利润":8690.5, "投资收益":186.2, "利润总额":9208.6, "所得税":2977.1, "净利润":6231.5, "货币资金":-8101.2, "短期投资":0.00)); +return Show2DTable(t, '名称', '代码', 2); +``` + +返回: + +####### ShowTableByField + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +arr := array((1, 2, 3, 4, 5), (2, 3, 4, 5, 6), (3, 4, 5, 6, 7), (4, 5, 6, 7, 8)); +return ShowTableByField(arr, array(1, 2, 3)); +``` + +返回: + +####### ShowTableByUnit + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := `array('a':(1, 2, 3, 4), 'b':(2, 3, 4, 5), 'c':(3, 4, 5, 6), 'd':(4, 5, 6, 7), 'e':(5, 6, 7, 8), 'f':(7, 8, 9, 10)); +return ShowTableByUnit(t, ``array('字段a', 'a', '', '')); +``` + +返回: + +####### ShowTableByInverse + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 生成数据表t +t := array(("代码":"SH600006", "名称":"东风汽车", "主营业务收入":151953.06, "主营业务利润":30559.66, "营业费用":10112.75, "管理费用":10666.36, "财务费用":-894.46, "营业利润":10693.23, "投资收益":-151.01, "利润总额":9904.7, "所得税":2413.81, "净利润":7873.08, "货币资金":-11664.28, "短期投资":-5370.7, "主营业务收入":167855.56, "主营业务利润":31127.95, "营业费用":4452.79, "管理费用":10541.15, "财务费用":-1013.26, "营业利润":17162.48, "投资收益":150.81, "利润总额":17246.26, "所得税":2629.5, "净利润":14574.03, "货币资金":532.5, "短期投资":4962.47), ("代码":"SH600007", "名称":"中国国贸", "主营业务收入":19715.3, "主营业务利润":10383.2, "营业费用":238.4, "管理费用":1422.7, "财务费用":1304.4, "营业利润":7417.7, "投资收益":81.1, "利润总额":6404.6, "所得税":2433.4, "净利润":3971.2, "货币资金":2964.5, "短期投资":0.00, "主营业务收入":17727.7, "主营业务利润":9989.1, "营业费用":165.5, "管理费用":1151.3, "财务费用":-18.2, "营业利润":8690.5, "投资收益":186.2, "利润总额":9208.6, "所得税":2977.1, "净利润":6231.5, "货币资金":-8101.2, "短期投资":0.00)); +return ShowTableByInverse(t, '代码', '', 2); +``` + +返回: + +####### QuickRecordExist + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array('a', 'c', 'd'); +return QuickRecordExist(t, 'd'); +// 结果:2 +``` + +####### RotateTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':4)); +return RotateTable(t); +``` + +####### NonIntersectionPart + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t1 := array(('a':1, 'b':4), ('a':7, 'b':8), ('a':2, 'b':3)); +t2 := array(('a':1, 'b':1), ('a':7, 'b':8), ('a':5, 'b':5)); +return NonIntersectionPart(t1, t2, 'b'); +``` + +####### FooterValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +对起始序号Fromcol、截止序号ToCol限定大小为0到数组t的字段个数,如果Fromcol>ToCol,则将Fromcol与ToCol互换 + +若type值为0,则计算各列平均值,如果type为1,则对列求和。 + +AverageColField可以为t数组中列名,如果列名刚好为对应字符串“平均”或“总计”,那么,除AverageColField列外,其他数据按type类型计算,统计数据 存储在最后一行,AverageColField列下对应为“平均”或“总计”字符串。 + +如果AverageColField为空或指定的列名不为“平均”或“总计”,那么,“平均”或“总计”字符串存放在第一列最后一行,其他列的统计结果存放在最后一行。范例 + +```tsl +s := array(array(1, 2, 3, 4, 5), +array(2, 3, 4, 5, 6), +array(3, 4, 5, 6, 7)); +return FooterValue(s, 1, 3, '', 1); +``` + +返回: + +####### FooterAverage + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +1、对起始序号Fromcol、截止序号ToCol限定大小为0到数组t的字段个数, + +如果Fromcol>ToCol,则将Fromcol与ToCol互换。 + +2、计算各列平均值 + +3、AverageColField可以为t数组中列名,如果列名刚好为对应字符串“平均”,那么,除AverageColField列外,其他列计算平均值,平均值存储在最后一行,AverageColField列最后一行值为“平均”。 + +如果AverageColField为空或指定的列名不为“平均”,那么,“平均”字符串存放在第一列最后一行,其他列的统计结果存放在对应列最后一行。范例 + +```tsl +s := array(array(1, 2, 3, 4, 5), +array(2, 3, 4, 5, 6), +array(3, 4, 5, 6, 7)); +return FooterAverage(s, 1, 3, ''); +``` + +返回: + +####### FooterSum + +算法 + +1、对起始序号Fromcol、截止序号ToCol限定大小为0到数组t的字段个数, + +如果Fromcol>ToCol,则将Fromcol与ToCol互换。 + +2、计算各列和 + +3、AverageColField可以为t数组中列名,如果列名刚好为对应字符串“总计”,那么,除AverageColField列外,其他列数据求和,统计值存储在最后一行,AverageColField列最后一行值为“总计”。 + +如果AverageColField为空或指定的列名不为“总计”,那么,“总计”字符串存放在第一列最后一行,其他列的统计结果存放在对应列最后一行。范例 + +```tsl +s := array(array(1, 2, 3, 4, 5), +array(2, 3, 4, 5, 6), +array(3, 4, 5, 6, 7)); +return FooterAverage(s, 1, 3, ''); +``` + +返回: + +####### SetRowDefaultValue + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := array(array(1, 2, 3, 4, 5), +array(2, 3, 4, 5, 6), +array(3, 4, 5, 6)); +SetRowDefaultValue(s, 2, 'wo'); +return s; +``` + +返回: + +####### InverseTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := array(array('A':'a', 'B':'b', 'C':'c', 'D':'d', 'e':'e'), +array('A':2, 'B':3, 'C':4, 'D':5, 'e':6), +array('A':3, 'B':4, 'C':5, 'D':6, 'e':7), ); +return InverseTable(s); +``` + +返回: + +####### GetSubTableByKey + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +s := array(array('A':'a', 'B':'b', 'C':'c', 'D':'d', 'e':'e'), +array('A':'c', 'B':3, 'C':4, 'D':5, 'e':6), +array('A':3, 'B':4, 'C':5, 'D':6, 'e':7)); +return GetSubTableByKey(s, 'A', 'a;c'); +``` + +返回: + +####### TableSelect + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := `array('a':(1, 2, 3, 4), 'b':(2, 3, 4, 5), 'c':(3, 4, 5, 6), 'd':(4, 5, 6, 7), 'e':(5, 6, 7, 8), 'f':(7, 8, 9, 10)); +return TableSelect(t, "~['b']=2", '~'); // 返回t中字段’b’=2的子表 +``` + +返回: + +####### TableType + +范例 + +```tsl +s := array(array(1, 2, 3, 4, 5), +array(2, 3, 4, 5, 6), +array(3, 4, 5, 6, 7)); +return tabletype(s); +// 返回:0 +``` + +####### GetSubTableFreeParam + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return GetSubTableFreeParam(); // 之前在系统参数中已经设置好第一个参数s=array(array('s':1,'w':2,'sl':3), array('s':2,'w':3,'sl':4), array('s':3,'w':4,'sl':5)),第二三个参数’s’,’w’。 +``` + +返回: + +####### ExpandTable + +用途:数组相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 按照分红送股列展开数据 +data := Query("", "SH600000;SZ000002", true, "", "代码", DefaultStockID(), "名称", +CurrentStockName(), "分红送股", infoarray(18)); +return ExpandTable(data, "分红送股"); +``` + +###### 数组下标 + +####### 内容 + +- frameIndex_filter +- frameIndex_getilocDZ + +####### frameIndex_filter + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +范例01 + +```tsl +// 选择 "回测周期":"因子分类" +allcols := +array("回测名称", "回测周期", "分组个数", "因子名称", "因子分类", "IC分析@IC均值", "IC分析@ICIR", "IC分析@IC胜率(%)", "回归分析@平均收益(%)", "回归分析@T值", "分组绝对收益(多头)@收益(%)", "分组绝对收益(多头)@波动率(%)", "分组绝对收益(多头)@胜率(%)", "分组相对收益(多头)@收益(%)", "分组相对收益(多头)@波动率(%)", "分组相对收益(多头)@胜率(%)", "分组相对收益(多头)@T值", "分组多空收益@收益(%)", "分组多空收益@波动率(%)", "分组多空收益@胜率(%)", "分组多空收益@T值", "创建人", "因子回测ID", "收藏人数", "是否已收藏"); +return frameIndex_filter(allcols, array('回测周期', '因子分类'), 1); +``` + +范例02 + +```tsl +// 选择 IC分析 开头的 +return frameIndex_filter(allcols, '^IC分析', 3); +``` + +范例03 + +```tsl +// 选择 IC分析 开头,或者 因子 开头的 +return frameIndex_filter(allcols, array('^IC分析', '^因子'), 3); +``` + +####### frameIndex_getilocDZ + +用途:数组相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +return frameIndex_getilocDZ(array('成长', '估值', '动量')); +``` diff --git a/data/tsl_reference_catalog_source/client.md b/data/tsl_reference_catalog_source/client.md new file mode 100644 index 00000000..b61902ba --- /dev/null +++ b/data/tsl_reference_catalog_source/client.md @@ -0,0 +1,396 @@ +#### 客户端函数 + +##### 内容 + +- 结果处理 +- 错误处理 +- 客户端行为控制函数 +- SendRunningData + +##### 结果处理 + +###### 内容 + +- DelPrecode +- IncPrecode +- ProcessField +- ProcessFirstField +- TimeSeriesSplit +- ReportSeriesSplit +- TwoDimFormat2 +- ThreeDimFormat2 +- ThreeDimFormat3 +- ThreeDimFormat4 +- ThreeDimFormat5 +- ThreeDimFormat6 +- IsTwoDim +- TransForm +- TransPose +- TransPoseForChart +- TransPoseForChartSysParam +- TransPoseForChartSysParamEx +- TransDataStandardize +- CallBack +- 层次表格的展开 +- 简单统计 +- 品种管理 + +###### DelPrecode + +###### IncPrecode + +###### ProcessField + +###### ProcessFirstField + +###### TimeSeriesSplit + +###### ReportSeriesSplit + +###### TwoDimFormat2 + +###### ThreeDimFormat2 + +###### ThreeDimFormat3 + +###### ThreeDimFormat4 + +###### ThreeDimFormat5 + +###### ThreeDimFormat6 + +###### IsTwoDim + +###### TransForm + +###### TransPose + +###### TransPoseForChart + +###### TransPoseForChartSysParam + +###### TransPoseForChartSysParamEx + +###### TransDataStandardize + +###### CallBack + +####### 内容 + +- DelPrecodeCallBack +- IncPrecodeCallBack + +####### DelPrecodeCallBack + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return DelPrecodeCallBack('SH600000'); +``` + +结果:’ 600000’ + +####### IncPrecodeCallBack + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return IncPrecodeCallBack('000002.SZ'); +``` + +结果:’SZ000002’ + +###### 层次表格的展开 + +####### 内容 + +- CheckDataCanBeExtract +- ExtractData +- ExtractDataEx +- ExtractDataEx2 +- ExtractDataLocalRun +- ExtractDataLocalRun2 + +####### CheckDataCanBeExtract + +####### ExtractData + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +r := Query("", "SH600000;SZ000002", true, "", "代码", DefaultStockID(), +"名称", CurrentStockName(), +"股票.分红送股", infoarray(18)); +return ExtractData(r, 1, 0); +``` + +####### ExtractDataEx + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +r := Query("", "SH600000;SZ000002", true, "", "代码", DefaultStockID(), +"名称", CurrentStockName(), +"名称2", CurrentStockName(), +"名称3f", CurrentStockName(), +"股票.分红送股", infoarray(18)); +return ExtractDataEx(r, 1, 0, 1); +``` + +####### ExtractDataEx2 + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 数据展开范例 +r := Query("", "SH600000;SZ000002", true, "", "代码", DefaultStockID(), +"名称", CurrentStockName(), +"名称2", CurrentStockName(), +"名称3f", CurrentStockName(), +"股票.分红送股", infoarray(18)); +return ExtractDataEx2(r, 1, 0, 1, 1); +``` + +####### ExtractDataLocalRun + +####### ExtractDataLocalRun2 + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 数据展开范例 +r := Query("", "SH600000;SZ000002", true, "", "代码", DefaultStockID(), +"名称", CurrentStockName(), +"名称2", CurrentStockName(), +"名称3f", CurrentStockName(), +"股票.分红送股", infoarray(18)); +setsysparam(pn_data(), r); +return ExtractDataLocalRun2(0, 1); +``` + +###### 简单统计 + +####### 内容 + +- SimpleStat +- SimpleStatLocal + +####### SimpleStat + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := array(1, 2, 3, 4, 5); +return SimpleStat(Data); +``` + +####### SimpleStatLocal + +###### 品种管理 + +####### 内容 + +- GetDefaultFuncNameByStock +- GetTypeOfStock + +####### GetDefaultFuncNameByStock + +####### GetTypeOfStock + +用途:结果处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return GetTypeOfStock('OF000001'); +``` + +结果:4 + +##### 错误处理 + +###### 内容 + +- ThisFuncOnlyForStock +- ThisFuncOnlyForBond +- ThisFuncUnderConstruction +- ThisFunOnlyForIndex +- RaiseError +- ThisFuncOnlyForFund +- ASSERT + +###### ThisFuncOnlyForStock + +###### ThisFuncOnlyForBond + +###### ThisFuncUnderConstruction + +###### ThisFunOnlyForIndex + +###### RaiseError + +范例 + +```tsl +return raise Error('function1', '无效的语段'); +``` + +###### ThisFuncOnlyForFund + +###### ASSERT + +用途:错误处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return ASSERT(0, '无效的语段'); +``` + +##### 客户端行为控制函数 + +###### 内容 + +- 客户端行为控制函数简介 +- TSExpert_ClientConfig + +###### 客户端行为控制函数简介 + +客户端行为控制,是指客户端会调用一个模型,该模型的返回的结果会影响到客户端的行为,目前,客户端支持用户编写一个名为TSExpert_ClientConfig的函数,客户端会根据该函数的返回结果集来决定CHART的背景图,CHART的颜色序列,重新登录自动执行函数等等行为。 + +###### TSExpert_ClientConfig + +范例 + +```tsl +// 在客户端内创建函数,函数名为TSExpert_ClientConfig,函数体内的函数如下 +r := array(); +r["AutoRun"][0] := 'TS_ClientDemo'; // TS_ClientDemo为预先设定好的函数,在下次登陆客户端时会自动运行该函数。其中TS_ClientDemo的代码为rdo2 MessageBox("欢迎登陆天软客户端","您好",rdo2 mb_DefButton1()); +return r; +``` + +效果: 重新启动客户端时,会弹出下面对话框 + +该函数的返回值为一个数组,该数组的下标定义如下: + +####### 内容 + +- ChartColor +- ChartColorArray +- DisabledFuncTypeList +- DisabledSystemFuncList +- DisabledSysFuncList +- FuncTypeList +- AutoRun + +####### ChartColor + +值为整数,为数组类型数据展示的Chart图的默认背景色。 + +例如:值为clWhite() + +####### ChartColorArray + +值为一个一维整数颜色数组,该数组为在数组类型数据展示的时候,下边的Chart的序列的颜色序列,例如:array(clRed(),clYellow(),clBlue()…..)表示第一个图的颜色为红色,第二个为黄色,第三个为蓝色…..。 + +####### DisabledFuncTypeList + +值为一个一维整数数组,代表了在系统里禁用的函数类型ID,函数类型在funcType.cfg里定义。被禁止的函数类型将不会在系统里展示。 + +####### DisabledSystemFuncList + +值为一个一维字符串数组,代表了在系统中隐藏的共用函数的函数名列表。 + +####### DisabledSysFuncList + +值为一个一维字符串数组,代表了在系统中隐藏的二进制系统函数的函数名列表。 + +####### FuncTypeList + +值为一个二维数组,该数组为扩展的函数类型定义,其定义参考FuncType.cfg。 + +这个二维数组有两列,分别为ID和NAME,ID列就是函数类型的数字,NAME则是函数类型的显示名称。 + +例如: + +Array(("ID":601,"NAME":"我的扩展.扩展范例1"),…….) + +####### AutoRun + +值为一个数组,代表在客户端每次重新登录后自动运行的函数列表。 + +数组可以是一维的,也可以是二维。如果是一维,则每项的值为字符串类型,为需要的自动运行的函数名,如果是二维的,则具备两列,分别为type和name。 + +type列,类型为整数,表示函数的类型。0:用户函数,1:共享函数,2:共用函数,3:系统函数 + +name列,类型为字符串,表示函数的名称。 + +例如:array("AutoRunDemo1","AutoRunDemo2")表明启动的时候自动运行名为autorundemo1和autorundemo2的函数。 + +也可以用array(("type":0,"name":"AutoRunDemo1"),("type":0,"name":"AutoRunDemo2"))表明自动运行用户函数AutoRunDemo1和用户函数AutoRunDemo2。 + +##### SendRunningData + +范例 + +```tsl +// 在原窗口输出个数,无需加Nwdow参数 +n := 0; +while n < 100 do +begin + Echo n; + SendRunningData(n); + n++; +end; +return 1; +// 在新窗口输出数组,则需要加Nwdow参数,代码如下: +n := 0; +while n < 100 do +begin + Echo n; + SendRunningData(rand(10), "新窗口"); + n++; +end; +return 1; +``` diff --git a/data/tsl_reference_catalog_source/compression.md b/data/tsl_reference_catalog_source/compression.md new file mode 100644 index 00000000..05e6bbd1 --- /dev/null +++ b/data/tsl_reference_catalog_source/compression.md @@ -0,0 +1,101 @@ +#### 压缩和解压函数 + +##### 内容 + +- 压缩和解压函数简介 +- ZipCompress +- ZipExtract +- RarExtract +- 压缩解压函数使用说明 +- unicompress +- uniuncompress + +##### 压缩和解压函数简介 + +ZIP和RAR是最常见的文件压缩格式,为此天软提供了ZIP文件压缩和解压函数,以及RAR的解压支持。因RAR格式版权所有人不允许除自己外的第二者提供压缩支持,目前天软没有提供RAR的压缩函数。 + +##### ZipCompress + +范例 + +```tsl +// 把文件d:\a.txt压缩到d:\a.zip文件中的/hello/world/a.txt中 +ZipCompress('', 'd:\\a.zip', '', 'd:\\a.txt', 'hello/world/a.txt'); +// 将d:\tmp目录压缩到d:\a.zip文件中 +ZipCompress('', 'd:\\a.zip', '', 'd:\\tmp', 'test'); +``` + +##### ZipExtract + +范例 + +```tsl +// 将ZIP文件解压,可以使用ZipExtract函数,例如将d:\a.zip文件解压到d:\tmp目录 +ZipExtract('', 'd:\\a.zip', '', 'd:\\tmp', '123'); +``` + +##### RarExtract + +范例 + +```tsl +// 将RAR文件解压,可以使用RarExtract函数,例如将d:\a.rar文件解压到d:\tmp目录 +RarExtract('', 'd:\\a.rar', '', 'd:\\tmp', '123'); +``` + +##### 压缩解压函数使用说明 + +函数中的alias参数用于指定目录别名 + +ZipCompress函数可以将由filename指定的文件或目录压缩到由zip_filename指定的压缩文件中,如果压缩文件不存在,函数会创建一个。ZIP格式的压缩不支持加密。 + +函数中所指定的path是压缩文件或目录在ZIP文件中的路径。如同文件系统中文件是在树状的目录结构中存储一样,ZIP文件中所存储的文件也是树状结构的,通过指定path参数,我们可以将文件或目录压缩后存放到ZIP文件中指定的目录下,如果path参数为空(“”),就压缩到ZIP的根目录下。例如我们把文件d:\a.txt压缩到d:\a.zip文件中的/hello/world/a.txt中,可以使用下面的语句: + +```tsl +ZipCompress('', 'd:\\a.zip', '', 'd:\\a.txt', 'hello/world/a.txt'); +``` + +又如我们要将d:\tmp目录压缩到d:\a.zip文件中的根下,可以使用这样的语句: + +```tsl +ZipCompress('', 'd:\\a.zip', '', 'd:\\tmp', 'test'); +``` + +要将ZIP文件解压,可以使用ZipExtract函数,例如将d:\a.zip文件解压到d:\tmp目录: + +```tsl +ZipExtract('', 'd:\\a.zip', '', 'd:\\tmp', '123') ; +``` + +要将RAR文件解压,可以使用RarExtract函数,例如将d:\a.rar文件解压到d:\tmp目录: + +```tsl +RarExtract('', 'd:\\a.rar', '', 'd:\\tmp', '123'); +``` + +##### unicompress + +范例 + +本地运行下面脚本: + +```tsl +data := "Holle Tinysoft天软"; +s := unicompress("zstd", data); +echo s, "\r\n"; +echo uniuncompress("zstd", s), "\r\n"; +return 1; +``` + +##### uniuncompress + +范例 + +```tsl +data := "Holle Tinysoft天软"; +len := length(data); +s := unicompress("zstd", data); +echo s, "\r\n"; +echo uniuncompress("zstd", s, len), "\r\n"; +return 1; +``` diff --git a/data/tsl_reference_catalog_source/digest_encoding.md b/data/tsl_reference_catalog_source/digest_encoding.md new file mode 100644 index 00000000..6b36b480 --- /dev/null +++ b/data/tsl_reference_catalog_source/digest_encoding.md @@ -0,0 +1,209 @@ +#### 信息摘要及编码 + +##### 内容 + +- 信息摘要函数 +- BASE64编码 +- URI EnCode函数 +- 进制编码函数 + +##### 信息摘要函数 + +信息摘要函数主要提供CRC32,MD5,SHA这三类信息摘要算法的实现,信息摘要算法广泛地应用于数字签名应用中。 + +###### 内容 + +- 摘要函数使用说明 +- GetMsgDigest +- GetMsgDigest(文件) + +###### 摘要函数使用说明 + +```tsl +filename := "d:\\test.txt"; +teststr := "hello"; +alias := ""; //别名 +return array( +"filename":filename, +"GetMsgDigest(crc32_str)":GetMsgDigest(teststr,0), +"GetMsgDigest(md5_str)":GetMsgDigest(teststr,1), +"GetMsgDigest(sha1_str)":GetMsgDigest(teststr,2), +"GetMsgDigest(sha224_str)":GetMsgDigest(teststr,3), +"GetMsgDigest(sha256_str)":GetMsgDigest(teststr,4), +"GetMsgDigest(sha384_str)":GetMsgDigest(teststr,5), +"GetMsgDigest(sha512_str)":GetMsgDigest(teststr,6), +"GetMsgDigest(alias, filename, crc32_str)":GetMsgDigest(alias,filename,0), +"GetMsgDigest(alias, filename, md5_str)":GetMsgDigest(alias,filename,1), +"GetMsgDigest(alias, filename, sha1_str)":GetMsgDigest(alias,filename,2), +"GetMsgDigest(alias, filename, sha224_str)":GetMsgDigest(alias,filename,3), +"GetMsgDigest(alias, filename, sha256_str)":GetMsgDigest(alias,filename,4), +"GetMsgDigest(alias, filename, sha384_str)":GetMsgDigest(alias,filename,5), +"GetMsgDigest(alias, filename, sha512_str)":GetMsgDigest(alias,filename,6) +); +``` + +###### GetMsgDigest + +用途:信息摘要函数相关函数。 +参数:arg1(按示例顺序传入)。 +返回:处理后的结果值。 + +- 摘要函数使用说明 +- GetMsgDigest +- GetMsgDigest(文件) + +###### GetMsgDigest(文件) + +##### BASE64编码 + +字符串与BASE64编码的互转函数 + +###### 内容 + +- BASE64编码函数使用说明 +- StrToBase64 +- Base64ToStr + +###### BASE64编码函数使用说明 + +```tsl +//常量定义 +test_str := 'hello world'; +//BASE64 +base64 := StrToBase64(test_str); //转换为BASE64编码 +orig_str := Base64ToStr(base64); //BASE64编码转换为字符串 +``` + +###### StrToBase64 + +用途:将字符串转换为对应类型。 +参数:arg1(按示例顺序传入)。 +返回:转换后的数值或日期。 + +范例 + +```tsl +return rdo2 StrToBase64('a12'); // 返回字符串:YTEy +``` + +###### Base64ToStr + +用途:将输入值转换为字符串。 +参数:arg1(按示例顺序传入)。 +返回:字符串。 + +范例 + +```tsl +return rdo2 Base64ToStr('YTEy'); // 返回字符串:a12 +``` + +##### URI EnCode函数 + +与JavaScript同名函数功能完全相同。 + +###### 内容 + +- EncodeURIComponent +- DecodeURIComponent +- EncodeURI +- DecodeURI + +###### EncodeURIComponent + +###### DecodeURIComponent + +###### EncodeURI + +###### DecodeURI + +##### 进制编码函数 + +###### 内容 + +- 进制编码函数使用说明 +- EncodeRadixstr +- DecodeRadixstr +- Decoderadixwstr +- Encoderadixwstr + +###### 进制编码函数使用说明 + +encoderadixstr("123","0x",16)结果为"0x310x320x33" 前缀 + +encoderadixstr("123","h",0x80000000+16)结果为"31h32h33h" 后缀 + +decoderadixstr("0x310x320x33",2,16)的结果为123 + +encoderadixstr("123","h",0x80000000+16)结果为"31h32h33h" + +decoderadixstr("31h32h33h",1,0x80000000+16)结果为"123" + +encoderadixstr("天软","0x",16)结果为"0xCC0xEC0xC80xED" 默认大写 + +encoderadixstr("天软","0x",0x40000000+16)结果为"0xcc0xec0xc80xed" 小写字母 + +###### EncodeRadixstr + +用途:进制编码函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +return EncodeRadixstr("1122", "0x", 16); // 结果为’ 0x310x310x320x32’,前缀,16进制 +return EncodeRadixstr("1122", "h", 0x80000000 + 16); // ’ 31h31h32h32h’,后缀,16进制 +return EncodeRadixstr("天软", "ox", 0x80000000 + 16); +// ’ CCoxECoxC8oxEDox’,后缀,默认为大写字母,16进制 +return EncodeRadixstr("天软", "0X", 0x80000000 + 0x40000000 + 16); +// ’ cc0Xec0Xc80Xed0X’,后缀,小写字母,16进制 +return EncodeRadixstr("18", "B", 2); // ’ B00110001B00111000’,二进制 +``` + +###### DecodeRadixstr + +用途:进制编码函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +return DecodeRadixstr('0x310x310x320x32', 2, 16); // 返回'1122' +// 注:这里的第二个参数是前缀或后缀的串的长度,并非指定串 +``` + +###### Decoderadixwstr + +用途:进制编码函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +return Decoderadixwstr('0x00310x00310x00320x0032', 2, 16); // 返回'1122' +// 注:这里的第二个参数是前缀或后缀的串的长度,并非指定串 +``` + +###### Encoderadixwstr + +用途:进制编码函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +return Encoderadixwstr("1122", "0x", 16); +// 结果为'0x00310x00310x00320x0032',前缀,16进制 +return Encoderadixwstr("1122", "h", 0x80000000 + 16); +// '0031h0031h0032h0032h',后缀,16进制 +return Encoderadixwstr("天软", "ox", 0x80000000 + 16); // '' +// '5929ox8F6Fox',后缀,默认为大写字母,16进制 +return Encoderadixwstr("天软", "0X", 0x80000000 + 0x40000000 + 16); +// '59290X8f6f0X',后缀,小写字母,16进制 +return Encoderadixwstr("18", "B", 2); +// 'B0000000000110001B0000000000111000',二进制 +``` diff --git a/data/tsl_reference_catalog_source/graphics.md b/data/tsl_reference_catalog_source/graphics.md new file mode 100644 index 00000000..6a3929f3 --- /dev/null +++ b/data/tsl_reference_catalog_source/graphics.md @@ -0,0 +1,608 @@ +#### 图形函数 + +##### 内容 + +- 作图函数 +- 图形类型函数 +- 图形字段函数 +- 图形标示函数 +- 图形填充设置函数 +- 颜色函数 +- 颜色变换函数 + +##### 作图函数 + +###### 内容 + +- Graph +- GraphGroup +- MergeGraph +- EncodeGraphGroup +- DecodeGraphGroup +- DecodeGraph +- EncodeGraph +- FastLine_Web +- BarLine_Web +- PieLine_Web +- GetColorByIndex + +###### Graph + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// K线图 +setsysparam(pn_stock(), 'SZ000002'); +setsysparam(pn_date(), inttodate(20140117)); +setsysparam(pn_nday(), 250); +t1 := NDay2(gfopen(), Open() , +gfclose(), close(), +gfhigh(), high(), +gflow(), low(), +gftime(), datetimetostr(sp_time()), +// KLine颜色 +gfColor(), IfThen3(Close(), Open(), +ClRed() ,//涨颜色 +clYellow() ,//平颜色 +ClLime()//跌颜色 +), +gffill(), ifThen3(Close(), Open(), flClear(), flSolid(), flSolid()) +); +t2 := NDay2('MA10', Ma(Close(), 10)); +g1 := Graph(gtKline(), 'KLine', t1); +g2 := Graph(gtline(), 'MA10', t2); +return graphgroup(g1, g2); +``` + +范例二: + +```tsl +// 折线图 +setsysparam(pn_stock(), 'SZ000002'); +setsysparam(pn_date(), inttodate(20140117)); +setsysparam(pn_nday(), 250); +GData1 := Nday2(gfclose(), close()); +GData2 := Nday2('MA5', MA(close(), 5)); +GData3 := Nday2('MA20', MA(close(), 20)); +g1 := Graph( gtLine(), gfclose(), Gdata1, gfColor() , clBlue()); +g2 := Graph( gtLine(), "MA5", Gdata2, gfColor() , clGreen()); +g3 := Graph( gtLine(), "MA20", Gdata3, gfColor() , clRed()); +return graphgroup(g1, g2, g3); +``` + +参考GraphGroup DecodeGraphGroup EncodeGraphGroup DecodeGraph EncodeGraph + +###### GraphGroup + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3,arg4(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +VolData := Nday2(GfVol() , Vol() , gfColor() , ifthen ( Close() > Open() , ClRed() , ClGreen() ) ); +MAVOL := Nday2('MA5', MA ( Vol() , 5 ) ); +VOLGraph := Graph(gtBar(), 'VOLGraph', VolData); +MAVOLGraph := Graph(gtLine(), 'MA5Graph', MAVOL, gfColor(), clBlue()); +return GraphGroup(VOLGraph, MAVOLGraph, gfMinValue(), 0); +``` + +结果说明:GraphGroup包含了两个TGraph图形,一个是VOLGraph成交量图形,另一个是MAVOLGraph成交量的5日均线的折线图形。这两个图形具有的共有属性是gfMinValue(),就是最小值为0。gfColor在VolData中作为了数据字段,用来指示每一个数据点的颜色。因此柱子会根据开盘和收盘的差异来决定色彩的显示。而在MAVOLGraph又作为了图形的属性,因此MAVOLGraph在显示的时候会呈现出蓝色。gfMinValue在返回的图形组合里作为了图形组合的属性,因此决定了图形会用0来作为最小的值来显示,而不会用区间内的最小成交量作为最小值显示。 + +另外,我们可以注意到,作为gtLine类型的MAVOLGraph并不含有特殊的值来指定折线的点的位置,在没有特定的数据字段的时候,系统会使用第一个存在的数据字段当成默认的gfValue来显示。 + +gfMinValue():设定最小值。一般的,图形会用查找视图内最小最小值用于显示,同时,为了特殊显示,也可以指定其显示的最大最小值,通常成交量的图是用0作为最小值的。参考Graph +DecodeGraphGroup EncodeGraphGroup DecodeGraph EncodeGraph + +###### MergeGraph + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3,arg4(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +setsysparam(pn_stock(), 'SZ000063'); +setsysparam(pn_date(), 20190301T); +setsysparam(pn_nday(), 100); +t1 := NDay2(gfopen(), Open() , +gfclose(), close(), +gfhigh(), high(), +gflow(), low(), +gftime(), datetimetostr(sp_time()), +// KLine颜色 +gfColor(), IfThen3(Close(), Open(), +ClRed() ,//涨颜色 +clYellow() ,//平颜色 +ClLime()//跌颜色 +), +gffill(), ifThen3(Close(), Open(), flClear(), flSolid(), flSolid()) +); +t2 := NDay2('MA5', Ma(Close(), 5)); // 5日均线 +t3 := NDay2('MA10', Ma(Close(), 10)); // 10日均线 +t4 := NDay2('MA20', Ma(Close(), 20)); // 20日均线 +g1 := graph(gtKline(), 'KLine', t1); +g2 := graph(gtline(), 'MA5', t2); +g3 := graph(gtline(), 'MA10', t3); +g4 := graph(gtline(), 'MA20', t4); +return MergeGraph(g1, g2, g3, g4); +``` + +返回: + +###### EncodeGraphGroup + +用途:作图函数相关函数。 +参数:arg1,arg2(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +// 取万科A 截止至2014年1月17日的250个交易日的K线数据与10日移动平均数据的图形组合 +setsysparam(pn_stock(), 'SZ000002'); +setsysparam(pn_date(), inttodate(20140117)); +setsysparam(pn_nday(), 250); +t1 := NDay2(gfopen(), Open() , +gfclose(), close(), +gfhigh(), high(), +gflow(), low(), +gftime(), datetimetostr(sp_time()), +// KLine颜色 +gfColor(), IfThen3(Close(), Open(), +ClRed() ,//涨颜色 +clYellow() ,//平颜色 +Clblue()//跌颜色 +), +gffill(), ifThen3(Close(), Open(), flClear(), flSolid(), flSolid()) +); +t2 := NDay2('MA10', Ma(Close(), 10)); +g1 := graph(gtKline(), 'KLine', t1); +g2 := graph(gtline(), 'MA10', t2); +return EncodeGraphGroup(array(g1, g2), array()); +``` + +参考Graph GraphGroup DecodeGraphGroup DecodeGraph EncodeGraph + +###### DecodeGraphGroup + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +VolData := Nday2(GfVol() , Vol() , gfColor() , ifthen ( Close() > Open() , ClRed() , ClGreen() ) ); +MAVOL := Nday2('MA5', MA ( Vol() , 5 ) ); +VOLGraph := Graph(gtBar(), 'VOLGraph', VolData); +MAVOLGraph := Graph(gtLine(), 'MA5Graph', MAVOL, gfColor(), clBlue()); +DATAARR := GraphGroup(VOLGraph, MAVOLGraph, gfMinValue(), 0); +DecodeGraphGroup(DATAARR, x, y); +return x; // 返回分解后的柱状图 +``` + +参考Graph GraphGroup EncodeGraphGroup DecodeGraph EncodeGraph + +###### DecodeGraph + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3,arg4,arg5(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +setsysparam(pn_stock(), 'SZ000002'); +setsysparam(pn_date(), inttodate(20140117)); +setsysparam(pn_nday(), 250); +t1 := NDay2(gfopen(), Open() , +gfclose(), close(), +gfhigh(), high(), +gflow(), low(), +gftime(), datetimetostr(sp_time()), +// KLine颜色 +gfColor(), IfThen3(Close(), Open(), +ClRed() ,//涨颜色 +clYellow() ,//平颜色 +Clblue()//跌颜色 +), +gffill(), ifThen3(Close(), Open(), flClear(), flSolid(), flSolid()) +); +g1 := graph(gtKline(), 'KLine', t1); +DecodeGraph(g1, ty, na, da, pr); +return array(ty, na, da, pr); +``` + +参考Graph GraphGroup DecodeGraphGroup EncodeGraphGroup EncodeGraph + +###### EncodeGraph + +用途:作图函数相关函数。 +参数:arg1,arg2,arg3,arg4(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +setsysparam(pn_stock(), 'SZ000002'); +setsysparam(pn_date(), inttodate(20140117)); +setsysparam(pn_nday(), 250); +t1 := NDay2(gfopen(), Open() , +gfclose(), close(), +gfhigh(), high(), +gflow(), low(), +gftime(), datetimetostr(sp_time()), +// KLine颜色 +gfColor(), IfThen3(Close(), Open(), +ClRed() ,//涨颜色 +clYellow() ,//平颜色 +Clblue()//跌颜色 +), +gffill(), ifThen3(Close(), Open(), flClear(), flSolid(), flSolid()) +); +return EncodeGraph(gtkline(), 'KLine', t1, array()); +``` + +参考Graph GraphGroup DecodeGraphGroup EncodeGraphGroup DecodeGraph + +###### FastLine_Web + +- Graph +- GraphGroup +- MergeGraph +- EncodeGraphGroup +- DecodeGraphGroup +- DecodeGraph +- EncodeGraph +- FastLine_Web +- BarLine_Web +- PieLine_Web +- GetColorByIndex + +###### BarLine_Web + +###### PieLine_Web + +###### GetColorByIndex + +用途:作图函数相关函数。 +参数:arg1(按示例顺序传入)。 +返回:整数。 + +范例 + +```tsl +return GetColorByIndex(1); +// 返回:16711680 +``` + +##### 图形类型函数 + +###### 内容 + +- gtLine +- gtKLine +- gtTower +- gtAmerican +- gtBar +- gtSingleBar +- gtCircle + +###### gtLine + +###### gtKLine + +###### gtTower + +###### gtAmerican + +###### gtBar + +###### gtSingleBar + +###### gtCircle + +##### 图形字段函数 + +这类函数用于描述数据点的特性或者描述整个图形的属性 + +###### 内容 + +- gfValue +- gfClose +- gfOpen +- gfHigh +- gfLow +- gfTowerLow +- gfTowerHigh +- gfTowerMid +- gfVol +- gfAmount +- gfTime +- gfColor +- gfFill +- gfFlag +- gfRateFlag +- gfZero +- gfMaxValue +- gfMinValue +- gfLTP +- gfTitleCaption +- gfLeftTitleCaption +- gfCoordinate + +###### gfValue + +###### gfClose + +###### gfOpen + +###### gfHigh + +###### gfLow + +###### gfTowerLow + +###### gfTowerHigh + +###### gfTowerMid + +###### gfVol + +###### gfAmount + +###### gfTime + +###### gfColor + +参考颜色函数 + +###### gfFill + +参考图形填充设置函数 + +###### gfFlag + +参考图形标示函数 + +###### gfRateFlag + +###### gfZero + +参考TGraphGroup + +###### gfMaxValue + +参考TGraphGroup + +###### gfMinValue + +参考TGraphGroup + +###### gfLTP + +参考TGraphGroup + +###### gfTitleCaption + +参考TGraphGroup + +###### gfLeftTitleCaption + +参考TGraphGroup + +###### gfCoordinate + +参考TGraphGroup + +##### 图形标示函数 + +用于为图形做出一定标示,例如买入点或卖出点,取值为整数。 + +###### 内容 + +- fgNone +- fgUp +- fgDown +- fgLeft +- fgRight +- fgLeftUp +- fgLeftDown +- fgRightUp +- fgRightDown + +###### fgNone + +###### fgUp + +###### fgDown + +###### fgLeft + +###### fgRight + +###### fgLeftUp + +###### fgLeftDown + +###### fgRightUp + +###### fgRightDown + +##### 图形填充设置函数 + +用于设定图形是否填充以及如何填充,取值为整数。 + +参考:gfFill + +###### 内容 + +- flSolid +- flClear +- flHorizontal +- flVertical +- flFDiagonal +- flBDiagonal +- flCross +- flDiagCross + +###### flSolid + +参考gfFill flClear flHorizontal flVertical flFDiagonal flBDiagonal flCross +flDiagCross + +###### flClear + +参考gfFill flSolid flHorizontal flVertical flFDiagonal flBDiagonal flCross +flDiagCross + +###### flHorizontal + +参考gfFill flSolid flClear flVertical flFDiagonal flBDiagonal flCross +flDiagCross + +###### flVertical + +参考gfFill flSolid flClear flHorizontal flFDiagonal flBDiagonal flCross +flDiagCross + +###### flFDiagonal + +参考gfFill flSolid flClear flHorizontal flVertical flBDiagonal flCross +flDiagCross + +###### flBDiagonal + +参考gfFill flSolid flClear flHorizontal flVertical flFDiagonal flCross +flDiagCross + +###### flCross + +参考gfFill flSolid flClear flHorizontal flVertical flFDiagonal flBDiagonal +flDiagCross + +###### flDiagCross + +参考gfFill flSolid flClear flHorizontal flVertical flFDiagonal flBDiagonal +flCross + +##### 颜色函数 + +###### 内容 + +- clBlack +- clMaroon +- clGreen +- clOlive +- clNavy +- clPurple +- clTeal +- clGray +- clSilver +- clRed +- clLime +- clYellow +- clBlue +- clFuchsia +- clAqua +- clLtGray +- clDkGray +- clWhite +- clMoneyGreen +- clSkyBlue +- clCream +- clMedGray + +###### clBlack + +###### clMaroon + +###### clGreen + +###### clOlive + +###### clNavy + +###### clPurple + +###### clTeal + +###### clGray + +###### clSilver + +###### clRed + +###### clLime + +###### clYellow + +###### clBlue + +###### clFuchsia + +###### clAqua + +###### clLtGray + +###### clDkGray + +###### clWhite + +###### clMoneyGreen + +###### clSkyBlue + +###### clCream + +###### clMedGray + +##### 颜色变换函数 + +###### 内容 + +- GetCValue +- GetMValue +- GetYValue +- GetKValue +- CMYK +- RGB +- Rgbbgr +- PaletteRGB +- PaletteIndex +- GetRValue +- GetGValue +- GetBValue + +###### GetCValue + +###### GetMValue + +###### GetYValue + +###### GetKValue + +###### CMYK + +###### RGB + +###### Rgbbgr + +###### PaletteRGB + +###### PaletteIndex + +###### GetRValue + +###### GetGValue + +###### GetBValue diff --git a/data/tsl_reference_catalog_source/index.md b/data/tsl_reference_catalog_source/index.md new file mode 100644 index 00000000..96bfcba6 --- /dev/null +++ b/data/tsl_reference_catalog_source/index.md @@ -0,0 +1,83 @@ +# TSL函数 + +> 本文档从 [archive/tsl/syntax_book/function/index.md](../../archive/tsl/syntax_book/function/index.md) 拆分而来 + +TSL函数包含数学、系统、基础、图形等通用函数,适用于各种TSL脚本开发场景。 + +## 目录 + +### 数学与计算 + +- **[数学函数](./math.md)** (14,396行) + - 数值计算、常用数学函数、位运算函数 + - 三角函数、角度量转换、双曲线函数 + - 指数对数函数、随机数、统计函数 + +### 系统与平台 + +- **[系统相关函数](./system.md)** (1,647行) + + - 系统信息、环境变量、进程控制 + - 内存管理、性能监控 + +- **[平台函数](./platform.md)** (553行) + + - 平台特定功能、系统调用 + +- **[客户端函数](./client.md)** (409行) + - 客户端交互、界面控制 + +### 基础功能 + +- **[基础函数](./base.md)** (10,660行) + + - 字符串处理、数组操作、日期时间 + - 类型转换、条件判断、数据结构 + - 文件操作、流程控制 + +- **[图形函数](./graphics.md)** (698行) + - 绘图、图表、可视化 + +### 资源与交互 + +- **[资源访问函数](./resource.md)** (4,897行) + + - 文件读写、数据库访问、网络通信 + - 配置文件、资源管理 + +- **[第三方交互函数](./third_party.md)** (610行) + - 第三方库调用、外部程序交互 + +### 工具函数 + +- **[压缩和解压函数](./compression.md)** (108行) + + - 数据压缩、解压缩、归档 + +- **[信息摘要及编码](./digest_encoding.md)** (172行) + - 哈希算法、加密、编码转换 + +## 快速索引 + +### 常用函数分类 + +| 功能类别 | 文件 | 典型函数示例 | +| ---------- | ---------------------------- | --------------------------------------- | +| 数学计算 | [math.md](./math.md) | Abs, Sqrt, Sin, Cos, Log, Exp, Round... | +| 字符串处理 | [base.md](./base.md) | Len, Mid, Left, Right, Trim, Replace... | +| 日期时间 | [base.md](./base.md) | Now, Date, Time, DateAdd, DateDiff... | +| 文件操作 | [resource.md](./resource.md) | FileExists, ReadFile, WriteFile... | +| 数组操作 | [base.md](./base.md) | Array, UBound, LBound, Sort... | +| 类型转换 | [base.md](./base.md) | CStr, CInt, CFloat, CBool... | + +## 使用提示 + +1. **数学函数**:`math.md` 包含了所有数学计算相关的函数,是数值处理的基础 +2. **基础函数**:`base.md` + 最为常用,包含了字符串、数组、日期时间等日常开发必需的函数 +3. **资源访问**:`resource.md` 涉及文件、数据库、网络等外部资源的访问 +4. **搜索建议**:在当前目录(`data/tsl_reference_catalog_source/`)使用全局搜索查找特定函数 + +--- + +**返回**: [archive/tsl/syntax_book/function/index.md](../../archive/tsl/syntax_book/function/index.md) diff --git a/data/tsl_reference_catalog_source/math.md b/data/tsl_reference_catalog_source/math.md new file mode 100644 index 00000000..a290f745 --- /dev/null +++ b/data/tsl_reference_catalog_source/math.md @@ -0,0 +1,13179 @@ +#### 数学函数 + +##### 内容 + +- 数值计算 +- 常用数学函数 +- 位运算函数 +- 三角函数 +- 角度量转换 +- 双曲线函数 +- 指数对数函数 +- 精度设置及取整运算 +- 比较判断函数 +- 一般统计量 +- 次序统计量 +- 统计函数 +- 统计分布 +- 统计推断 +- 多元统计分析 +- 回归 +- 灰色系统 +- 主成分分析 +- 时间序列分析 +- 优化 +- 小波分析 +- 财务函数 +- 增长率与比率 +- 概率分布 +- 信号处理 + +##### 数值计算 + +###### 内容 + +- 数值微积分 +- 线性方程组的求解 +- 插值 +- 矩阵运算及分解 +- 数组扩展 +- 其他 + +###### 数值微积分 + +####### 内容 + +- ig_Romberg +- integral +- ig_Trapezoid_1 +- ig_Trapezoid_2 +- ig_Simpson_1 +- ig_Gauss +- ig_Chebyshev +- ig_Simpson_2 +- sf_SinX +- sf_CosX +- sf_eX +- sf_EllipseX_1 +- sf_EllipseX_2 +- Conv +- Hessian + +####### ig_Romberg + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Romberg(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Trapezoid_1 ig_Simpson_1 ig_Gauss ig_Chebyshev + +####### integral + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +return integral(callback, a, b, ’Romberg’); +``` + +其中fun1函数: + +```tsl +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考ig_Trapezoid_1 ig_Trapezoid_2 ig_Simpson_1 ig_Romberg ig_Gauss ig_Chebyshev +ig_Simpson_2 + +####### ig_Trapezoid_1 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Trapezoid_1(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Simpson_1 ig_Romberg ig_Gauss ig_Chebyshev + +####### ig_Trapezoid_2 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Trapezoid_2(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Trapezoid_1 ig_Simpson_1 ig_Romberg ig_Gauss ig_Chebyshev + +####### ig_Simpson_1 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Simpson_1(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Trapezoid_1 ig_Romberg ig_Gauss ig_Chebyshev + +####### ig_Gauss + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Gauss(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Trapezoid_1 ig_Simpson_1 ig_Romberg ig_Chebyshev + +####### ig_Chebyshev + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 3; +callback := "fun1"; +ig_Chebyshev(a, b, CallBack, v); +return v; +function fun1(x) +begin + return 2 * x + 1; +end; +// 结果:10 +``` + +参考integral ig_Trapezoid_1 ig_Simpson_1 ig_Romberg ig_Gauss + +####### ig_Simpson_2 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 1; +b := 2; +callback1 := "y1"; +callback2 := "y2"; +callback3 := "f"; +ig_Simpson_2(a, b, CallBack1, CallBack2, CallBack3, v); +return v; +function y1(x) +begin + return -x; +end; +function y2(x) +begin + return x; +end; +function f(x, y) +begin + return x + 2 * y; +end; +// 结果:4.66667 +``` + +参考integral ig_Simpson_1 + +####### sf_SinX + +范例 + +```tsl +sf_sinx(2, v); +return v; +// 结果: +1.60541 +``` + +参考sf_CosX sf_eX + +####### sf_CosX + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_CosX(2, v); +return v; +// 结果: +0.42298 +``` + +参考sf_SinX sf_eX + +####### sf_eX + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_eX(2, v); +return v; +// 结果:-0.0489 +``` + +参考sf_SinX sf_CosX + +####### sf_EllipseX_1 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +k := 6; +f := 8; +sf_EllipseX_1(k, f, v); +return v; +// 结果:8.05747 +``` + +参考sf_EllipseX_2 + +####### sf_EllipseX_2 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +k := 6; +f := 8; +sf_EllipseX_2(k, f, v); +return v; +// 结果:7.94314 +``` + +参考sf_EllipseX_1 + +####### Conv + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(0.4044, 0.32362, 0.38548, 0.17435, 0.08502, 0.41899, 0.02551, 0.46226); +b := array(0.82284, 0.7466, 0.17411, 0.85894, 0.7105, 0.51353, 0.30399, 0.01498, 0.0914, 0.36445, 0.14731, 0.1659, 0.98853, 0.44569, 0.11908); +return conv(a, b); +``` + +####### Hessian + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return hessian("Hessian.demo", array(3, 4)); +``` + +###### 线性方程组的求解 + +####### 内容 + +- se_Gauss +- se_Gauss_Jordan +- se_Ldl +- se_Cholesky +- se_Gauss_Seidel + +####### se_Gauss + +范例 + +```tsl +A := array((1, 0, 0), +(0, 2, 0), +(0, 0, 3)); +B := array(1, 4, 9); +se_gauss(A, B, X); +return X; +// 结果:array(1,2,3); +``` + +参考se_Gauss_Jordan se_Ldl se_Cholesky se_Gauss_Seidel + +####### se_Gauss_Jordan + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 0, 0), +(0, 2, 0), +(0, 0, 3)); +B := array((1, 3), +(4, 6), +(9, 9)); +se_Gauss_Jordan(A, B, X); +return X; +``` + +X=参考se_Gauss se_Ldl se_Cholesky se_Gauss_Seidel + +####### se_Ldl + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 0, 0), +(0, 2, 0), +(0, 0, 3)); +B := array((1, 3), +(4, 6), +(9, 9)); +se_Ldl(A, B, X); +return X; +``` + +X=参考se_Gauss se_Gauss_Jordan se_Cholesky se_Gauss_Seidel + +####### se_Cholesky + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 0, 0), +(0, 2, 0), +(0, 0, 3)); +B := array((1, 3), +(4, 6), +(9, 9)); +se_Cholesky(A, B, X); +return X; +``` + +X=参考se_Gauss se_Gauss_Jordan se_Ldl se_Gauss_Seidel + +####### se_Gauss_Seidel + +范例 + +```tsl +A := array((1, 0, 0), +(0, 2, 0), +(0, 0, 3)); +B := array((1, 3), +(4, 6), +(9, 9)); +se_Gauss_Jordan(A, B, X); +return X; +``` + +X=参考se_Gauss se_Gauss_Jordan se_Ldl se_Cholesky + +###### 插值 + +####### 内容 + +- interp +- interp_unit +- ip_Lagrangian_A +- ip_Lagrangian_B +- ip_Parabola_A +- ip_Parabola_B +- ip_Hermite_A +- ip_Hermite_B +- ip_Aitken_A +- ip_Aitken_B +- ip_Spline_A +- ip_Spline_B +- ip_Spline_C +- ip_SLQ +- ip_SLG + +####### interp + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +已知数据集有[(x0,y0), (x1,y1)…(xn,yn)] + +1、"nearest" 最邻近插值: + +在数据集寻找两点(xi,yi), (xi+1,yi+1),满足xi≤x≤xi+1。 + +插值方程fx=yi+1 (x-xi>x-xi+1)yi (x-xi≤x-xi+1) + +2、"linear" 分段线性插值: + +插值函数为一次多项式fx=ax+b, (x0,y0), +(x1,y1)是数据集上相异的两点,且x0x1) + +a1x = 1+2x-x0x1-x02 + +同样由β0(x0) = β0(x1)= β0'(x1) = 0,可令 + +β0(x) = c(x-x0)( x-x1)2 + +再由β0'(x0) = 1,得c = 1(x0-x1)2 + +β0(x) = (x-x0) ( x-x1x0-x1)2 ,β1(x) = (x-x1) ( x-x0x1-x0)2 + +a0(x) = [1+2x-x0x1-x0] ( x-x1x0-x1)2 ,β0(x) = (x-x0) ( x-x1x0-x1)2 + +a1(x) = [1+2x-x1x0-x1] ( x-x0x1-x0)2 ,β1(x) = (x-x1) ( x-x0x1-x0)2 + +即 + +a0(x) = [1+2l1(x)]l02(x) + +β0(x) = [x-x0]l02(x) + +a1(x) = [1+2l0(x)]l12(x) + +β1(x) = [x-x1]l12(x) + +l02(x) ,l12(x) 为以(x0,y0),(x1,y1) 插值点得Lagrange一次基函数。 + +可得满足条件得三次埃尔米特插值多项式为 + +H3x = y0a0(x) + y1a1(x) + m0β0x+m1β1x + += y0[1+2x-x0x1-x0] ( x-x1x0-x1)2 + y1[1+2x-x1x0-x1] ( x-x0x1-x0)2 + m0(x-x0) ( +x-x1x0-x1)2 + m1(x-x1) ( x-x0x1-x0)2范例 + +```tsl +X := array(0, 0.01) - > 1; +Y := X ^ 2 - X; +Xi := array(0.005, 0.01) - > 1; +Yi := interp(X, Y, Xi, 'spline'); +return Yi; +// 结果:6 +``` + +1、"nearest" + +```tsl +x_ := array(5, 1, 19, 8); +y_ := array(2, 3, 1, 7); +xi := array(4, 12); +return interp(x_, y_, xi, "nearest"); +// 返回: array(2,7) +``` + +2、" linear" 分段线性插值 + +```tsl +x_ := array(5, 1, 19, 8); +y_ := array(2, 3, 1, 7); +xi := array(4, 12); +return interp(x_, y_, xi, "linear"); +// 返回: array(2.25,4.8182) +``` + +3、"spline" 三次样条插值 + +```tsl +x_ := array(5, 1, 19, 8); +y_ := array(2, 3, 1, 7); +xi := array(4, 12); +return interp(x_, y_, xi, "spline"); +// 返回: array(1.1407,13.9444) +``` + +4、"pchip" 分段三次hermite插值 + +```tsl +x_ := array(5, 1, 19, 8); +y_ := array(2, 3, 1, 7); +xi := array(4, 12); +return interp(x_, y_, xi, "pchip"); +// 返回: array(2.0156,6.7115) +``` + +####### interp_unit + +说明:插值相关函数的单元 + +其中包括的接口如下: + +######## 内容 + +- HISTC2 +- chckxy +- nearest +- linear +- pchip +- pwch +- ppval +- spline + +######## HISTC2 + +算法 + +对于a中每个元素a[j]在b中查找b[i]<=a[j]<=b[j+1],取a[j]的位置为i+1,返回a中满足条件的元素在b中的所属位置。i,j从0开始。范例 + +```tsl +uses interp_unit; // 置顶 +a := 1 - > 10; +b := 3 - > 7; +return HISTC2(a, b); +// 返回:array(0,0,1,1,2,3,4,0,0,0) +``` + +######## chckxy + +范例 + +```tsl +uses interp_unit; // 置顶 +x := array(5, 1, 19, 8); +y := array(2, 3, 1, 7); +chckxy(x, y); +return x | y; +``` + +######## nearest + +算法 + +已知数据集有[(x0,y0), (x1,y1)…(xn,yn)] + +在数据集寻找两点(xi,yi), (xi+1,yi+1),满足xi≤x≤xi+1。 + +插值方程fx=yi+1 (x-xi>x-xi+1)yi (x-xi≤x-xi+1)范例 + +```tsl +uses interp_unit; // 置顶 +x := array(5, 1, 19, 8); +y := array(2, 3, 1, 7); +xi := array(4, 12); +return nearest(x, y, xi); +// 返回:array(3,1) +``` + +######## linear + +算法 + +插值函数为一次多项式fx=ax+b, (x0,y0), +(x1,y1)是数据集上相异的两点,且x0x1) + +a1x = 1+2x-x0x1-x02 + +同样由β0(x0) = β0(x1)= β0'(x1) = 0,可令 + +β0(x) = c(x-x0)( x-x1)2 + +再由β0'(x0) = 1,得c = 1(x0-x1)2 + +β0(x) = (x-x0) ( x-x1x0-x1)2 ,β1(x) = (x-x1) ( x-x0x1-x0)2 + +a0(x) = [1+2x-x0x1-x0] ( x-x1x0-x1)2 ,β0(x) = (x-x0) ( x-x1x0-x1)2 + +a1(x) = [1+2x-x1x0-x1] ( x-x0x1-x0)2 ,β1(x) = (x-x1) ( x-x0x1-x0)2 + +即 + +a0(x) = [1+2l1(x)]l02(x) + +β0(x) = [x-x0]l02(x) + +a1(x) = [1+2l0(x)]l12(x) + +β1(x) = [x-x1]l12(x) + +l02(x) ,l12(x) 为以(x0,y0),(x1,y1) 插值点得Lagrange一次基函数。 + +可得满足条件得三次埃尔米特插值多项式为 + +H3x = y0a0(x) + y1a1(x) + m0β0x+m1β1x + += y0[1+2x-x0x1-x0] ( x-x1x0-x1)2 + y1[1+2x-x1x0-x1] ( x-x0x1-x0)2 + m0(x-x0) ( +x-x1x0-x1)2 + m1(x-x1) ( x-x0x1-x0)2范例 + +```tsl +uses interp_unit; // 置顶 +x := array(5, 1, 19, 8); +y := array(2, 3, 1, 7); +xx := array(4, 12); +return pchip(x, y, xx); +// 返回:array(3.3403,6.9345) +``` + +######## pwch + +######## ppval + +######## spline + +范例 + +```tsl +x := array(5, 1, 19, 8); +y := array(2, 3, 1, 7); +xx := array(4, 12); +return spline(x, y, xx); +// 返回:array(1.1407,13.9444) +``` + +####### ip_Lagrangian_A + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 1.2, 1.5, 2.3, 2.9, 4, 4.5, 8); +Y := X ^ 2 - X; +xv := 3; +ip_Lagrangian_A(X, Y, xv, yv); +return yv; +// 结果:6 +``` + +参考ip_Lagrangian_B ip_Parabola_A ip_Hermite_A ip_Aitken_A + +####### ip_Lagrangian_B + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X0 := 1.3; +h := 0.5; +Y := array(1, 3, 4, 6, 9, 11, 13); +xv := 3; +ip_Lagrangian_B(X0, h, Y, xv, yv); +return yv; +// 结果:7.17766 +``` + +参考ip_Lagrangian_A ip_Parabola_B ip_Hermite_B ip_Aitken_B + +####### ip_Parabola_A + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 1.2, 1.5, 2.3, 2.9, 4, 4.5, 8); +Y := array(1, 3, 4, 7, 9, 13, 15, 20); +xv := 3; +ip_Parabola_A(X, Y, xv, yv); +return yv; +// 结果:9.34581 +``` + +参考ip_Lagrangian_A ip_Parabola_B ip_Hermite_A ip_Aitken_A + +####### ip_Parabola_B + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X0 := 1.3; +h := 0.5; +Y := array(1, 3, 4, 6, 9, 11, 13); +xv := 3; +ip_Parabola_B(X0, h, Y, xv, yv); +return yv; +// 结果:7.08 +``` + +参考ip_Lagrangian_B ip_Parabola_A ip_Hermite_B ip_Aitken_B + +####### ip_Hermite_A + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 1.2, 1.5, 2.3, 2.9, 4, 4.5, 8); +Y := X ^ 2 - X; +Dy := 2 * X - 1; +xv := 3; +ip_Hermite_A(X, Y, Dy, xv, yv); +return yv; +// 结果:6 +``` + +参考ip_Lagrangian_A ip_Parabola_A ip_Hermite_B ip_Aitken_A + +####### ip_Hermite_B + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X0 := 1; +h := 1; +Y := array(0, 2, 6, 12, 20, 30); +Dy := array(1, 3, 5, 7, 9, 11); +xv := 4.5; +ip_Hermite_B(X0, h, Y, Dy, xv, yv); +return yv; +// 结果:15.75 +``` + +参考ip_Lagrangian_B ip_Parabola_B ip_Hermite_A ip_Aitken_B + +####### ip_Aitken_A + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 1.2, 1.5, 2.3, 2.9, 4, 4.5, 8); +Y := array(1, 3, 4, 7, 9, 13, 15, 20); +xv := 3; +ip_Aitken_A(X, Y, xv, yv); +return yv; +// 结果:9.32917 +``` + +参考ip_Lagrangian_A ip_Parabola_A ip_Hermite_A ip_Aitken_B + +####### ip_Aitken_B + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X0 := 1.3; +h := 0.5; +Y := array(1, 3, 4, 6, 9, 11, 13); +xv := 3; +ip_Aitken_B(X0, h, Y, xv, yv); +return yv; +// 结果:7.08 +``` + +参考ip_Lagrangian_B ip_Parabola_B ip_Hermite_B ip_Aitken_A + +####### ip_Spline_A + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 2, 3, 4, 5, 6); +Y := array(0, 2, 6, 12, 20, 30); +dy0 := 1; +dyn_1 := 11; +xv := 4.5; +ip_Spline_A(X, Y, dy0, dyn_1, xv, yv); +return yv; +// 结果:15.75 +``` + +参考ip_Spline_B ip_Spline_C + +####### ip_Spline_B + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 2, 3, 4, 5, 6); +Y := array(0, 2, 6, 12, 20, 30); +ddy0 := 2; +ddyn_1 := 2; +xv := 4.5; +ip_Spline_B(X, Y, ddy0, ddyn_1, xv, yv); +return yv; +// 结果:15.2828 +``` + +参考ip_Spline_A ip_Spline_C + +####### ip_Spline_C + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 2, 3, 4, 5, 6); +Y := array(2, 6, 3, 0, 3, 2); +xv := 3.5; +ip_Spline_C(X, Y, xv, yv); +return yv; +// 结果:0.71591 +``` + +参考ip_Spline_A ip_Spline_B + +####### ip_SLQ + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 2, 3, 4); +Y := array(1, 2, 3); +z := array((4, 6, 8), +(6, 9, 10), +(11, 20, 25), +(14, 24, 30)); +xv := 3.5; +yv := 4.5; +ip_SLQ(X, Y, z, xv, yv, zv); +return zv; +// 结果:29.59375 +``` + +参考ip_SLG + +####### ip_SLG + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array(1, 2, 3, 4); +Y := array(1, 2, 3); +z := array((4, 6, 8), +(6, 9, 10), +(11, 20, 25), +(14, 24, 30)); +xv := 3.5; +yv := 4.5; +ip_SLG(X, Y, z, xv, yv, zv); +return zv; +// 结果:31.54688 +``` + +参考ip_SLQ + +###### 矩阵运算及分解 + +####### 内容 + +- mt_Transposition +- mt_Multiplication +- mt_Addition +- mt_iv_Gauss_Jordan +- mt_iv_Ldl +- mt_Subtraction +- Mt_decompose_lu +- mt_decompose_qr +- mt*va* Cholesky +- mt_decompose_chol +- chol +- mt_va_Gauss_Jordan +- mt_decompose_svd +- mt_decompose_ldl +- mt_decompose_eig +- Standarize_II +- ReIndex2 +- Det +- isSymmetry +- Orth +- roots +- Eigen +- pinv +- norm2 +- Cond +- diag +- isDefinite + +####### mt_Transposition + +用途:数值计算相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +A := array((1, 3, 6), +(0, 4, 2)); +mt_Transposition(A, C); +return C; +// 结果: +array((1, 0), +(3, 4), +(6, 2)) +``` + +参考mt_Multiplication mt_Addition mt_Subtraction + +####### mt_Multiplication + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 3, 6), +(0, 4, 2)); +B := array((1, 2), +(4, 0), +(3, 2)); +mt_Multiplication(A, B, C); +return C; +// 结果: +array((31, 14), +(22, 4)) +``` + +参考mt_Addition mt_Subtraction mt_Transposition + +####### mt_Addition + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 3, 6), +(0, 4, 2)); +B := array((1, 2, 4), +(0, 3, 2)); +mt_Addition(A, B, C); +return C; +// 结果: +array((2, 5, 10), +(0, 7, 4)) +``` + +参考mt_Multiplication mt_Subtraction mt_Transposition + +####### mt_iv_Gauss_Jordan + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((3, 2), +(4, 6)); +mt_iv_Gauss_Jordan(A, X); +return X; +// 结果: +array((0.6, -0.2), +(-0.4, 0.3)) +``` + +参考mt_iv_Ldl + +####### mt_iv_Ldl + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 4), +(4, 6)); +mt_iv_Ldl(A, X); +return X; +// 结果: +array((-0.6, 0.4), +(0.4, -0.1)) +``` + +参考mt_iv_Gauss_Jordan + +####### mt_Subtraction + +用途:进行字符串提取或替换处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 3, 6), +(0, 4, 2)); +B := array((1, 2, 4), +(0, 3, 2)); +mt_Subtraction(A, B, C); +return C; +// 结果: +array((0, 1, 2), +(0, 1, 0)) +``` + +参考mt_Multiplication mt_Addition mt_Transposition + +####### Mt_decompose_lu + +用途:数值计算相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +H := corr(rand(100, 4)); +Mt_decompose_lu(H, L, U); +return array(L, U); +``` + +参考Mt_decompose_lu chol mt_decompose_qr mt_decompose_eig mt_decompose_svd +mt_decompose_ldl mt_decompose_chol + +####### mt_decompose_qr + +用途:数值计算相关函数。 +参数: + +返回:整数。 + +范例 + +范例01: + +```tsl +H := corr(rand(100, 4)); +mt_decompose_qr(H, Q, R); // QR分解 +return array(Q, R); +``` + +范例02: + +```tsl +H := corr(rand(100, 4)); +return mt_decompose_qr(H); // 返回上三角矩阵 +``` + +范例03: + +```tsl +H := corr(rand(100, 4)); +mt_decompose_qr(H, Q, R, E, 0); +return array(Q, R, E); +``` + +参考Mt_decompose_lu chol mt_decompose_eig mt_decompose_svd mt_decompose_ldl +mt_decompose_chol + +####### mt*va* Cholesky + +范例 + +```tsl +A := array((1, 2), +(2, 6)); +mt_va_Cholesky(A, v); +return v; +// 结果:1.414 +``` + +参考mt_va_Gauss_Jordan + +####### mt_decompose_chol + +参考Mt_decompose_lu chol mt_decompose_qr mt_decompose_eig mt_decompose_ldl + +####### chol + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +H := corr(rand(100, 4)); +chol(H, L, p); // 乔列斯基分解 +if p = -1 then return L; // p=-1表示分解成功 +``` + +参考Mt_decompose_lu mt_decompose_qr mt_decompose_eig mt_decompose_svd +mt_decompose_ldl mt_decompose_chol + +####### mt_va_Gauss_Jordan + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((1, 4), +(4, 6)); +mt_va_Gauss_Jordan(A, v); +return v; +// 结果:-10 +``` + +参考mt*va* Cholesky + +####### mt_decompose_svd + +算法 + +假设矩阵A为一个m×n的矩阵,定义矩阵A的SVD分解为: + +A=USDT + +其中U为m×m矩阵,S为m×n矩阵,D为个n×n矩阵,其中U、D都为酉矩阵。 + +求解U、S、D三个矩阵的步骤如下: + +1)根据下式求解方阵ATA的特征值与特征向量: + +ATAdi=λidi + +n个特征向量di组成右奇异矩阵D。 + +同理,利用AATui=λiui计算可得左奇异矩阵U。 + +2)求奇异值矩阵S(除了对角线为奇异值σi,其余位置为0)可根据以下公式求得: + +AD=USAdi=uiσi + +(也可通过σi=λi计算),即可计算出奇异值矩阵S。范例 + +```tsl +// 计算矩阵A的SVD分解 +A := array((0, 1), (1, 1), (1, 0)); +Mt_Decompose_SVD(A, U, S, D); +// 反推初始矩阵A,使用U:*(eye(3,2)*S):*`D; +return array((U), (S), (D)); +``` + +U,S,D矩阵分别为: + +####### mt_decompose_ldl + +参考Mt_decompose_lu chol mt_decompose_qr mt_decompose_eig mt_decompose_chol + +####### mt_decompose_eig + +用途:数值计算相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +H := corr(rand(100, 4)); +mt_decompose_eig(H, wr, wi, vr); +return array(wr, wi, vr); +``` + +参考Mt_decompose_lu chol mt_decompose_qr mt_decompose_svd mt_decompose_ldl +mt_decompose_chol + +####### Standarize_II + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 每列之和为0 +A := rand(5, 5); +A := Standarize_II(a, 7); +return A; +``` + +####### ReIndex2 + +范例 + +范例数据表:a:=array('C':('A':1,'B':'too'),'D':('A':2,'B':'two')); + +其显示如下: + +范例一:将表列标改为数字 + +```tsl +a := array('C':('A':1, 'B':'too'), 'D':('A':2, 'B':'two')); +return reindex2(a, 0); +``` + +范例二:将行列标作为首列首行 + +```tsl +a := array('C':('A':1, 'B':'too'), 'D':('A':2, 'B':'two')); +return reindex2(a, 5); +``` + +####### Det + +范例 + +```tsl +A := array((1, 2), (3, 4)); +return det(A); // -2 +``` + +####### isSymmetry + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +A := array((2, 1), (1, 3)); +return isSymmetry(A, 0.1); // 1 +``` + +####### Orth + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 计算矩阵A的标准正交基 +A := array((0, 1), (1, 1), (1, 0)); +return Orth(A); +``` + +####### roots + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求根:3x^3+x^2+x^1+0^0=0 +return roots(array(0, 1, 1, 3)); +``` + +####### Eigen + +范例 + +```tsl +A := array((1, 2), (3, 4)); +eigen(A, eigen); +return eigen; +// array(-0.37,5.37) +``` + +####### pinv + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array((9, 1), (-1, 0), (0, 2), (1, 1)); +return pinv(x); +``` + +####### norm2 + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((2, 1), (1, 3)); +return norm2(A, 'inf'); // 4 +``` + +####### Cond + +范例 + +```tsl +x := array((9, 1), (-1, 0), (0, 2), (1, 1)); +return cond(x); // 4.22 +``` + +####### diag + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array((2, 1), (1, 3)); +return diag(A); // array(2,3); +``` + +####### isDefinite + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +x := array((3, 1), (1, 4)); +return isDefinite(x); // 1 +``` + +###### 数组扩展 + +####### 内容 + +- Any +- ALL + +####### Any + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 判断非数组的真假 +return any('a', 0); +``` + +范例二: + +```tsl +// 判断特殊数据类型的真假 +return any(array(1, '', ' ', nan, nil, inf, -inf, array()), 1); +``` + +结果 + +范例三: + +```tsl +// 判断二维数组的行 +f := array('e':('A':1, 'B':0), 'f':('A':2, 'B':''), 'd':('A':3, 'B':nil)); +return any(f, 1); +``` + +结果:’e’,’f’,’d’为行标,表示该行结果。其中,’d’行中,对集合(3,nil)判断为真,则该行值判断结果为1,’B’列中。 + +范例四: + +```tsl +// 判断多维数组的行 +t := array('e':('A':0, 'B':0), 'f':('A':2, 'B':array(1, 0))); +return any(t, 1); +``` + +结果:’f’行中对集合(0,array(1,0))->(0,1)->1,则该列结果为1 + +范例五: + +```tsl +// 判断多维数组的列 +t := array('e':('A':1, 'B':1), 'f':('A':2, 'B':array(1, 0))); +return any(t, 2); +``` + +结果 + +####### ALL + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 判断数组中所有元素是否都为真 +return all(array(1, 2, -1, 1, 9)); +``` + +范例二: + +```tsl +// 判断特殊数据类型的真假 +return all(array(1, '', ' ', nan, nil, inf, -inf, array()), 1); +``` + +结果 + +范例三: + +```tsl +// 判断二维数组的行 +f := array('e':('A':1, 'B':0), 'f':('A':2, 'B':3), 'd':('A':3, 'B':nil)); +return all(f, 1); +``` + +结果:’e’,’f’,’d’为行标,表示该行判断结果。其中,’d’行中,对集合(3,nil)判断为假,因为其中nil判断为假。 + +范例四: + +```tsl +// 判断多维数组的行 +t := array('e':('A':1, 'B':1), 'f':('A':2, 'B':array(1, 0))); +return all(t, 1); +``` + +结果:’f’行中对集合(2,array(1,0))->(1,0)->0,则该行结果为0 + +范例五: + +```tsl +// 判断多维数组的列 +t := array('e':('A':1, 'B':1), 'f':('A':2, 'B':array(1, 0))); +return all(t, 2); +``` + +结果:’B’列中对集合(1,array(1,0))->(1,0)->0,则该行结果为0 + +###### 其他 + +####### 内容 + +- perms +- nchoosek +- MaxDrawDown +- MinRecoveryTime +- Betainc +- PercentileOfScore +- GenerateCombinations +- Percentage + +####### perms + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:求10的阶乘 + +```tsl +return perms(10); +``` + +返回结果:3628800 + +范例02:排列组合 + +```tsl +return perms(array("a", "b", "c")); +``` + +返回结果: + +array( + +("c","b","a"), + +("c","a","b"), + +("b","c","a"), + +("b","a","c"), + +("a","b","c"), + +("a","c","b")) + +范例03:返回数组Array(('A','B'),('C', 'D'))中任意两个数据的排列组合 + +```tsl +v := array(('A', 'B'), ('C', 'D')); +return perms(v, 2); +``` + +范例04:对排列组合的每列求和 + +```tsl +function test_1cth(); +begin + func := createobject("funcexe"); + a := array("A", "B", "C"); + return perms(a, 3, func); +end; +type funcexe = class() +data; +function create(); +begin + data := ""; +end; +function exe(dat); +begin + data += dat; +end; +end; +``` + +####### nchoosek + +用途:数值计算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return nchoosek(array('a', 'b', 'c', 'd'), 2); +``` + +结果: + +array( + +("d","c"), + +("d","b"), + +("d","a"), + +("c","b"), + +("c","a"), + +("b","a")) + +####### MaxDrawDown + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +算法 + +数据差序列 + +Fi,j=xj-xi ,其中(i 11; +return LogN(Base, X); +``` + +这里最直观的的理解是把二维数组看成一维数据(其每一个元素是一维数组),所以,这个问题也就简化为两个等大小的一维数组在做计算了。超过两个以上主要参数的操作是类似的 + +支持这项操作的函数包括: + +单参数输入: + +常用数学函数:Odd,Abs,Sqr,Sqrt + +三角函数:Sin,Cos,Tan,Cot,CoTan,Sec,Csc,Secant,Cosecant,ArcSin,ArcCos,ArcTan,ArcCot,ArcSec,ArcCsc,SinCos + +角度转换函数,双曲线函数 + +指数对数函数:Ln,LnXP1,Log10,Log2,Exp + +精度设置及取整函数:Int,Ceil,Ceil32,Ceil64,Floor,Floor32,Floor64,Trunc,Trunc32,Trunc64,Frac,Round,Round32,Round64,SimpleRound,SimpleRound32,SimpleRound64 + +比较判断函数:IsNan,IsInfinite,Sign + +多个参数输入: + +DivMod,Frexp,Ldexp,Poly,ArcTan2,Hypot,LogN,IntPower,Power,RoundTo,SimpleRoundTo,IsZero,Min,Max,CompareValue,SameValue,RandomRange,InRange,EnsureRange,RandG,财务函数等 + +##### 位运算函数 + +###### 内容 + +- \_And +- \_Or +- \_Not +- \_Xor +- \_Shl +- \_Shr +- \_Rol +- \_Ror + +###### \_And + +范例 + +```tsl +return _And(6, 3); // 返回十进制(6=110) and 3=(11) 最后得到二进制10 +// 结果:2 +``` + +参考\_Or \_Not \_Xor \_Shl \_Shr \_Rol \_Ror + +###### \_Or + +范例 + +```tsl +return _Or (6, 3); +// 结果:7 +// 返回十进制(6=110) or 3=(11) 最后得到二进制111,十进制是7 +``` + +参考\_And \_Not \_Xor \_Shl \_Shr \_Rol \_Ror + +###### \_Not + +范例 + +```tsl +return _Not (4); +// 结果:-5 +// 返回十进制_not (4=00000100) 取非运算最后得到二进制11111011,十进制//是-5,注意:在计算机中,负数以其正值的补码形式表示。补码是烦吗+1, +// 5=00000101,得到反码11111010,得到补码11111011=-5 +``` + +参考\_And \_Or \_Xor \_Shl \_Shr \_Rol \_Ror + +###### \_Xor + +范例 + +```tsl +return _Xor (6, 3); +// 结果:5 +// 返回十进制 (6=110) Xor (3=011) 最后得到二进制101,十进制是5 +``` + +参考\_And \_Or \_Not \_Shl \_Shr \_Rol \_Ror + +###### \_Shl + +范例 + +```tsl +return _Shl (6, 3); +// 结果:48 +// 返回十进制 (6=110) _Shl 3 最后得到二进制110000,十进制是48 +``` + +参考\_And \_Or \_Not \_Xor \_Shr \_Rol \_Ror + +###### \_Shr + +范例 + +```tsl +return _Shr (36, 3); +// 结果:4 +// 返回十进制 (36=100100) _Shr 3最后得到二进制00000100,十进制是4 +``` + +参考\_And \_Or \_Not \_Xor \_Shl \_Rol \_Ror + +###### \_Rol + +范例 + +```tsl +return _Rol (36, 3); +// 结果:288 +// 返回十进制 (36=100100) 左移3位,最后得到二进制100100000,十进制是//288 +``` + +参考\_And \_Or \_Not \_Xor \_Shl \_Shr \_Ror + +###### \_Ror + +范例 + +```tsl +return _Ror (36, 2); +// 结果:9 +// 返回十进制 (36=100100) 右移2位,最后得到二进制00001001,十进制是9 +``` + +参考\_And \_Or \_Not \_Xor \_Shl \_Shr \_Rol + +##### 三角函数 + +###### 内容 + +- Sin +- Cos +- SinCos +- Tan +- Cot +- CoTan +- Sec +- Csc +- Secant +- Cosecant +- ArcSin +- ArcCos +- ArcTan +- ArcTan2 +- ArcCot +- ArcSec +- ArcCsc +- Hypot + +###### Sin + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求sin(π/6) +return Sin(pi() / 6); +// 结果:0.5 +``` + +参考简单函数对数组支持 Cos SinCos ArcSin Sinh + +###### Cos + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求cos(π/3) +return Cos(pi() / 3); +// 结果:0.5 +``` + +参考简单函数对数组支持 Sin SinCos Cosecant ArcCos Cosh + +###### SinCos + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +SinCos(pi() / 2, sin, cos); +return array(sin, cos); +``` + +参考简单函数对数组支持 Cos SinCos ArcSin Sinh + +###### Tan + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求tan(π/4) +return Tan(pi() / 4); +// 结果:1 +``` + +参考简单函数对数组支持 Cot CoTan ArcTan ArcTan2 Tanh + +###### Cot + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Cot (π/4) +return Cot(pi() / 4); +// 结果:1 +``` + +参考简单函数对数组支持 CoTan ArcCot ArcCotH Tan + +###### CoTan + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Cotan(π/4) +return CoTan(pi() / 4); +// 结果:1 +``` + +参考简单函数对数组支持 CoTan ArcCot ArcCotH Tan + +###### Sec + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Sec(π/3) +return Sec(pi() / 3); +// 结果:2 +``` + +参考简单函数对数组支持 Csc Secant ArcSec SecH + +###### Csc + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Csc(π/6) +return Csc(pi() / 6); +// 结果:2 +``` + +参考简单函数对数组支持 Sec Secant ArcCsc CscH + +###### Secant + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Secant (π/6) +return Secant(pi() / 3); +// 结果:2 +``` + +参考简单函数对数组支持 Sec Csc ArcSec SecH + +###### Cosecant + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Cosecant (π/6) +return Cosecant(pi() / 6); +// 结果:2 +``` + +参考简单函数对数组支持 Sin SinCos Cosecant ArcCos Cosh + +###### ArcSin + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return ArcSin(1); +// 结果:1.57 //约等于π/2 +``` + +参考简单函数对数组支持 Sin ArcSinh + +###### ArcCos + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return ArcCos(0); +// 结果:1.57 //约等于π/2 +``` + +参考简单函数对数组支持 Cos Cosecant ArcCosh + +###### ArcTan + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcTan(1) +return ArcTan(1); +// 结果:0.785398163397448 //该值=pi()/4 +``` + +参考简单函数对数组支持 ArcTan2 ArcTan ArcTanh + +###### ArcTan2 + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return ArcTan2(1, 2); +// 结果:0.46 +``` + +参考简单函数对数组支持 Tan ArcTan ArcTanh + +###### ArcCot + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return ArcCot(1); +// 结果:0.7854 +``` + +参考简单函数对数组支持 Cot CoTan ArcCotH + +###### ArcSec + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcSec(2) +return ArcSec(2); +// 结果:1.05 +``` + +参考简单函数对数组支持 Secant Sec ArcSecH + +###### ArcCsc + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcCsc(2) +return ArcCsc(2); +// 结果:0.52 +``` + +参考简单函数对数组支持 Csc ArcCscH + +###### Hypot + +用途:三角函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Hypot (3,4) +return Hypot(3, 4); // 返回sqrt(3^2+4^2) +// 结果:5 +``` + +参考简单函数对数组支持 ArcTan2 + +##### 角度量转换 + +###### 内容 + +- RadToDeg +- RadToGrad +- RadToCycle +- DegToRad +- DegToGrad +- DegToCycle +- GradToRad +- GradToDeg +- GradToCycle +- CycleToRad +- CycleToDeg +- CycleToGrad + +###### RadToDeg + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求RadToDeg (π/3) +return RadToDeg(pi() / 3); +// 结果:60 +``` + +参考简单函数对数组支持 RadToGrad RadToCycle DegToRad DegToGrad DegToCycle +GradToRad GradToDeg CycleToRad CycleToDeg + +###### RadToGrad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求RadToGrad (π/4) +return RadToGrad(pi() / 4); +// 结果:50 +``` + +参考简单函数对数组支持 RadToDeg RadToCycle DegToRad DegToGrad GradToRad +GradToDeg GradToCycle CycleToRad CycleToGrad + +###### RadToCycle + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求RadToCycle (π/4) +return RadToCycle(pi() / 4); +// 结果:0.125 +``` + +参考简单函数对数组支持 RadToDeg RadToGrad DegToRad DegToCycle GradToRad +GradToCycle CycleToRad CycleToDeg CycleToGrad + +###### DegToRad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求DegToRad (60) +return DegToRad(60); +// 结果:1.0472 //返回π/3 +``` + +参考简单函数对数组支持 RadToDeg RadToGrad RadToCycle DegToGrad DegToCycle +GradToRad GradToDeg CycleToRad CycleToDeg + +###### DegToGrad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求DegToGrad (90) +return DegToGrad(90); +// 结果:100 +``` + +s参考简单函数对数组支持 RadToDeg RadToGrad DegToRad DegToCycle GradToRad +GradToDeg GradToCycle CycleToDeg CycleToGrad + +###### DegToCycle + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求DegToCycle(45) +return DegToCycle(45); +// 结果:0.125 +``` + +参考简单函数对数组支持 RadToDeg RadToCycle DegToRad DegToGrad GradToDeg +GradToCycle CycleToRad CycleToDeg CycleToGrad + +###### GradToRad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求GradToRad(50) +return GradToRad(50); +// 结果:0.79//结果相当于π/4 +``` + +参考简单函数对数组支持 RadToDeg RadToGrad RadToCycle DegToRad DegToGrad +GradToDeg GradToCycle CycleToRad CycleToGrad + +###### GradToDeg + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求GradToDeg(50) +return GradToDeg(50); +// 结果:45 +``` + +参考简单函数对数组支持 RadToDeg RadToGrad DegToRad DegToGrad DegToCycle +GradToRad GradToCycle CycleToDeg CycleToGrad + +###### GradToCycle + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求GradToCycle(100) +return GradToCycle(100); +// 结果:0.25 +``` + +参考简单函数对数组支持 RadToGrad RadToCycle DegToGrad DegToCycle GradToRad +GradToDeg CycleToRad CycleToDeg CycleToGrad + +###### CycleToRad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求CycleToRad(1/4) +return CycleToRad(1 / 4); +// 结果:1.57 //相当于π/2 +``` + +参考简单函数对数组支持 RadToDeg RadToGrad RadToCycle DegToRad DegToCycle +GradToRad GradToCycle CycleToDeg CycleToGrad + +###### CycleToDeg + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求CycleToDeg(1/4) +return CycleToDeg(1 / 4); +// 结果:90 +``` + +参考简单函数对数组支持 RadToDeg RadToCycle DegToRad DegToGrad DegToCycle +GradToDeg GradToCycle CycleToRad CycleToGrad + +###### CycleToGrad + +用途:角度量转换相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求CycleToGrad(1/4) +return CycleToGrad(1 / 4); +// 结果:100 +``` + +参考简单函数对数组支持 RadToGrad RadToCycle DegToGrad DegToCycle GradToRad +GradToDeg GradToCycle CycleToRad CycleToDeg + +##### 双曲线函数 + +###### 内容 + +- Sinh +- Cosh +- Tanh +- CotH +- SecH +- CscH +- ArcCosh +- ArcSinh +- ArcTanh +- ArcCotH +- ArcSecH +- ArcCscH + +###### Sinh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Sinh (2) +return Sinh(2); +// 结果:3.63 +``` + +参考简单函数对数组支持 Cosh ArcSinh Sin + +###### Cosh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Cosh(2) +return Cosh(2); +// 结果:3.76 +``` + +参考简单函数对数组支持 Cos Cosecant Sinh ArcCosh + +###### Tanh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求Tanh(2) +return Tanh(2); +// 结果:0.96 +``` + +参考简单函数对数组支持 Tan CotH ArcTanh + +###### CotH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求CotH(2) +return CotH(2); +// 结果:1.04 +``` + +参考简单函数对数组支持 Cot CoTan Tanh ArcCotH + +###### SecH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求SecH(2) +return SecH(2); +// 结果:0.27 +``` + +参考简单函数对数组支持 Secant Sec CscH ArcSecH + +###### CscH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求CscH (2) +return CscH(2); +// 结果:0.28 +``` + +参考简单函数对数组支持 Csc SecH ArcCscH + +###### ArcCosh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcCosh(2) +return ArcCosh(2); +// 结果:1.32 +``` + +参考简单函数对数组支持 Cosh ArcCos + +###### ArcSinh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcSinh (2) +return ArcSinh(2); +// 结果:1.44 +``` + +参考简单函数对数组支持 ArcSin Sinh + +###### ArcTanh + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcTanh(0.8) +return ArcTanh(0.8); +// 结果:1.1 +``` + +参考简单函数对数组支持 Tanh ArcTan + +###### ArcCotH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcCotH(4) +return ArcCotH(4); +// 结果:0.26 +``` + +参考简单函数对数组支持 ArcCot Tanh + +###### ArcSecH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcSecH(4) +return ArcSecH(0.5); +// 结果:1.32 +``` + +参考简单函数对数组支持 SecH ArcSec + +###### ArcCscH + +用途:双曲线函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ArcCscH(4) +return ArcCscH(4); +// 结果:0.25 +``` + +参考简单函数对数组支持 ArcCsc CscH + +##### 指数对数函数 + +###### 内容 + +- Ln +- LnXP1 +- Log10 +- Log2 +- LogN +- Exp +- IntPower +- Power + +###### Ln + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求ln(e^2) +return Ln(7.38905609893065); +// 结果:2 +``` + +参考简单函数对数组支持 LnXP1 Log10 Log2 LogN Exp IntPower Power + +###### LnXP1 + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return LnXP1(3); +// 结果:1.39 //返回ln4 +``` + +参考简单函数对数组支持 Ln Log10 Log2 LogN Exp IntPower Power + +###### Log10 + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Log10(100); +// 结果:2 //返回log10100 +``` + +参考简单函数对数组支持 Ln LnXP1 Log2 LogN Exp IntPower Power + +###### Log2 + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Log2(8); +// 结果:3 //返回log28 +``` + +参考简单函数对数组支持 Ln LnXP1 Log10 LogN Exp IntPower Power + +###### LogN + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return LogN(2, 8); +// 结果:3 //返回log28 +``` + +参考简单函数对数组支持 Ln LnXP1 Log10 Log2 Exp IntPower Power + +###### Exp + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求e^2 +return Exp(2); +// 结果:7.38905609893065 +``` + +参考简单函数对数组支持 Ln LnXP1 Log10 Log2 LogN IntPower Power + +###### IntPower + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return IntPower(2, 3.2); +// 结果:8 //返回2^3 +``` + +参考简单函数对数组支持 Ln LnXP1 Log10 Log2 LogN Exp Power + +###### Power + +用途:指数对数函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Power(2, 3.2); +// 结果:9.19 //返回2^3.2 +``` + +参考简单函数对数组支持 Ln LnXP1 Log10 Log2 LogN Exp IntPower + +##### 精度设置及取整运算 + +###### 内容 + +- Int +- Ceil +- Ceil32 +- Ceil64 +- Floor +- Floor32 +- Floor64 +- Trunc +- Trunc32 +- Trunc64 +- Frac +- Round +- Round32 +- Round64 +- SimpleRound +- SimpleRound32 +- SimpleRound64 +- RoundTo +- SimpleRoundTo + +###### Int + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求x +X := 2.45; +return Int(x); +// 结果:2.0 +``` + +参考简单函数对数组支持 Ceil Floor Trunc Frac + +###### Ceil + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Ceil(-2.8); +// 结果:-2 +``` + +参考简单函数对数组支持 Ceil32 Ceil64 Int Floor Trunc Frac + +###### Ceil32 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Ceil32(-2.8); +// 结果:-2 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Ceil64 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Ceil64(-2.8); +// 结果:-2 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Floor + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Floor(-2.8); +// 结果:-3 +``` + +参考简单函数对数组支持 Floor32 Floor64 Int Ceil Trunc Frac + +###### Floor32 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Floor32(-2.8); +// 结果:-3 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Floor64 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Floor64(-2.8); +// 结果:-3 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Trunc + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := Trunc(-6.8); +return x; +// 结果:-6 +``` + +参考简单函数对数组支持 Trunc32 Trunc64 Int Ceil Floor Frac + +###### Trunc32 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := Trunc32(-6.8); +return x; +// 结果:-6 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Trunc64 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := Trunc64(6.8); +return x; +// 结果:6 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc Frac + +###### Frac + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求x +X := 2.45; +return Frac(x); +// 结果:0.45 +``` + +参考简单函数对数组支持 Int Ceil Floor Trunc + +###### Round + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求x +X := 3.5; +return Round(x); +// 结果:4 +``` + +参考简单函数对数组支持 Round32 Round64 SimpleRound RoundTo SimpleRoundTo + +###### Round32 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := Round32(6.8); +return x; +// 结果:7 +``` + +参考简单函数对数组支持 Round SimpleRound RoundTo SimpleRoundTo + +###### Round64 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := Round64(3.5); +return x; +// 结果:4 +``` + +参考简单函数对数组支持 Round SimpleRound RoundTo SimpleRoundTo + +###### SimpleRound + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 求x +X := 3.5; +return SimpleRound(x); +// 结果:4 +``` + +参考简单函数对数组支持 SimpleRound32 SimpleRound64 Round RoundTo SimpleRoundTo + +###### SimpleRound32 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := SimpleRound32(6.8); +return x; +// 结果:7 +``` + +参考简单函数对数组支持 Round SimpleRound RoundTo SimpleRoundTo + +###### SimpleRound64 + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := SimpleRound64(3.5); +return x; +// 结果:4 +``` + +参考简单函数对数组支持 Round SimpleRound RoundTo SimpleRoundTo + +###### RoundTo + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:整数四舍五入 + +```tsl +return RoundTo(1234567.3, 4); +// 结果:1230000 +``` + +范例02:小数部分四舍五入 + +```tsl +return RoundTo(1.234567, -3); +// 结果:1.235 +``` + +参考简单函数对数组支持 Round SimpleRound SimpleRoundTo + +###### SimpleRoundTo + +用途:精度设置及取整运算相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +return SimpleRoundTo(1234567.3,4); +// 结果:1230000 +``` + +范例02: + +```tsl +return SimpleRoundTo(-1.235, -2); +// -1.24 +``` + +参考简单函数对数组支持 Round SimpleRound RoundTo + +##### 比较判断函数 + +###### 内容 + +- IsNan +- IsInfinite +- Sign +- IsZero +- Min +- Max +- CompareValue +- SameValue +- RandomRange +- InRange +- EnsureRange + +###### IsNan + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +范例01:判断单个值是否nan + +```tsl +v := nan; +return IsNan(v); // 1 +``` + +范例02:判断数组中各元素是否nan + +```tsl +Data := array(2, nan, 3, '', 's', nil); +return IsNan(data); +``` + +参考简单函数对数组支持 IsInfinite + +###### IsInfinite + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +范例01:判断单个值是否inf + +```tsl +return IsInfinite(inf); +// 结果:1 +``` + +范例02:判断数组中各元素是否nan + +```tsl +Data := array(2, nan, 3, '', 's', nil, inf); +return IsInfinite(data); +``` + +参考简单函数对数组支持 IsNan + +###### Sign + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Sign(-2); +// 结果:-1 +``` + +参考简单函数对数组支持 + +###### IsZero + +用途:判断条件是否成立。 +参数: + +返回:布尔值。 + +范例 + +```tsl +a := 1.400000000001; +b := 1.399999999999; +return IsZero(a - b, 0.000000001); // 在9位小数的精度下 +// 结果:1 +``` + +参考简单函数对数组支持 CompareValue SameValue RandomRange InRange EnsureRange + +###### Min + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 比较两个值 +return Min(3, 3.6); +// 结果:3 +``` + +比较两个数组 + +```tsl +a := array(1, 3, 5); +b := array(2, 3, 4); +return Min(a, b); +``` + +参考简单函数对数组支持 MinValue MinIntValue MaxValue MaxIntValue Max + +###### Max + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Max(5, 5.6); +// 结果:5.6 +return Max(array(1, 2, 8), array(4, 5, 6)); +``` + +参考简单函数对数组支持 MinValue MinIntValue MaxValue MaxIntValue Min + +###### CompareValue + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return CompareValue(3, 4, 0.5); +// 结果:-1 +// 表示3与4之间的差距超过0.5则正常比较,否则认为相等 +``` + +参考简单函数对数组支持 IsZero SameValue RandomRange InRange EnsureRange + +###### SameValue + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return SameValue(3, 4, 0.5); +// 结果:0 +// 表示3与4之间的差距在0.5之内认为相等,否则认为不相等 +``` + +参考简单函数对数组支持 IsZero CompareValue RandomRange InRange EnsureRange + +###### RandomRange + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return RandomRange(4.7, 8.5); +// 结果:5//返回4到8之间的随机整数 +``` + +参考简单函数对数组支持 IsZero CompareValue SameValue InRange EnsureRange + +###### InRange + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return InRange(4.3, 4, 8); +// 结果:1 +``` + +参考简单函数对数组支持 IsZero CompareValue SameValue RandomRange EnsureRange + +###### EnsureRange + +用途:比较判断函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return EnsureRange(4.3, 4, 8); +// 结果:4.3 +``` + +参考简单函数对数组支持 IsZero CompareValue SameValue RandomRange InRange + +##### 一般统计量 + +###### 内容 + +- MinIntValue +- SumOfSquares +- StdDev +- Mean +- Sum +- MaxValue +- MinValue +- Norm +- SumsAndSquares +- MaxIntValue +- SumInt +- Harmean +- Variance +- MeanAndStdDev +- AveDev +- Skewness +- TotalVariance +- Product +- PopnStdDev +- kurtosis2 +- Median +- skewness2 +- 统计函数功能拓展 +- Kurtosis +- Mode +- RandG +- Geomean +- PopnVariance +- MomentSkewKurtosis +- DevSq +- randomfrom + +###### MinIntValue + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 6.5, 7.6); +return MinIntValue(a); +// 结果:3 +``` + +参考统计函数功能拓展 MinValue MaxValue MaxIntValue Min Max + +###### SumOfSquares + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(2, 3, 1, 5, 6.5, 7.5); +return SumOfSquares(a); +// 结果:124 +``` + +参考统计函数功能拓展 Norm SumsAndSquares + +###### StdDev + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求样本标准差 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return StdDev(a); +// 结果:1.46070759108956 //样本a的标准差 +``` + +范例02:二维数组指定列+指定步长计算样本标准差 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-样本标准差"] := StdDev(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 SumOfSquares Norm PopnStdDev Variance PopnVariance + +###### Mean + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求平均值 + +```tsl +a := array(2, 3, 1, 5, 6, 7); +return Mean(a); +// 结果:4 +``` + +范例02:二维数组指定列+指定步长计算平均 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-平均"] := Mean(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Sum StdDev Geomean Harmean Mode Median + +###### Sum + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求和 + +```tsl +a := array(2, 3, 1, 5, 6, 7); +return Sum(a); +// 结果:24 +``` + +范例02:二维数组指定列+指定步长求和 + +```tsl +arr := ones(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-累加"] := Sum(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Mean SumInt SumOfSquares Norm SumsAndSquares + +###### MaxValue + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求最大值 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 6.5, 7.6); +return MaxValue(a); +// 结果:7.6 +``` + +范例02:二维数组指定列+指定步长计算最大值 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-最大"] := MaxValue(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 MinValue MinIntValue MaxIntValue Min Max + +###### MinValue + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求最小值 + +```tsl +a := array(2, 3, 1, 5, 6, 7); +return MinValue(a); +// 结果:1 +``` + +范例02:二维数组指定列+指定步长计算最小值 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-最小"] := MinValue(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 MinIntValue MaxValue MaxIntValue Min Max + +###### Norm + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求平方和的平方根 + +```tsl +a := array(5, 3, 5, 5, 7, 7); +return Norm(a); +// 结果:13.490737563232 +``` + +范例02:二维数组指定列+指定步长计算平方和的平方根 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-平方和的平方根"] := Norm(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 SumOfSquares + +###### SumsAndSquares + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(2, 3, 1, 5, 6, 7); +// b是总和,c是平方和 +SumsAndSquares(a, b, c); +return array(b, c); +``` + +参考统计函数功能拓展 Sum SumOfSquares + +###### MaxIntValue + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return MaxIntValue(a); +// 结果:7 +``` + +参考统计函数功能拓展 MinValue MinIntValue MaxValue Min Max + +###### SumInt + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(2, 3, 1, 5, 6.5, 7.5); +return SumInt(a); +// 结果:24 +``` + +参考统计函数功能拓展 Sum + +###### Harmean + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组计算调和平均数 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Harmean(Data); +// 结果:5.44 +``` + +范例02:二维数组指定列+指定步长计算调和平均数 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-调和平均数"] := Harmean(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Mean StdDev Geomean Mode Median + +###### Variance + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求样本方差 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return Variance(a); +// 结果:2.13366666666666 +``` + +范例02:二维数组指定列+指定步长计算样本方差 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-样本方差"] := Variance(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 StdDev PopnStdDev PopnVariance + +###### MeanAndStdDev + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +// b是返回的平均值,c是返回的标准差 +MeanAndStdDev(a, b, c); +return array(b, c); +``` + +参考统计函数功能拓展 Mean StdDev + +###### AveDev + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +// 返回数组Data的平均绝对偏 +return AveDev(Data); +// 结果:2.2 +``` + +参考统计函数功能拓展 StdDev + +###### Skewness + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求偏度 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Skewness(Data); +// 结果:0.11 +``` + +范例02:二维数组指定列+指定步长计算偏度 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-偏度"] := Skewness(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 skewness2 Kurtosis kurtosis2 + +###### TotalVariance + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return TotalVariance(a); +// 结果:10.6683333333333 +``` + +参考统计函数功能拓展 Variance + +###### Product + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +一维数组计算累乘值 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Product(Data); +// 结果:259200 //返回5*3*6*8*9*10*4 +``` + +范例02:二维数组指定列+指定步长计算累乘值 + +```tsl +arr := rand(10, array("A", "B")) * 10; +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-累乘"] := Product(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Sum + +###### PopnStdDev + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求总体标准差 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return PopnStdDev(a); +// 结果:1.33343749593131 +``` + +范例02:二维数组指定列+指定步长计算总体标准差 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-总体标准差"] := PopnStdDev(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 StdDev Variance PopnVariance + +###### kurtosis2 + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01::一维数组计算峰度 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return kurtosis2(Data); +// 结果:1.57 +``` + +范例02:二维数组指定列+指定步长计算峰度 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-峰度"] := kurtosis2(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Skew skewness2 Kurtosis + +###### Median + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Median(Data); +// 结果:6 +``` + +参考统计函数功能拓展 Mean StdDev Geomean Harmean Mode + +###### skewness2 + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求偏度 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return skewness2(Data); +// 结果:0.09 +``` + +范例02:二维数组指定列+指定步长计算偏度 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-偏度"] := skewness2(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Skewness Kurtosis kurtosis2 + +###### 统计函数功能拓展 + +我们以前的统计函数,只支持对于一维数组的处理,现在一并支持了对二维数组的处理,对行列操作的选择,移动统计,选择部分字段做统计等功能。 + +比如func(In1,In2...InN[,Out1,...OutN]),这类函数,In参数除支持二维数组外,还增加了五个可选参数func(In1,In2...InN[,Out1,...OutN],Opt1[,Opt2[, +Opt3[, Opt4[, Opt5]]]]]) + +Opt1:对列操作为0(默认),对行操作为1,可缺省(以下参数都是默认缺省的参数); + +Opt2:是否移动进行计算,为0表示不移动(默认),其余正整数表示移动计算的长度; + +Opt3:对字段筛选,nil表示全选(默认),可以使用数组进行多选,也可以使用简单类型进行单选 + +Opt4:异常处理参数,按照存储位来进行管理(默认为0): + +第一位管理的是是否忽略异常值(不包括nil),即1不报错,0报错。 + +第二位管理的是nil值是否报错,即1报错,0不报错。 + +第三位管的是计算移动长度的时候,nil值及字符串等异常值是否包括在内。即0不忽略,1忽略。 + +这样的话,衍生出8种组合场景,分别对应如下: + +注:下列说明中移动时异常值包括nil值在内,而其它处异常值中不包括nil值在内。 + +| 二进制 | 十进制值 | 功能说明 | +| ------ | -------- | ------------------------------------------------- | +| 0b000 | 0 | 默认值,异常值报错,nil不报错,移动时异常值不忽略 | +| 0b001 | 1 | 异常值不报错,nil值不报错,移动时异常值不忽略 | +| 0b010 | 2 | 异常值与nil值报错,移动时异常值不忽略 | +| 0b011 | 3 | 异常值不报错,nil值报错,移动时异常值不忽略 | +| 0b100 | 4 | 异常值报错,nil值不报错,计算移动单位时忽略异常值 | +| 0b101 | 5 | 异常值与nil值不报错,计算移动单位时忽略异常值 | +| 0b110 | 6 | 异常值报错,nil值报错,计算移动单位时忽略异常值 | +| 0b111 | 7 | 异常值不报错,nil值报错,计算移动单位时忽略异常值 | + +Opt5:当In为空数组时的返回值,该参数默认缺省为0。 + +常用统计量:以mean函数为例: + +正常数据的处理: + +```tsl +a := array((1, 2, 3), (2, nil, 4), (4, 5, 6)); // 在一般的统计函数中,遇到nil是不会报错的 +return mean(a); // 对每一列求均值 +return mean(a, 1); // 对每一行求均值 +return mean(a, 0, 2); // 求取长度为2的移动平均 +return mean(a, 0, 2, array(0, 1)); // 只对0,1列做计算 +return mean(a, 0, 2, array(0, 1), 4); +// 比较和上一个返回,这里求移动均值时跳过了nil +``` + +含字符串异常数据 + +```tsl +a := array((1, 2, 3), (2, nil, "a"), (4, 5, 6)); +return mean(a, 0, 2, array(0, 1), 1); +// 忽略含字符串元素时候的报错 +return mean(a, 0, 2, array(0, 1), 1 + 4); +// 比较和上一个返回,这里求移动均值时跳过了nil和字符串元素 +``` + +空数组时候的默认输出: + +```tsl +return mean(array(), 0, 0, nil, 1, "默认输出值"); // 输出第6个参数 +``` + +一维数组的处理和n\*1二维数组类似,注意第二个参数一般为0,移动平均还是一维数组,一般平均结果是实数。 + +```tsl +a := rand(100); +return mean(a); // 结果为实数 +return mean(a, 0, 10); // 长度为10的移动平均 +``` + +次序统计量,以Large函数为例: + +相比较统计函数的用法,次序统计函数主要要注意的是第二个不可缺省的参数的设置问题,比如:Large(Data:Array;N:[Int,Array]):[real,Array]; + +N是一个整数的时候 + +```tsl +a := 1 - > 10; +a |= a; +return _large(a, 1); // 这样可以得到每列最大的元素 +``` + +N是一个一维数组的时候 + +```tsl +a := rand(100, 10); +return _large(a, 1 - > 10); // 对列做的时候,N的长度必须和列数目一致 +return _large(a, ones(100), 1); // 对行做的时候,N的长度必须和行数目一致 +``` + +###### Kurtosis + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组计算峰度 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Kurtosis(Data); +// 结果:-1.64 +``` + +结果:-1.64 + +范例02:二维数组指定列+指定步长计算峰度 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-峰度"] := Kurtosis(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Skewness skewness2 kurtosis2 + +###### Mode + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Mode(Data); +// 结果:3 +``` + +参考统计函数功能拓展 Mean StdDev Geomean Harmean Median + +###### RandG + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return RandG(2, 3); +// 结果:3.05 //3.05是均值为2,标准差为3的高斯分布的一个样本数据 +``` + +参考简单函数对数组支持 + +###### Geomean + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组计算几何平均数 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Geomean(Data); +// 结果:5.93 +``` + +范例02:二维数组指定列+指定步长计算几何平均数 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-几何平均数"] := Geomean(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 Mean StdDev Harmean Mode Median + +###### PopnVariance + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:一维数组求总体方差 + +```tsl +a := array(5.3, 3.9, 5.6, 5, 7.5, 7.6); +return PopnVariance(a); +// 结果:1.77805555555555 +``` + +范例02:二维数组指定列+指定步长计算总体方差 + +```tsl +arr := rand(10, array("A", "B")); +ml := length(arr); // 移动步长--指定大于等于总长度数,则统计从首行到当前行的区间 +arr[:, "A-总体方差"] := PopnVariance(arr, 0, ml, "A"); +return arr; +``` + +参考统计函数功能拓展 StdDev PopnStdDev Variance + +###### MomentSkewKurtosis + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +MomentSkewKurtosis(Data, M1, M2, M3, M4, Skew, Kurtosis); +return array(M1, M2, M3, M4, Skew, Kurtosis); +``` + +结果; + +参考统计函数功能拓展 + +###### DevSq + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return DevSq(Data); +// 结果:41.71 +``` + +参考统计函数功能拓展 StdDev + +###### randomfrom + +用途:一般统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return randomfrom(Data); +// 结果:9 +``` + +参考统计函数功能拓展 + +##### 次序统计量 + +###### 内容 + +- Large +- Small +- Percentile +- Percentrank +- Quartile +- Rank +- Trimmean +- Frequency + +###### Large + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +// 返回数组Data中第3大的数据 +return Large(Data, 3); +// 结果:8 +``` + +参考统计函数功能拓展 Small Percentile + +###### Small + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 返回数组Data中第3小的数据 +Data := array(5, 3, 6, 8, 9, 10, 4); +return Small(Data, 3); +// 结果:5 +``` + +参考统计函数功能拓展 Large Percentile + +###### Percentile + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +对序列从小到大排序,数据长度为n,则 + +(1) + +求(n-1)\* PCT,记整数部分为i,小数部分为j + +(2) + +所求结果=(1-j)*序列第(i+1)个数+j*序列第(i+2)个数 + +范例 + +范例1:序列百分点的值 + +```tsl +// 返回数组Data的第3个百分点 +Data := array(5, 3, 6, 8, 9, 10, 4); +return Percentile(Data, 0.3); +// 结果:4.8 +``` + +范例2:二维数组各列百分点的值 + +```tsl +a := array('A':('g':1, 'f':2, 'k':3), +'B':('g':10, 'f':20, 'k':30), +'C':('g':100, 'f':200, 'k':300), +'D':('g':1000, 'f':2000, 'k':3000), +); +return Percentile(a, 0.5, 0); +``` + +范例3:二维数组指定列指定步长的百分点的值 + +```tsl +a := array('A':('g':1, 'f':2, 'k':3), +'B':('g':10, 'f':20, 'k':30), +'C':('g':100, 'f':200, 'k':300), +'D':('g':1000, 'f':2000, 'k':3000), +); +return Percentile(a, 0.5, 0, 2, array('f', 'k')); +``` + +参考统计函数功能拓展 Large Small + +###### Percentrank + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 返回8在数组Data的百分点,即小于8的个数/(小于8个数+大于8个 +// 数)结果是4/6 +Data := array(5, 3, 6, 8, 9, 10, 4); +return Percentrank(Data, 8); +// 结果:0.666666666666667 +``` + +参考统计函数功能拓展 Large Small Percentile + +###### Quartile + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 返回数组Data中第3个四分位数,即75%。然后按照Percentile的算法求值 +// (7-1)*75%=4.5,i=4,j=5,最终结果是(1-0.5)*8+0.5*9=8.5 +Data := array(5, 3, 6, 8, 9, 10, 4); +return Quartile(Data, 3); +// 结果:8.5 +``` + +参考统计函数功能拓展 Large Small Percentile Percentrank + +###### Rank + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +return Rank(Data, 8); +// 结果:3 +``` + +参考统计函数功能拓展 Percentile Percentrank + +###### Trimmean + +用途:对字符串进行裁剪处理。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 去除个数=总个数7*0.7=4.9,头和尾各去除2个数据,剩下数据5,6,8求//均值 +Data := array(5, 3, 6, 8, 9, 10, 4); +return Trimmean(Data, 0.7); +// 结果:6.33333333333333 +``` + +参考统计函数功能拓展 + +###### Frequency + +用途:次序统计量相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Data := array(5, 3, 6, 8, 9, 10, 4); +FreqData := array(1, 2, 3); +return Frequency(Data, FreqData); +``` + +参考统计函数功能拓展 + +##### 统计函数 + +###### 内容 + +- Cov +- Correl +- Slope +- Intercept +- Rsq +- Steyx +- Slopeandintercept +- VariationCoefficient +- Skew +- SelfStddev +- RegressionChannel +- Kurt +- MeanAndPopnStdDevWithRate +- BetaAndAlpha +- 扩充统计 +- 含NAN统计 +- correlpaired +- correlpaired_side + +###### Cov + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +备注:数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘的协方差 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Cov(data[:, "价格"], data[:, "大盘"]); +``` + +###### Correl + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法ra,b=cov(a,b)σaσb,其中cov(a,b)为a,b序列协方差,σ为总体标准差。 + +备注:数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘价格的相关系数 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Correl(data[:, "价格"], data[:, "大盘"]); +``` + +###### Slope + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 or + +备注:数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘收盘价格的回归斜率 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Slope(data[:, "价格"], data[:, "大盘"]); +``` + +###### Intercept + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +备注:数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘收盘价的相回归截距 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Intercept(data[:, "价格"], data[:, "大盘"]); +``` + +###### Rsq + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +备注:参数数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘的乘积矩相关系数平方 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Rsq(data[:, "价格"], data[:, "大盘"]); +``` + +###### Steyx + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +备注:数据长度必须保持长度一致且大于2。范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘的相对标准偏差 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Steyx(data[:, "价格"], data[:, "大盘"]); +``` + +###### Slopeandintercept + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +备注:参数数据长度必须保持一致且大于等于2范例 + +万科A在2018/10/1~2018/10/30日线收盘与大盘收盘价格的回归斜率和截距 + +```tsl +begt := 20181001T; +Endt := 20181030T; +Setsysparam(Pn_Stock(), "SZ000002"); +dateArr := markettradedayQK(begt, Endt); +data := select thisrow as"日期", +Spec(Specdate(close(), thisrow), "SZ000002") as"价格", +SPec(Specdate(Close(), thisrow), "SH000001") as"大盘" +from dateArr +end; +return Slopeandintercept(data[:, "价格"], data[:, "大盘"]); +``` + +###### VariationCoefficient + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法C.V.=σ/μ,其中σ为标准差,μ为均值。范例 + +```tsl +return VariationCoefficient(array(1, 2, 1, 2, 1, 2)); +// 返回:0.33 +``` + +###### Skew + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法sc=1n(ti-μσ)3\*nn-1(n-2),其中n为序列长度,其中σ为标准差,μ为均值。范例 + +```tsl +Skew(array(1, 2, 3, 4, 5, 7), s); +return s; +// 返回:0.46 +``` + +###### SelfStddev + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +t2=t-Rmar,并将t2中大于0的元素化为0。 + +对t2求标准差范例 + +```tsl +return SelfStddev(array(1, 2, 3, 4, 5), 3); +// 返回:0.89 +``` + +###### RegressionChannel + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法返回BETA系数以及ALPHA值,并得到上行轨道以及下行轨道的ALPHA。依此得到指定X的上轨以及下轨,并根据当前的Y得到其所在轨道中的百分比,如果<0则低于下轨,>100则超越上轨。依照Alpha和Beta值,得到nowx的预期回归运行值。范例 + +```tsl +RegressionChannel(array(1, 2, 3, 4, 5), array(6, 7, 8, 9, 10), 1, 2, 3, 4, 5, 6, 7, 8, s, a); +return a; +// 返回:-3 +``` + +###### Kurt + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +其中n为序列长度,其中Stdev为标准差。范例 + +```tsl +Kurt(array(1, 2, 3, 4, 5), s); +return s; +// 返回:-1.2 +``` + +###### MeanAndPopnStdDevWithRate + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +算法 + +μ=1nRi\*Di1nRi + +σ=1nRi*inRi*Di2-(1nRi\*Di)21nRi + +其中μ为均值,σ为标准差范例 + +```tsl +MeanAndPopnStdDevWithRate(array(1, 2, 3), array(1, 1, 1), m, s); +return m; +// 返回:2 +``` + +###### BetaAndAlpha + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +BetaAndAlpha(array(3, 6), array(4, 12), k, b); +return k; +// 返回:0.375 +``` + +###### 扩充统计 + +####### 内容 + +- Expanding_Unit + +####### Expanding_Unit + +功能描述: + +扩充统计单元库,扩充统计方法,提高运算效率,譬如cumsum + +输 入: + +r 必须为数字数组,当为空数组时,返回空数组 + +支持一维数组或二维数组(此时按列统计),也可以为二维数据表 + +######## 内容 + +- ExpdMax +- ExpdMin +- ExpdSum +- ExpdProduct +- ExpdVar +- ExpdStd + +######## ExpdMax + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdMax(r); // array(-1,2,2,9) +``` + +######## ExpdMin + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdMin (r); // array(-1,-1,-3,-3) +``` + +######## ExpdSum + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdSum (r); // array(-1,1,-2,7) +``` + +######## ExpdProduct + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdProduct (r); // array(-1,-2,6,54) +``` + +######## ExpdVar + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdVar (r, 0); // array(0,2.25,4.22,20.69) +``` + +######## ExpdStd + +范例 + +```tsl +r := array(-1, 2, -3, 9); +return ExpdStd (r, 0); // array(0,1.5,2.05,4.55) +``` + +###### 含NAN统计 + +####### 内容 + +- NanMean +- NanSum +- NanStd +- NanVariance +- NanPopnStd +- NanPopnVariance +- NanRankArr +- NanPercentRankArr + +####### NanMean + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return NanMean(A); +// 结果:6.33 +``` + +####### NanSum + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return NanSum(A); +// 结果:19 +``` + +####### NanStd + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return NanStd(A); +// 结果:1.53 +``` + +####### NanVariance + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return NanVariance(A); +// 结果:2.33 +``` + +####### NanPopnStd + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return NanPopnStd(A); +// 结果:1.25 +``` + +####### NanPopnVariance + +范例 + +```tsl +A := array(5, 6, 8, Nan); +return PopnVariance(A); +// 结果:1.56 +``` + +####### NanRankArr + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(1, 1, 2, 2, 2, 9, Nan, 9, 9); +return NanRankArr(a); +// 结果:array(1,1,3,3,3,6,NAN,6,6) +``` + +####### NanPercentRankArr + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := array(1, 1, 2, 2, 2, 9, Nan, 9, 9); +return NanPercentRankArr(a); +// 结果:array(0.0,0.0,0.29,0.29,0.29,0.71,NAN,0.71,0.71) +``` + +###### correlpaired + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01 + +```tsl +a := rand(10); +b := rand(10); +return correlpaired(a, b); // array((0.17)) +``` + +范例02 + +```tsl +a := rand(10); +b := rand(10, 2); +return correlpaired(a, b); // array((-0.35,-0.19)) +``` + +范例03 + +```tsl +a := rand(10, 2); +b := rand(10, 4); +return correlpaired(a, b); +``` + +返回: + +范例04 + +```tsl +a := `array("A":rand(10)); +b := `array("A":rand(10), "B":rand(10)); +return correlpaired(a, b); // array((0.2,-0.08)) +``` + +###### correlpaired_side + +用途:统计函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := randnorm(0, 1, 20, array(0, 1, 2, 3, 4)); +dirType := 3; +return correlpaired_side(a, filtType); +``` + +##### 统计分布 + +###### 内容 + +- Gammaln +- Hist +- sf_Error +- erfc +- sf_Gamma +- erf +- erfcinv +- sf_Beta +- sf_IntegerBessel_1 +- sf_IncompleteGamma +- Gamma +- erfinv +- 分布函数 +- Randnorm +- sf_F +- sf_geopdf +- sf_RealBessel_1 +- sf_unidcdf +- sf_normpdf +- sf_geoinv +- sf_unidpdf +- sf_IncompleteBeta +- sf_normalinv2 +- sf_norminv +- Randunid +- sf_Normal +- sf_unidinv +- sf_X2 +- sf_IntegerBessel_2 +- sf_normcdf +- sf_t +- sf_geocdf +- Randgeo +- sf_normalinv +- Normfit +- sf_RealBessel_2 +- sf_hygeinv +- poissfit +- sf_binocdf +- Randhyge +- sf_poissinv +- sf_poisscdf +- sf_nbininv +- binofit +- sf_hygepdf +- sf_unifcdf +- sf_exppdf +- sf_binoinv +- uniffit +- sf_nbinpdf +- Randnbin +- Randpoiss +- sf_hygecdf +- sf_poisspdf +- Randbino +- Randunif +- sf_unifinv +- sf_binopdf +- sf_nbincdf +- sf_unifpdf +- sf_tcdf +- sf_fpdf +- sf_tinv +- expfit +- Randgam +- sf_ch2inv +- sf_ch2cdf +- sf_finv1 +- Randt +- sf_expcdf +- sf_finv +- sf_gamcdf +- sf_tpdf +- sf_x2inv +- sf_gampdf +- sf_gammainv +- sf_fcdf +- sf_ch2pdf +- Randf +- Randexp +- Randch2 +- sf_gaminv +- sf_expinv +- sf_betapdf +- sf_tinv1 +- RandCauchy +- sf_Laplacecdf +- Randbeta +- sf_Cauchypdf +- sf_logninv +- sf_Laplaceinv +- sf_betacdf +- sf_raylinv +- sf_wblcdf +- sf_lognpdf +- sf_Cauchycdf +- Randlogn +- Randrayl +- sf_Laplacepdf +- sf_raylpdf +- sf_wblinv +- sf_logncdf +- sf_Cauchyinv +- sf_raylcdf +- Randwbl +- sf_betainv +- RandLaplace +- sf_wblpdf +- sf_betainv1 +- sf_mvtcdf +- Mvtcdfqmc +- sf_mvncdf +- sf_copulacdf +- sf_copulafit +- RandCopula +- sf_exp +- Norminv + +###### Gammaln + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Gammaln(array(1.5, 2.3, 3.4)); +// 结果:array(-0.120782237635245,0.15418945495963,1.09232805980274) +``` + +###### Hist + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := randnorm(0, 1, 10000); +return Hist(A, 30, center); +``` + +结果,一维数字数组 + +###### sf_Error + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_Error(0.15, v); +return v; +// 结果:0.168 +``` + +###### erfc + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return erfc(0.15); +// 0.832004028572637 +``` + +###### sf_Gamma + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_Gamma(5, v); +return v; +// 结果:24 +``` + +参考sf_IncompleteGamma + +###### erf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return erf(0.15); +// 结果:0.168 +``` + +###### erfcinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return erfcinv(0.15); +// 结果:1.01790246483203 +``` + +###### sf_Beta + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_Beta(2, 5, v); +return v; +// 结果:0.03333 +``` + +参考sf_Gamma + +###### sf_IntegerBessel_1 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +n := 7; +x := 4.5; +sf_IntegerBessel_1(n, x, v); +return v; +// 结果:0.03002 +``` + +参考sf_IntegerBessel_2 sf_RealBessel_1 sf_RealBessel_2 + +###### sf_IncompleteGamma + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 5; +x := 7; +sf_IncompleteGamma(a, x, v); +return v; +// 结果:0.82701 +``` + +参考sf_Gamma + +###### Gamma + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Gamma(array(1.5, 2.3, 3.4)); +// 结果:array(0.886226925452758,1.16671190519816,2.98120642681033) +``` + +###### erfinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return erfinv(0.15); +// 结果:0.13372692166482 +``` + +###### 分布函数 + +TinySoft金融分析平台上提供了有关统计分布的函数:概率密度,(累计)分布函数,分位数函数(分布逆函数),随机数函数,估计函数 + +概率密度,(累计)分布函数,分位数的函数命名使用规则: + +概率分布函数(包括概率密度函数,分布函数,分布逆函数)输入的第一个变量参数是随机变量或分布函数值,都支持数组形式,中间的参数,一般为分布参数,参数个数不定,只支持符合要求的实数和整数类型.最后一个参数存在的主要原因是为了支持tinysoft金融分析平台以前的使用方法,该参数可缺省,而使用return输出结果,输出结果和第一个参数的维度是一样的. + +随机数函数命名使用规则: + +生成随机数的函数名称一般使用rand+分布类型(分布参数+行数目+列数目),如: + +return randrayl(5,array('a','b','c')); + +return randrayl(5,array('a','b','c','d','e','f'),4); + +return randrayl(5,4,array('a')); + +或使用rand函数: + +A:=rand(100,100,array("normal")); //标准正态分布 + +a := rand(100,100,array("normal",0,1));//标准正态分布 + +支持如下类型(大小写无关):正态分布"normal",泊松分布"posisson",伽马分布"Gamma",均匀分布"Uniform",二项分布"Binomial",几何分布"Geometric",指数分布"Exp",beta分布"Beta",对数正态分布"Lognormal",威布尔分布"Weibull",柯西"Cauchy",拉普拉斯"Laplace",超几何"Hypergeometric",离散均匀"IntUniform",瑞利分布"Rayleigh" + +估计函数命名使用规则: + +估计函数的函数名称一般使用分布类型+fit(数据+显著性水平)如 + +return normfit(rand(1000,5),0.05); + +结果以列为样本进行估计,muhat,muci为正态分布位置参数的点估计,区间估计,sigmahat,sigmaci为正态分布形态参数的点估计,区间估计.其中每一个样本区间的区间估计中含有两个值,upper是上限,lower是下限. + +函数列表: + +| | 概率密度 | 分布函数 | 分布逆函数 | 随机数 | 估计函数 | +| ------------ | -------------- | -------------- | -------------- | ----------- | -------- | +| 离散均匀分布 | sf_unidpdf | sf_unidcdf | sf_unidinv | randunid | | +| 几何分布 | sf_geopdf | sf_geocdf | sf_geoinv | Randgeo | | +| 超几何分布 | sf_hygepdf | sf_hygecdf | sf_hygeinv | Randhyge | | +| 二项分布 | sf_binopdf | sf_binocdf | sf_binoinv | Randbino | binofit | +| 负二项分布 | sf_nbinpdf | sf_nbincdf | sf_nbininv | Randnbin | | +| 均匀分布 | sf_unifpdf | sf_unifcdf | sf_unifinv | Randunif | uniffit | +| 泊松分布 | sf_poissonpdf | sf_poissoncdf | sf_poissoninv | Randpoisson | poissfit | +| 指数分布 | sf_exppdf | sf_expcdf | sf_expinv | Randexp | expfit | +| 正态分布 | sf_normpdf | sf_normcdf | sf_norminv | Randnorm | | +| 卡方分布 | sf_ch2pdf | sf_ch2cdf | sf_ch2inv | Randch2 | | +| 学生T分布 | sf_tpdf | sf_tcdf | sf_tinv1 | Randt | | +| F分布 | sf_fpdf | sf_fcdf | sf_finv1 | Randf | | +| gam分布 | sf_gampdf | sf_gamcdf | sf_gaminv | Randgam | | +| beta分布 | sf_betapdf | sf_betacdf | sf_betainv1 | Randbeta | | +| 瑞利分布 | sf_raylpdf | sf_raylcdf | sf_raylinv1 | Randrayl | | +| 威布尔分布 | sf_wblpdf | sf_wblcdf | sf_wblinv | Randwbl | | +| 对数正态分布 | sf_lognpdf | sf_logncdf | sf_logninv | Randlohn | | +| 拉普拉斯分布 | sf_Laplacepdf | sf_Laplacecdf | sf_Laplaceinv | RandLaplace | | +| 柯西分布 | sf\_ Cauchypdf | sf\_ Cauchycdf | sf\_ Cauchyinv | RandCauchy | | + +###### Randnorm + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randnorm(0, 1, 10, array("a", "b")); +``` + +参考分布函数 sf_normpdf sf_normcdf sf_norminv Normfit + +###### sf_F + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +f := 2; +n1 := 3; +n2 := 5; +sf_F(f, n1, n2, v); +return v; +// 结果:0.76738 +``` + +参考sf_Normal sf_t sf_X2 + +###### sf_geopdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_geopdf(x, 0.5); +``` + +参考sf_geocdf sf_geoinv Randgeo 分布函数 + +###### sf_RealBessel_1 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +n := 7; +x := 4.5; +sf_RealBessel_1(n, x, v); +return v; +// 结果:0.10684 +``` + +参考sf_IntegerBessel_1 sf_IntegerBessel_2 sf_RealBessel_2 + +###### sf_unidcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-4, 0.1) - > 4; +return sf_unidcdf(x, 0, 1); +``` + +参考sf_unidpdf sf_unidcdf sf_unidinv Randunid 分布函数 + +###### sf_normpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-2, 0.1) - > 2; +return sf_normpdf(x, 0, 1); +``` + +参考分布函数 sf_normcdf sf_norminv Randnorm Normfit + +###### sf_geoinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_geoinv(y, 0.5); +``` + +参考sf_geopdf sf_geocdf Randgeo 分布函数 + +###### sf_unidpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_unidpdf(x, 10); +``` + +参考sf_unidpdf sf_unidcdf sf_unidinv Randunid 分布函数 + +###### sf_IncompleteBeta + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := 3; +b := 4; +x := 0.25; +sf_IncompleteBeta(a, b, x, v); +return v; +// 结果:0.16943 +``` + +参考sf_Beta + +###### sf_normalinv2 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_normalinv2(0.5 , v); +return v; // 返回结果0. +``` + +###### sf_norminv + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_norminv(y, 0, 1); +``` + +参考分布函数 sf_normpdf sf_normcdf Randnorm Normfit + +###### Randunid + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randunid(10, 10, array("a", "b")); +``` + +参考sf_unidpdf sf_unidcdf sf_unidinv 分布函数 + +###### sf_Normal + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 0; +a := 0; +d := 1; +sf_Normal(x, a, d, v); +return v; +// 结果:0.5 +``` + +参考sf_t sf_X2 sf_F + +###### sf_unidinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_unidinv(y, 10); +``` + +参考sf_unidpdf sf_unidcdf sf_unidinv Randunid 分布函数 + +###### sf_X2 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 2.5; +n := 10; +sf_X2(x, n, v); +return v; +// 结果:0.00912 +``` + +参考sf_Normal sf_t sf_F + +###### sf_IntegerBessel_2 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +n := 7; +x := 4.5; +sf_IntegerBessel_2(n, x, v); +return v; +// 结果: +-2.02943 +``` + +参考sf_IntegerBessel_1 sf_RealBessel_1 sf_RealBessel_2 + +###### sf_normcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +标准正态分布的概率密度函数为: + +pt=12πe-t22 t∈(-∞,+∞) + +则随机变量x对应分布函数(x): + +(x)=12π-∞xe-t22dt + +定义函数erfx=2π0xe-t2dt(x>0)为误差函数; + +函数erfcx=1-erfx=2πx+∞e-t2dt为余误差函数。 + +则分布函数x与余误差函数有以下关系: + +x=0.5\*erfc(-x2) + +设随机变量服从均值为mu,标准差为sigma的正态分布Nmu,sigma,经过标准化 + +z=x-musigma + +后服从标准正态分布N0,1。 + +变量z对应的分布函数值为: + +z=0.5\*erfc(-z2)范例 + +```tsl +x := array(-4, 0.1) - > 4; +return sf_normcdf(x, 0, 1); +``` + +参考分布函数 sf_normpdf sf_norminv Randnorm Normfit + +###### sf_t + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +t := 2.5; +n := 10; +sf_t(t, n, v); +return v; +// 结果:0.98428 +``` + +参考sf_Normal sf_X2 sf_F + +###### sf_geocdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_geocdf(x, 0.5); +``` + +参考sf_geopdf sf_geoinv Randgeo 分布函数 + +###### Randgeo + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randgeo(10, 10, array("a", "b")); +``` + +参考sf_geopdf sf_geocdf sf_geoinv 分布函数 + +###### sf_normalinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_normalinv(0.5, 0, 1, v); +return v; // 返回结果0. +``` + +###### Normfit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := randnorm(0, 1, 10, array("a", "b")); +return Normfit(x, 0.05); +``` + +结果:返回mu,sigma的估计以及他们的在alpha的显著性水平下的区间估计 + +###### sf_RealBessel_2 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +n := 7; +x := 4.5; +sf_RealBessel_2(n, x, v); +return v; +// 结果:0.56161 +``` + +参考sf_IntegerBessel_1 sf_IntegerBessel_2 sf_RealBessel_1 + +###### sf_hygeinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_hygeinv(y, 100, 10, 20); +``` + +参考sf_hygepdf sf_hygecdf Randhyge 分布函数 + +###### poissfit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := randpoiss(1, 100); +return poissfit(x, 0.05); +``` + +结果:返回lambda的估计以及他们的在alpha的显著性水平下的区间估计 + +参考sf_poisspdf sf_poisscdf sf_poissinv Randpoiss 分布函数 + +###### sf_binocdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_binocdf(x, 10, 0.5); +``` + +参考sf_binopdf sf_binoinv Randbino binofit 分布函数 + +###### Randhyge + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randhyge(100, 10, 20, 10, array("a", "b")); +``` + +参考sf_hygepdf sf_hygecdf sf_hygeinv 分布函数 + +###### sf_poissinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_poissinv(y, 10); +``` + +参考sf_poisspdf sf_poisscdf Randpoiss poissfit 分布函数 + +###### sf_poisscdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 20; +return sf_poisscdf(x, 10); +``` + +参考sf_poisspdf sf_poissinv Randpoiss poissfit 分布函数 + +###### sf_nbininv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_nbininv(y, 10, 0.5); +``` + +参考sf_nbinpdf sf_nbincdf Randnbin 分布函数 + +###### binofit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := randbino(10, 0.5, 1); +return binofit(x, 10, 0.05); +``` + +结果:返回p的估计以及在alpha的显著性水平下的区间估计 + +参考sf_binopdf sf_binocdf sf_binoinv Randbino 分布函数 + +###### sf_hygepdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 20; +return sf_hygepdf(x, 100, 10, 20); +``` + +参考sf_hygecdf sf_hygeinv Randhyge 分布函数 + +###### sf_unifcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_unifcdf(x, 1, 10); +``` + +参考sf_unifpdf Randunif uniffit 分布函数 + +###### sf_exppdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 4.5; +return sf_exppdf(x, 1); +``` + +参考sf_expcdf sf_expinv Randexp expfit 分布函数 + +###### sf_binoinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_binoinv(y, 10, 0.5); +``` + +参考sf_binopdf sf_binocdf Randbino binofit 分布函数 + +###### uniffit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := randunif(1, 10, 100); +return uniffit(x, 0.05); +``` + +结果:返回a,b的估计以及他们的在alpha的显著性水平下的区间估计 + +参考sf_unifpdf sf_unifcdf sf_unifinv Randunif 分布函数 + +###### sf_nbinpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 20; +return sf_nbinpdf(x, 10, 0.5); +``` + +参考sf_nbincdf sf_nbininv Randnbin 分布函数 + +###### Randnbin + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randnbin(10, 0.5, 10, array("a", "b")); +``` + +参考sf_nbinpdf sf_nbincdf sf_nbininv 分布函数 + +###### Randpoiss + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randpoiss(10, 10, array("a", "b")); +``` + +参考sf_poisspdf sf_poisscdf sf_poissinv poissfit 分布函数 + +###### sf_hygecdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_hygecdf(x, 100, 10, 20); +``` + +参考sf_hygepdf sf_hygeinv Randhyge 分布函数 + +###### sf_poisspdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 20; +return sf_poisspdf(x, 10); +``` + +参考sf_poisscdf sf_poissinv Randpoiss poissfit 分布函数 + +###### Randbino + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randbino(10, 0.5, 10, array("a", "b")); +``` + +参考sf_binopdf sf_binocdf sf_binoinv binofit 分布函数 + +###### Randunif + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randunif(1, 10, 10, array("a", "b")); +``` + +参考sf_unifpdf sf_unifcdf sf_unifinv uniffit 分布函数 + +###### sf_unifinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_unifinv(y, 1, 10); +``` + +参考sf_unifpdf sf_unifcdf Randunif uniffit 分布函数 + +###### sf_binopdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 20; +return sf_binopdf(x, 10, 0.5); +``` + +参考sf_binocdf sf_binoinv Randbino binofit 分布函数 + +###### sf_nbincdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_nbincdf(x, 10, 0.5); +``` + +参考sf_nbinpdf sf_nbininv Randnbin 分布函数 + +###### sf_unifpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 1 - > 10; +return sf_unifpdf(x, 1, 10); +``` + +参考sf_unifcdf Randunif uniffit 分布函数 + +###### sf_tcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-2.5, 0.1) - > 2.5; +return sf_tcdf(x, 30); +``` + +参考sf_tpdf sf_tinv1 Randt 分布函数 + +###### sf_fpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 3; +return sf_fpdf(x, 20, 30); +``` + +参考sf_fcdf sf_finv1 Randf 分布函数 + +###### sf_tinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_tinv(0.6, 30, v); +return v; // 返回结果0.255605364951908 +``` + +###### expfit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := randexp(1, 100); +return expfit(x, 0.05); +``` + +结果:返回parm的估计已经他们的在alpha的显著性水平下的区间估计 + +参考sf_exppdf sf_expcdf sf_expinv Randexp 分布函数 + +###### Randgam + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randgam(2, 2, 100, array("a", "b")); +``` + +参考sf_gampdf sf_gamcdf sf_gaminv 分布函数 + +###### sf_ch2inv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_ch2inv(y, 30); +``` + +参考sf_ch2pdf sf_ch2cdf Randch2 分布函数 + +###### sf_ch2cdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 0 - > 50; +return sf_ch2cdf(x, 30); +``` + +参考sf_ch2pdf sf_ch2inv Randch2 分布函数 + +###### sf_finv1 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_finv1(y, 20, 30); +``` + +参考sf_fpdf sf_fcdf Randf 分布函数 + +###### Randt + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randt(30, 10, array("a", "b")); +``` + +参考sf_tpdf sf_tcdf sf_tinv1 分布函数 + +###### sf_expcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 4.5; +return sf_expcdf(x, 1); +``` + +参考sf_exppdf sf_expinv Randexp expfit 分布函数 + +###### sf_finv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_finv(0.6, 20, 30, v); +return v; // 返回结果1.09737928787751 +``` + +###### sf_gamcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 13; +return sf_gamcdf(x, 2, 2); +``` + +参考sf_gampdf sf_gaminv Randgam 分布函数 + +###### sf_tpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-2.5, 0.1) - > 2.5; +return sf_tpdf(x, 30); +``` + +参考sf_tcdf sf_tinv1 Randt 分布函数 + +###### sf_x2inv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_x2inv(0.6, 30, v); +return v; // 返回结果31.3158632360391 +``` + +###### sf_gampdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 13; +return sf_gampdf(x, 2, 2); +``` + +参考sf_gamcdf sf_gaminv Randgam 分布函数 + +###### sf_gammainv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sf_gammainv(0.068094, 9, v); +return v; // 返回结果 5.000005596 +``` + +###### sf_fcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 3; +return sf_fcdf(x, 20, 30); +``` + +参考sf_fpdf sf_finv1 Randf 分布函数 + +###### sf_ch2pdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := 0 - > 50; +return sf_ch2pdf(x, 30); +``` + +参考sf_ch2cdf sf_ch2inv Randch2 分布函数 + +###### Randf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randf(20, 30, 10, array("a", "b")); +``` + +参考sf_fpdf sf_fcdf sf_finv1 分布函数 + +###### Randexp + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randexp(1, 10, array("a", "b")); +``` + +参考sf_exppdf sf_expcdf sf_expinv expfit 分布函数 + +###### Randch2 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randch2(30, 10, array("a", "b")); +``` + +参考sf_ch2pdf sf_ch2cdf sf_ch2inv 分布函数 + +###### sf_gaminv + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_gaminv(y, 2, 2); +``` + +参考sf_gampdf sf_gamcdf Randgam 分布函数 + +###### sf_expinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_expinv(y, 1); +``` + +参考sf_exppdf sf_expcdf Randexp expfit 分布函数 + +###### sf_betapdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.01) - > 1; +return sf_betapdf(x, 2, 4); +``` + +参考sf_betacdf sf_betainv Randbeta 分布函数 + +###### sf_tinv1 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_tinv1(y, 30); +``` + +参考sf_tpdf sf_tcdf Randt 分布函数 + +###### RandCauchy + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return RandCauchy(0, 2, 10, array("a", "b")); +``` + +参考sf_Cauchypdf sf_Cauchycdf sf_Cauchyinv 分布函数 + +###### sf_Laplacecdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-8, 0.1) - > 8; +return sf_Laplacecdf(x, 0, 2); +``` + +参考sf_Laplacepdf sf_Laplaceinv RandLaplace 分布函数 + +###### Randbeta + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randbeta(2, 4, 100, array("a", "b")); +``` + +参考sf_betapdf sf_betacdf sf_betainv 分布函数 + +###### sf_Cauchypdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-60, 1) - > 60; +return sf_Cauchypdf(x, 0, 2); +``` + +参考sf_Cauchycdf sf_Cauchyinv RandCauchy 分布函数 + +###### sf_logninv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_logninv(y, 0, 1); +``` + +参考sf_lognpdf sf_logncdf Randlogn 分布函数 + +###### sf_Laplaceinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_Laplaceinv(y, 0, 2); +``` + +参考sf_Laplacepdf sf_Laplacecdf RandLaplace 分布函数 + +###### sf_betacdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.01) - > 1; +return sf_betacdf(x, 2, 4); +``` + +参考sf_betapdf sf_betainv Randbeta 分布函数 + +###### sf_raylinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_raylinv(y, 1); +``` + +参考sf_raylpdf sf_raylcdf Randrayl 分布函数 + +###### sf_wblcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.05) - > 3; +return sf_wblcdf(x, 1, 1.5); +``` + +参考sf_wblpdf sf_wblinv Randwbl 分布函数 + +###### sf_lognpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 5; +return sf_lognpdf(x, 0, 1); +``` + +参考sf_logncdf sf_logninv Randlogn 分布函数 + +###### sf_Cauchycdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-60, 1) - > 60; +return sf_Cauchycdf(x, 0, 2); +``` + +参考sf_Cauchypdf sf_Cauchyinv RandCauchy 分布函数 + +###### Randlogn + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randlogn(0, 1, 10, array("a", "b")); +``` + +参考sf_lognpdf sf_logncdf sf_logninv 分布函数 + +###### Randrayl + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randrayl(1, 100, array("a", "b")); +``` + +参考sf_raylpdf sf_raylcdf sf_raylinv 分布函数 + +###### sf_Laplacepdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(-8, 0.1) - > 8; +return sf_Laplacepdf(x, 0, 2); +``` + +参考sf_Laplacecdf sf_Laplaceinv RandLaplace 分布函数 + +###### sf_raylpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.05) - > 9; +return sf_raylpdf(x, 1); +``` + +参考sf_raylcdf sf_raylinv Randrayl 分布函数 + +###### sf_wblinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_wblinv(y, 1, 1.5); +``` + +参考sf_wblpdf sf_wblcdf Randwbl 分布函数 + +###### sf_logncdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.1) - > 5; +return sf_logncdf(x, 0, 1); +``` + +参考sf_lognpdf sf_logninv Randlogn 分布函数 + +###### sf_Cauchyinv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_Cauchyinv(y, 0, 2); +``` + +参考sf_Cauchypdf sf_Cauchycdf RandCauchy 分布函数 + +###### sf_raylcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.05) - > 3; +return sf_raylcdf(x, 1); +``` + +参考sf_raylpdf sf_raylinv Randrayl 分布函数 + +###### Randwbl + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Randwbl(1, 1.5, 100, array("a", "b")); +``` + +参考sf_wblpdf sf_wblcdf sf_wblinv 分布函数 + +###### sf_betainv + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +r := sf_betainv(y, 2, 4, x); +return x; +``` + +参考sf_betapdf sf_betacdf Randbeta 分布函数 + +###### RandLaplace + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return RandLaplace(0, 2, 10, array("a", "b")); +``` + +参考sf_Laplacepdf sf_Laplacecdf sf_Laplaceinv 分布函数 + +###### sf_wblpdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(0, 0.05) - > 3; +return sf_wblpdf(x, 1, 1.5); +``` + +参考sf_wblcdf sf_wblinv Randwbl 分布函数 + +###### sf_betainv1 + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +return sf_betainv1(y, 2, 4); +``` + +参考sf_betapdf sf_betacdf Randbeta 分布函数 + +###### sf_mvtcdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +Rho := array( +(1.0000, 0.9264, 0.0406), +(0.9264, 1.0000, 0.0613), +(0.0406, 0.0613, 1.0000) +); +u := Randunif(0, 1, 300, 3); +return sf_mvtcdf(nil, u, rho, 2); +``` + +范例02: + +```tsl +return sf_mvtcdf(zeros(length(u), 3), u, rho, 2); +``` + +###### Mvtcdfqmc + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +Rho := array( +(1, 0.923912552224476, 0.035770327030089), +(0.923912552224476, 1, 0.084276570941762), +(0.035770327030089, 0.084276570941762, 1) +); +return Mvtcdfqmc(array(0, 0, 0), rand(3), rho, 2, array()); +``` + +###### sf_mvncdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +Rho := array( +(1.0000, 0.9264, 0.0406), +(0.9264, 1.0000, 0.0613), +(0.0406, 0.0613, 1.0000) +); +u := Randunif(0, 1, 300, 3); +return sf_mvncdf(nil, u, nil, rho); +``` + +范例02: + +```tsl +return sf_mvncdf(zeros(length(u), 3), u, zeros(1, 3), rho); +``` + +###### sf_copulacdf + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:gaussian分布 + +```tsl +u := Randunif(0, 1, 300, 3); +Rho := array( +(1.0000, 0.9239, 0.0358), +(0.9239, 1.0000, 0.0843), +(0.0358, 0.0843, 1.0000) +); +return sf_copulacdf(u, "gaussian", rho); +``` + +范例02:t分布 + +```tsl +u := Randunif(0, 1, 300, 3); +Rho := array( +(1, 0.923912552224476, 0.035770327030089), +(0.923912552224476, 1, 0.084276570941762), +(0.035770327030089, 0.084276570941762, 1) +); +return sf_copulacdf(u, "t", rho, 2); +``` + +范例03:阿基米德族,clayton(frank、gumbel调用相同) + +```tsl +u := Randunif(0, 1, 300, 2); +return sf_copulacdf(u, "clayton", nil, 1); +``` + +###### sf_copulafit + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:gaussian分布 + +```tsl +// 返回数组,相关系数矩阵 +u := Randunif(0, 1, 300, 3); +return sf_copulafit(u, "gaussian", "AML"); +``` + +范例02:t分布 + +```tsl +// 返回数组,相关系数矩阵以及自由度 +u := Randunif(0, 1, 300, 2); +return sf_copulafit(u, "t", "AML"); +``` + +范例03:阿基米德族,clayton(frank、gumbel调用相同) + +```tsl +// 返回实数,参数估计值 +u := Randunif(0, 1, 300, 2); +return sf_copulafit(u[:, 0:1], "clayton"); +``` + +###### RandCopula + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:gaussian分布 + +```tsl +Rho := array( +(1.0000, 0.9239, 0.0358), +(0.9239, 1.0000, 0.0843), +(0.0358, 0.0843, 1.0000) +); +n := 10; +v := array((0, 0, 0), (0, 0, 0), (0, 0, 0)); +return RandCopula("gaussian", rho, v, n); +``` + +范例02:t分布 + +```tsl +Rho := array( +(1.0000, 0.9239, 0.0358), +(0.9239, 1.0000, 0.0843), +(0.0358, 0.0843, 1.0000) +); +n := 10; +return RandCopula("t", rho, 3, n); +``` + +范例03:阿基米德族,clayton(frank、gumbel调用相同) + +```tsl +alpha := 1; +n := 10; +return RandCopula("clayton", nil, alpha, n); +``` + +###### sf_exp + +用途:统计分布相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.01, 0.01) - > 0.99; +sf_exp(y, 3, v); +return v; +``` + +###### Norminv + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Norminv(0.15, 0.5, 1); // -0.5364 +``` + +##### 统计推断 + +###### 内容 + +- Estimate_SNU +- Estimate_TNU +- Estimate\_ SND +- Estimate_TND +- Estimate_SP +- Estimate_TP +- Hypoth_TailRes +- NormPlot +- Hypoth_Kstest +- Hypoth_lillietest +- Hypoth_IndepTest +- Hypoth_KruskalWallis +- Hypoth_SNUTest +- Hypoth_TNUTest +- Hypoth_SNDTest +- Hypoth_TNDTest +- Hypoth_LSUTest +- Anova_Single +- Anova_Twice +- Anova_Bartlett +- Anova_Levene +- 假设检验 +- 配对检验 + +###### Estimate_SNU + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(4.68, 4.85, 4.32, 4.85, 4.61, 5.02, 5.2, 4.6, 4.58, 4.72, 4.38, 4.7); +return Estimate_SNU(x, nil, 0.05, 'both'); +``` + +参考Estimate*TNU Estimate* SND Estimate_TND Estimate_SP Estimate_TP + +###### Estimate_TNU + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((628, 583, 510, 554, 612, 523, 530, 615), (535, 433, 398, 470, 567, 480, 498, 560, 503, 426)); +d := array(nil, nil); +return Estimate_TNU(X, d, 0.05, 'both', 1); +``` + +参考Estimate*SNU Estimate* SND Estimate_TND Estimate_SP Estimate_TP + +###### Estimate\_ SND + +范例 + +```tsl +x := array(45.3, 45.4, 45.1, 45.3, 45.5, 45.7, 45.4, 45.3, 45.6); +alpha := 0.05; +return Estimate_SND(x, alpha, 'right'); +``` + +参考Estimate_SNU Estimate_TNU Estimate_TND Estimate_SP Estimate_TP + +###### Estimate_TND + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((2.066, 2.063, 2.068, 2.06, 2.067), (2.058, 2.057, 2.063, 2.059, 2.06)); +alpha := 0.1; +return Estimate_TND(X, alpha); +``` + +参考Estimate*SNU Estimate_TNU Estimate* SND Estimate_SP Estimate_TP + +###### Estimate_SP + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +mx := 0.3; +n := 120; +alpha := 0.05; +return Estimate_SP(mx, n, alpha); +``` + +参考Estimate*SNU Estimate_TNU Estimate* SND Estimate_TND Estimate_TP + +###### Estimate_TP + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +P := array(0.478, 0.328); +N := array(1000.00, 750.00); +alpha := 0.05; +return Estimate_TP(P, N, alpha); +``` + +参考Estimate*SNU Estimate_TNU Estimate* SND Estimate_TND Estimate_SP + +###### Hypoth_TailRes + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Hypoth_TailRes(50.110101, 0.06, "left", 0.05); +``` + +###### NormPlot + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := rand(10); +return NormPlot(x); +``` + +array( + +("采样位数":0.171976955840364,"理想位数":-1.64484977722168), + +("采样位数":0.301570532377809,"理想位数":-1.03643536567688), + +("采样位数":0.470976530341431,"理想位数":-0.674489885568619), + +("采样位数":0.479131903499365,"理想位数":-0.38532167673111), + +("采样位数":0.678062069928274,"理想位数":-0.125661492347717), + +("采样位数":0.735156666953117,"理想位数":0.125661492347717), + +("采样位数":0.739045920781791,"理想位数":0.38532167673111), + +("采样位数":0.780685598030686,"理想位数":0.674489885568619), + +("采样位数":0.817699506180361,"理想位数":1.03643536567688), + +("采样位数":0.828364443266764,"理想位数":1.64484977722168)) + +QQ图形: + +Return NormPlot(x,1); + +结果:0.911334081735257参考Hypoth_Kstest Hypoth_lillietest + +###### Hypoth_Kstest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Hypoth_Kstest(randn(0, 1, 100), ’both’, a, cdf); +``` + +参考NormPlot Hypoth_lillietest + +###### Hypoth_lillietest + +用途:统计推断相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return Hypoth_lillietest(array(9.4000, 8.8000, 9.6000, 10.2000, +10.1000, 7.2000 , 11.1000, 8.2000, +8.6000, 9.6000), +0.05, "norm"); +``` + +参考NormPlot Hypoth_Kstest + +###### Hypoth_IndepTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((25, 70, 60, 85, 95, 90, 80), (70, 60, 20, 30, 15, 40, 35), (50, 70, 60, 80, 90, 70, 75)); +return Hypoth_IndepTest(X, 0.05); +``` + +结果表示拒绝原假设,即x与y有关参考Hypoth_KruskalWallis + +###### Hypoth_KruskalWallis + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array((120, 30), (479, 371));return Hypoth_KruskalWallis(x, 0.05); +``` + +结果表示接受原假设,即x与y无关参考Hypoth_IndepTest + +###### Hypoth_SNUTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(8.05, 8.15, 8.2, 8.1, 8.25); +u := 8; +d := 0.2; +tail := "both"; +alpha := 0.05; +return Hypoth_SNUTest(x, u, d, tail, alpha); +``` + +表示接受原假设,均值等于8,该假设检验使用U检验,其中U统计量为1.677,对应的P值为0.094,在显著性水平为0.05时,不能拒绝原假设,所以我们接受原假设。结果中还给出了均值的在0.05的显著性水平下的置信区间参考Hypoth_TNUTest +Hypoth_SNDTest Hypoth_TNDTest Hypoth_LSUTest + +###### Hypoth_TNUTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((76.43, 76.21, 73.58, 69.69, 65.29, 70.83, 82.75, 72.34), +(73.66, 64.27, 69.34, 71.37, 69.77, 68.12, 67.27, 68.07, 62.61)); +uu := 0; +d := array(1, 1); +tail := "both"; +alpha := 0.05; +return Hypoth_TNUTest(X, uu, d, tail, alpha, 0); +``` + +表示拒绝均值差等于0的原假设。该假设检验使用U检验,其中U统计量为10.525,对应的P值为0.00,在显著性水平为0.05时,拒绝原假设,所以我们认为两个样本均值之差显著不为0。结果中还给出了均值差在0.05的显著性水平下的置信区间。参考Hypoth_SNUTest +Hypoth_SNDTest Hypoth_TNDTest Hypoth_LSUTest + +###### Hypoth_SNDTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(1.38, 1.43, 1.39, 1.40, 1.41); +d2 := sqr(0.048); +tail := "left"; +alpha := 0.1; +return Hypoth_SNDTest(x, d2, tail, alpha); +``` + +表示拒绝方差大于sqr(0.048)的原假设。该假设检验使用卡方检验,其中卡方统计量为0.642,对应的P值为0.042,在显著性水平为0.05时,拒绝原假设。参考Hypoth_SNUTest +Hypoth_TNUTest Hypoth_TNDTest Hypoth_LSUTest + +###### Hypoth_TNDTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((0.140, 0.138, 0.143, 0.141, 0.144, 0.137), (0.135, 0.140, 0.142, 0.136, 0.139)); +tail := "both"; +alpha := 0.1; +return Hypoth_TNDTest(X, tail, alpha); +``` + +表示接受原假设,则方差相同参考Hypoth_SNUTest Hypoth_TNUTest Hypoth_SNDTest +Hypoth_LSUTest + +###### Hypoth_LSUTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +mx := 1.85; +s2 := 0.0064; +n := 100; +u := 1.84; +tail := "both"; +alpha := 0.01; +return Hypoth_LSUTest(mx, s2, n, u, tail, alpha); +``` + +表示均值为1.84参考Hypoth_SNUTest Hypoth_TNUTest Hypoth_SNDTest Hypoth_TNDTest + +###### Anova_Single + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +例子来自《概率论与数理统计教程》-高等教育出版社 P379 例8.1.4 + +因素A有4个水平,对A进行重复试验,获得观察值如下: + +A1=12 18 + +A2=14 12 13 + +A3=19 17 21 + +A4=24 30 + +现在显著性水平0.05下,判断以上各水平是否有显著差异 + +```tsl +x := array((12, 18), (14, 12, 13), (19, 17, 21), (24, 30)); +alpha := 0.05; +return Anova_Single(x, alpha); +``` + +结果表示拒绝原假设,即各个水平下的方差间有显著差异参考Anova_Twice Anova_Bartlett +Anova_Levene + +###### Anova_Twice + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +在某指标,因素A和因素B有3个水平,对A、B分别进行2次重复试验,获得观察值如下: + +x:= +array((75.00,81.00,74.00),(75.00,81.00,73.00),(62.00,85.00,79.00),(71.00,68.00,60.00), +(58.00,92.00, 75.00),(73.00,90.00,81.00)); + +现在显著性水平0.05下,判断以上因素A和B对某指标是否有显著影响 + +```tsl +x := array((75.00, 81.00, 74.00), (75.00, 81.00, 73.00), (62.00, 85.00, 79.00), (71.00, 68.00, 60.00), (58.00, 92.00, 75.00), (73.00, 90.00, 81.00)); +return Anova_Twice(x, 0.05, 2); +``` + +因素A:结果表示接受原假设,即因素A对某指标无显著影响 + +因素B:结果表示拒绝原假设,即因素B对某指标影响显著 + +交叉效应:结果表示拒绝原假设,即交叉效应对某指标影响显著参考Anova_Single +Anova_Bartlett Anova_Levene + +###### Anova_Bartlett + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +因素A有4个水平,对A进行重复试验,获得观察值如下: + +A1=7.96.26.68.68.910.19.6 + +A2=5.7 7.5 9.8 6.1 8.4 + +A3=6.4 7.1 7.9 4.5 5 4 + +A4=6.8 7.5 5 5.3 6.1 7.4 + +现在显著性水平0.05下,判断以上四组数据方差是否有显著差异: + +```tsl +x := array((7.9, 6.2, 6.6, 8.6, 8.9, 10.1, 9.6), (5.7, 7.5, 9.8, 6.1, 8.4), (6.4, 7.1, 7.9, 4.5, 5.0, 4.0), (6.8, 7.5, 5.0, 5.3, 6.1, 7.4)); +return Anova_Bartlett(x, 0.05); +``` + +array("B-Stat":0.965,"P-Value":0.81,"df":3,"Hypothesis":1) + +结果表示接受原假设,即各个水平下的方差间无显著差异参考Anova_Single Anova_Twice +Anova_Levene + +###### Anova_Levene + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +因素A有4个水平,对A进行重复试验,获得观察值如下: + +A1=7.96.26.68.68.910.19.6 + +A2=5.7 7.5 9.8 6.1 8.4 + +A3=6.4 7.1 7.9 4.5 5 4 + +A4=6.8 7.5 5 5.3 6.1 7.4 + +现在显著性水平0.05下,判断以上四组数据方差是否有显著差异: + +```tsl +x := array((7.9, 6.2, 6.6, 8.6, 8.9, 10.1, 9.6), (5.7, 7.5, 9.8, 6.1, 8.4), (6.4, 7.1, 7.9, 4.5, 5.0, 4.0), (6.8, 7.5, 5.0, 5.3, 6.1, 7.4)); +return Anova_Levene(x, 0.05); +``` + +array("F-Stat":0.514,"P-Value":0.678,"df1":3,"df2":20,"Hypothesis":1) + +结果表示接受原假设,即各个水平下的方差间无显著差异参考Anova_Single Anova_Twice +Anova_Bartlett + +###### 假设检验 + +####### 内容 + +- Hypoth_SignTest +- Hypoth_WilcoxonTest +- Hypoth_McNemarTest + +####### Hypoth_SignTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(27.8, 27.8, 29.1, 32.2, 32.7, 32.7, 36.4, 36.5, 37.5, 37.7, 38.8, 41.9); +pi_ := 0.5; +q0 := 32; +tail := "both"; +Alpha := 0.05; +return Hypoth_SignTest(x, pi_, q0, tail, alpha); +``` + +####### Hypoth_WilcoxonTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(27.8, 27.8, 29.1, 32.2, 32.7, 32.7, 36.4, 36.5, 37.5, 37.7, 38.8, 41.9); +m0 := 34; +tail := "both"; +Alpha := 0.05; +return Hypoth_WilcoxonTest(x, m0, tail, Alpha); +``` + +结果 + +####### Hypoth_McNemarTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array((6, 4), (20, 10)); +Alpha := 0.05; +return Hypoth_McNemarTest(x, Alpha); +``` + +结果 + +###### 配对检验 + +####### 内容 + +- Hypoth_PNUTest +- Hypoth_PSignTest +- Hypoth_PWilcoxonTest + +####### Hypoth_PNUTest + +用途:统计推断相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +X := array((5, 4, 7, 3, 5, 8, 5, 6), (6, 6, 7, 4, 3, 9, 7, 6)); +uu := 0; +d := nil; +tail := "both"; +alpha := 0.05; +return Hypoth_PNUTest(x, uu, d, tail, alpha) +``` + +####### Hypoth_PSignTest + +####### Hypoth_PWilcoxonTest + +##### 多元统计分析 + +###### 内容 + +- Corr +- CorrelationMatrix +- Covariance +- Corrcoef +- Corr_partial +- Distance +- Cluster_Kmeans +- Cluster_System +- Cluster_ward +- Discrim +- princomp +- Factor +- corr_canonical +- corr_Spearman +- 相对重要性 +- Cov2CorrMatrix +- CorrMatrixAdjust +- corr_Kendall +- HISTC + +###### Corr + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := rand(3, 4); +return Corr(A, 1); // 返回的是一般相关系数矩阵 +``` + +输出结果: + +```tsl +A := rand(3, 4); +return ret := Corr(A, 1, 'both'); +``` + +输出结果: + +array( + +( + +(1,-0.997183665009044,-0.25079062964811,0.52903553507686), + +(-0.997183665009044,1,0.177482907109564,-0.463902099303707), + +(-0.25079062964811,0.177482907109564,1,-0.954156728736678), + +(0.52903553507686,-0.463902099303707,-0.954156728736678,0.999999999999999)), + +( + +(0.00,0.0477902336084508,0.83861889909013,0.645107717271616), + +(0.0477902336084508,0.00,0.886409132694126,0.692897950958597), + +(0.83861889909013,0.886409132694126,0.00,0.1935111818216), + +(0.645107717271616,0.692897950958597,0.1935111818216,2.683151079097E-8))) + +Ret[0]:相关系数矩阵 + +Ret[1]:相关系数假设检验P值参考Covariance Corr_partial CorrelationMatrix +Corrcoef Corr_partial Distance + +###### CorrelationMatrix + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := rand(4, 3); +return CorrelationMatrix(a, 1); +``` + +结果 + +参考Corr Covariance Corr_partial Corrcoef Corr_partial Distance + +###### Covariance + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := rand(4, 3); +return Covariance(A); +``` + +结果 + +参考Corr CorrelationMatrix Corr_partial Corrcoef Corr_partial Distance + +###### Corrcoef + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := rand(7, 4); +return Corrcoef(A); // 返回简单相关系数分析 +``` + +输出结果: + +参考Corr Covariance Corr_partial CorrelationMatrix Corr_partial Distance + +###### Corr_partial + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := rand(100, 3); +y := rand(100, 2); +z := rand(100, 2); +return Corr_partial(x, y, z, 2); +// 返回结果:array((-0.0862,0.2046),(-0.1844,0.00),(0.0736,0.0411)) +ret := Corr_partial(x, y, z, 2, 'both'); // 返回检验ret 为一个数据表类型 +return ret['coef']; // 偏相关系数 +return ret['pval']; // 检验偏相关系数是否显著的P值 +return ret['df']; // 自由度 +``` + +参考Corr Covariance CorrelationMatrix Corrcoef Corr_partial Distance + +###### Distance + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(22, 35, 24, 32, 43, 53); +y := array(1, 2, 3, 4, 5, 6); +name := 'euclidean'; // 采用欧式距; +return Distance(x, y, name); +``` + +结果 80.04998438475; + +```tsl +x := array( +(700.9, 39.77, 8.49, 12.94, 19.27, 11.05, 2.04, 13.29), +(7.68, 50.37, 11.35, 13.3, 19.25, 14.59, 2.75, 14.87), +(9.42, 27.93, 8.2, 8.14, 16.17, 9.42, 1.55, 9.76), +(9.16, 27000.98, 9.01, 9.32, 15.99, 9.1, 1.82, 11.35), +(10.06, 28.64, 10.52, 10.05, 16.18, 8.39, 1.96, 10.81)); +name := "euclidean"; +return Distance(x, name); +``` + +结果 + +array( + +(0,693.32,691.62,26970.08,690.96), + +(693.32,0,24.64,26950.61,23.54), + +(691.62,24.64,0,26973.05,3.5), + +(26970.08,26950.61,26973.05,0,26972.34), + +(690.96,23.54,3.5,26972.34,0));参考Corr Covariance Cluster_Kmeans Cluster_System +Cluster_ward + +###### Cluster_Kmeans + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +sample := array( +(700.9, 39.77, 8.49, 12.94, 19.27, 11.05, 2.04, 13.29), (7.68, 50.37, 11.35, 13.3, 19.25, 14.59, 2.75, 14.87), +(9.42, 27.93, 8.2, 8.14, 16.17, 9.42, 1.55, 9.76), +(9.16, 27000.98, 9.01, 9.32, 15.99, 9.1, 1.82, 11.35), +(10.06, 28.64, 10.52, 10.05, 16.18, 8.39, 1.96, 10.81)); +n := 3; +options := array("maxiter":20, "tol":1.0e - 16, "distance":1, "out":1); // 可不输入采用默认 +return Cluster_Kmeans(sample, n, options); +``` + +结果 + +array( + +(1,2,4), //第一类为 1,2,4 个样本 + +(3), // 第二类为第3个样本 + +(0)); // 第三类为第0 个样本参考Distance Cluster_System Cluster_ward + +###### Cluster_System + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array( +(7.9, 39.77, 8.49, 12.94, 19.27, 11.05, 2.04, 13.29), +(7.68, 50.37, 11.35, 13.3, 19.25, 14.59, 2.75, 14.87), +(9.42, 27.93, 8.2, 8.14, 16.17, 9.42, 1.55, 9.76), +(9.16, 27.98, 9.01, 9.32, 15.99, 9.1, 1.82, 11.35), +(10.06, 28.64, 10.52, 10.05, 16.18, 8.39, 1.96, 10.81)); +dmethods := 1; +methods := 1; +output := array('best':1); +ret1 := Cluster_System(a, Dmethods, Methods); +ret2 := Cluster_System(a, Dmethods, Methods, output); +``` + +ret1,为谱系图 + +array( + +(2,3,2.2032702966273), + +(2,3,3.50368377568526), + +(0,1,11.6726218134573), + +(0,1,18.0243203755371)); + +谱系图解析: + +每行表示一次归类,(2,3,2.2032702966273)表示将第2个样本与第3个样本合并,为样本2,样本3,4为合并前的样本4,5,样本数减少一个。(2,3,3.50368377568526)表示将第3个样本与第2个样本合并为样本2,样本3为该次合并前的样本4, 样本数减少一个。 + +ret2为最佳分类 + +array(0,0,1,1,1) ; + +样本0,1 被分在第一个类; + +样本 2,3,4 被分在第二个类中;参考Distance Cluster_Kmeans Cluster_ward + +###### Cluster_ward + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array( +(7.9, 39.77, 8.49, 12.94, 19.27, 11.05, 2.04, 13.29), +(7.68, 50.37, 11.35, 13.3, 19.25, 14.59, 2.75, 14.87), +(9.42, 27.93, 8.2, 8.14, 16.17, 9.42, 1.55, 9.76), +(9.16, 27.98, 9.01, 9.32, 15.99, 9.1, 1.82, 11.35), +(10.06, 28.64, 10.52, 10.05, 16.18, 8.39, 1.96, 10.81)); +return Cluster_ward(a); +``` + +结果 + +结果解析:第0列与第1列表示合并组合的相对位置,第2列表示合并组合间的距离平方,第3 列表示分类情况,中各个元素用 "," 分割类类之间用"#"分割 + +###### Discrim + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := array( +(3.00, 8.35, 23.53, 7.51, 8.62, 17.42, 10.00, 1.04, 11.21), +(3.00, 9.25, 23.75, 6.61, 9.19, 17.77, 10.48, 1.72, 10.51), +(3.00, 8.19, 30.5, 4.72, 9.78, 16.28, 7.6, 2.52, 10.32), +(3.00, 7.73, 29.2, 5.42, 9.43, 19.29, 8.49, 2.52, 10.00), +(3.00, 9.42, 27.93, 8.2, 8.14, 16.17, 9.42, 1.55, 9.76), +(3.00, 9.16, 27.98, 9.01, 9.32, 15.99, 9.1, 1.82, 11.35), +(3.00, 10.06, 28.64, 10.52, 10.05, 16.18, 8.39, 1.96, 10.81), +(1.00, 8.67, 36.05, 7.31, 7.75, 16.67, 11.68, 2.38, 12.88), +(1.00, 9.98, 37.69, 7.01, 8.94, 16.15, 11.08, 0.83, 11.67), +(1.00, 6.77, 38.69, 6.01, 8.82, 14.79, 11.44, 1.74, 13.23), +(1.00, 8.14, 37.75, 9.61, 8.49, 13.15, 9.76, 1.28, 11.28), +(1.00, 7.67, 35.71, 8.04, 8.31, 15.13, 7.67, 1.41, 13.25), +(1.00, 7.9, 39.77, 8.49, 12.94, 19.29, 11.05, 2.04, 13.29), +(1.00, 7.18, 40.91, 7.32, 8.94, 17.6, 12.75, 1.14, 14.8), +(1.00, 8.82, 33.7, 7.59, 10.98, 18.82, 14.73, 1.78, 10.1), +(1.00, 6.25, 35.02, 4.72, 6.28, 10.03, 7.15, 1.93, 10.39), +(2.00, 10.6, 52.41, 7.7, 9.98, 12.53, 11.7, 2.31, 14.69), +(3.00, 7.27, 52.65, 3.84, 9.16, 13.03, 15.26, 1.98, 14.57), +(3.00, 13.45, 55.85, 5.5, 7.45, 9.55, 9.52, 2.21, 16.3), +(3.00, 10.85, 44.68, 7.32, 14.51, 17.13, 12.08, 1.26, 11.57), +(3.00, 7.21, 45.79, 7.66, 10.36, 16.56, 12.86, 2.25, 11.69), +(3.00, 7.68, 50.37, 11.35, 13.3, 19.25, 14.59, 2.75, 14.87), +(2.00, 7.78, 48.44, 8.00, 20.51, 22.12, 15.73, 1.15, 16.61)); +X := array( +(9.09, 28.12, 7.4, 9.62, 17.26, 11.12, 2.49, 12.65), +(9.41, 28.2, 5.77, 10.8, 16.36, 11.56, 1.53, 12.17), +(8.7, 28.12, 7.21, 10.53, 19.45, 13.3, 1.66, 11.96), +(6.93, 29.85, 4.54, 9.49, 16.62, 10.65, 1.88, 13.61)); +options := array('cov':1, 'backtest':1, 'crosstest':1); +return Discrim(A, X, 0, options); +``` + +计算结果: + +参考Cluster_Kmeans Cluster_System Distance Cluster_ward + +###### princomp + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := array( +(947.00, 23.4, 14.8, 45.3, 0.46, 85.2, 373.00, 9.54, 0.37, 3.88), +(935.00, 23.2, 16.2, 41.7, 0.4, 83.3, 305.00, 7.9, 0.38, 4.81), +(918.2, 20.9, 14.8, 43.8, 0.38, 82.6, 320.00, 9.51, 0.43, 4.52), +(910.7, 23.4, 16.1, 44.00, 0.46, 85.2, 338.00, 8.6, 0.33, 3.84), +(905.00, 22.9, 17.00, 39.8, 0.45, 80.4, 348.00, 9.53, 0.42, 4.4), +(890.6, 22.3, 15.7, 44.00, 0.41, 85.4, 286.00, 8.67, 0.39, 4.5), +(853.4, 20.9, 15.9, 41.6, 0.35, 85.4, 273.00, 9.79, 0.42, 4.29), +(837.3, 20.2, 14.4, 37.3, 0.33, 82.5, 326.00, 7.62, 0.36, 4.73), +(833.3, 22.2, 15.2, 38.3, 0.37, 82.2, 310.00, 7.84, 0.4, 5.1), +(760.9, 20.4, 15.5, 40.7, 0.32, 84.2, 268.00, 7.75, 0.35, 4.52), +(760.3, 20.8, 15.1, 44.8, 0.35, 79.5, 273.00, 8.91, 0.45, 5.05), +(742.5, 23.4, 14.7, 43.1, 0.35, 79.5, 310.00, 9.13, 0.4, 4.36)); +return princomp(data, 0.85, 1, resid); +``` + +参考Factor + +###### Factor + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +我们对2010年上证A股的9个财务指标进行因子分析: + +TSL代码: + +```tsl +stockn := getbk("上证A股"); +vo := BackUpSystemParameters(); +SetSysParam(pn_date(), today()); +sto := array(); +for nI := 0 to length(stockn) - 1 do +begin + SetSysParam(pn_stock(), stockn[nI]); + if IsStockGoMarket(inttodate(20011231)) then sto[length(sto)] := stockn[nI]; +end; +st := array2str(sto, ";"); +A1 := Query("", st, true, "", "代码", DefaultStockID(), +"主营业务利润", report(46008, 20101231), +"利润总额", report(46024, 20101231), +"净利润", report(46033, 20101231), +"加权每股收益", report(42003, 20101231), +"每股净资产", report(42006, 20101231), +"加权净资产收益率", report(42013, 20101231), +"资产总计", report(44059, 20101231), +"股本", report(44099, 20101231)); +RestoreSystemParameters(vo); +a := zeros(mrows(a1), mcols(a1)); +a[:, :] := a1[:, :]; +stock := a[:, 0]; +data := a[:, 1:8]; +// 取得纯数据矩阵 +br := Factor(data, 0.85); // +return br; +``` + +结果分析: + +Ret["kmo",0]=0.733,即表明数据可以做因子分析 + +ret["Total Variance +Explained",0]:第一列为样本矩阵的相关系数矩阵的特征值,第二列为方差贡献率,第三列为累计方差贡献率 + +ret["Component Matrix",0]:因子载荷矩阵 + +ret["Communalities",0]:共同度表示三个因子解释掉变量的多少,显然,共同度越大,表示能解释原来变量的信息就越全; + +ret["thogonal matrix",0]:从thogonal +matrix中看出第一个公因子可以解释为“规模因子”,因为它的 0:主营业务收入净额、1:主营业务利润;、2:利润总额、3:净利润、7:资产总计、8:股本的绝对值都比较大;第二个公因子可以解释为“收益率因子”,因为其4:每股收益、5:每股净资产的绝对值大;第三个公因子则可以解释为“每股价值因子”因为其4:每股收益和6:净资产收益率;的绝对值较大。因子分析模型中的因子是抽象的,得根据研究对象的具体分析所解释,“解释”是抽象的概念。 + +ret["Rotation matrix",0]:旋转矩阵 + +array( + +(0.9888,0.1296,0.0734), + +(-0.149,0.8703,0.4695), + +(-0.0031,-0.4752,0.8799)) + +ret["Factor +score",0]:因子得分,表示各个股票在这三个因子的得分情况,让研究人员更好的做其他分析参考princomp + +###### corr_canonical + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +典型性分析算法说明: + +典型相关分析是用来分析两组随机变量之间的相关性程度的一种统计方法,它能够有效地解释两组随机变量之间相互线性依赖的关系。 + +比如在实际问题中,经常遇到一部分变量和另一部分变量之间的相互关系。例如,在经济学中研究商品价格的相关指标和销售的相关指标之间的关系;在地质学中,研究岩石形成的成因关系,考察岩石的化学成分与其周围化学成分的相关性;教育学中,考察学生入学考试成绩和本科阶段一些主要课程成绩的相关性;在统计学中,也可以用来做随机变量之间的多重共线性判断和重构随机变量组,改进随机变量之间多重共线性问题,使得回归分析等结果更加合理,等等。 + +一般地,假设有两组随机变量和研究它们的相关关系,当p=q=1时,就是通常两个随机变量之间的相关关系;当p>1,q>1时,采用类似主成分分析的方法,找出的线性组合U和的线性组合V,即:U=,,于是将研究两组变量的相关性问题转化成研究两个变量的相关性问题,并且可以适当的调整系数a 和b,使得U和V的相关性达到最大,称这种相关为典型相关,基于这种原则的分析方法称为典型相关分析。 + +第一步,先定义典型相关,设X=和Y=为随机向量,用X和Y的线性组合和之间相关性来研究X与Y之间的相关性,并希望找到a与b,使得最大。由相关系数定义, + +| | | (4. 1) | +| --- | --- | ------ | + +对任意的α,β和c,d有 + +| | | (4. 2) | +| --- | --- | ------ | + +式(4.2)说明,使得相关系数最大的和并不唯一。因此,在综合变量,可限定,。 + +总结一下第一步,设X=和Y=,p+q维随机向量的均值为0,协方差阵正定。若存在a1=和b1=,使得是约束问题 + +| | max | (4. 3) | +| --- | ---- | ------ | +| | s.t. | (4. 4) | +| | | (4. 5) | + +目标函数的最大值,则成,为的第一对典型变量,称它们之间的相关系数为第一典型相关系数。 + +如果存在和使得 + +和前面的k-1对典型变量都不相关; + +; + +和相关系数最大 + +则称,为的第k对典型变量,称它们之间的相关系数为第k典型相关系数典型相关系数。 + +第二步,下面直接给出计算过程所需的重要推导步骤以及计算过程: + +设Z=,则有,,令,,因此,求解第一对典型变量和典型相关系数的约束问题式(4.3)~(4.5)就等价为 + +| | max | (4. 6) | +| --- | ---- | ------ | +| | s.t. | (4. 7) | +| | | (4. 8) | + +这是一个典型的约束优化问题,这里采用拉格朗日乘数法求解该约束问题,其中为Lagrange乘子,得到如下方程: + +| | | (4. 9) | +| --- | --- | ------- | +| | | (4. 10) | +| | | (4. 11) | +| | | (4. 12) | + +求解上述方程组,在式(4.6)左乘,在式(4.7)左乘,然后将式(4.8)代入式(4.6),将式(4.9)代入式(4.7),得到结果。由于正定(在第一步中有定义,即使没有定义的情况下协方差矩阵也是半正定的),所以和存在,先将式(4.6)和(4.7)中和移到等号右边,然后再分别左乘和,得到 + +| | , | (4. 13) | +| --- | --- | ------- | + +然后将代入式中,所以有 + +| | | (4. 14) | +| --- | --- | ------- | + +同理,可得 + +| | | (4. 15) | +| --- | --- | ------- | + +其中,。 + +因此,是矩阵特征根(注意,和具有相同的特征根),是的特征根对应的特征向量,是的特征根对应的特征向量。 + +由于,式(4.9)和式(4.11)可得。所以典型相关系数就是和共有根号下的特征根。 + +因此,优化问题式(4.3)~式(4.5)的解和就是求或最大特征跟相应的特征向量和。 + +计算步骤如下: + +令; + +计算最大的特征根和对应的特征向量,令,,,则为第一对典型相关系数,,为第一对典型变量。 + +对于第k对典型变量的求解方法类似于第一对典型相关变量,只需要将(2)改为 + +计算最大的特征根和对应的特征向量,令,,,则是第k对典型相关系数,,为第k对典型变量。 + +第三步,由于在实际中,设,和,所以无法求出典型变量和典型相关系数,需要用样本数据估计样本协方差矩阵。 + +已知,总体Z的n次观测数据 + +于是可给出Z的样本资料矩阵为 + +假设Z~Np+q(μ,∑),则样本协方差的极大似然估计为 + +其中,称为样本协方差矩阵。具体计算过程和第二步中的计算步骤基本相同,只需要将替换为即可求解。范例 + +实例1: + +某康复俱乐部对两组指标的典型相关性分析 + +某康复俱乐部对20名中年人测量了3个生理指标:体重(X1)、腰围(X2)、脉搏(X3)和三个训练指标:引体向上(Y1)、仰卧起坐次数(Y2)、跳跃次数(Y3) + +表1 :某康复俱乐部两组生理指标的典型相关分析 + +| 编号 | X1 | X2 | X3 | Y1 | Y2 | Y3 | +| ---- | --- | --- | --- | --- | --- | --- | +| 1 | 191 | 36 | 50 | 5 | 162 | 60 | +| 2 | 193 | 38 | 58 | 12 | 101 | 101 | +| 3 | 189 | 35 | 46 | 13 | 155 | 58 | +| 4 | 211 | 38 | 56 | 8 | 101 | 38 | +| 5 | 176 | 31 | 74 | 15 | 200 | 40 | +| 6 | 169 | 34 | 50 | 17 | 120 | 38 | +| 7 | 154 | 34 | 64 | 14 | 215 | 105 | +| 8 | 193 | 36 | 46 | 6 | 70 | 31 | +| 9 | 176 | 37 | 54 | 4 | 60 | 25 | +| 10 | 156 | 33 | 54 | 15 | 225 | 73 | +| 11 | 189 | 37 | 52 | 2 | 110 | 60 | +| 12 | 162 | 35 | 62 | 12 | 105 | 37 | +| 13 | 182 | 36 | 56 | 4 | 101 | 42 | +| 14 | 167 | 34 | 60 | 6 | 125 | 40 | +| 15 | 154 | 33 | 56 | 17 | 251 | 250 | +| 16 | 166 | 33 | 52 | 13 | 210 | 115 | +| 17 | 247 | 46 | 50 | 1 | 50 | 50 | +| 18 | 202 | 37 | 62 | 12 | 210 | 120 | +| 19 | 157 | 32 | 52 | 11 | 230 | 80 | +| 20 | 138 | 33 | 68 | 2 | 110 | 43 | + +```tsl +return corr_canonical(x, y, 0.1, 1); +``` + +实例2:企业经济效益典型相关分析 + +某市为了全面分析机械类各企业的经济效益,选择了8个不同的利润指标,14家企业关于这8个指标的统计数据如表4-1所示. + +表2:机械类各企业的经济效益主成分分析 + +| 企业 | X1净产值利润率% | X2固定资产利润率% | X3总产值利润% | X4销售收入利润率% | Y1产品成本利润率% | Y2物耗利润率% | Y3人均利润率千元/人 | Y4流动资金利润率% | +| ---- | --------------- | ----------------- | ------------- | ----------------- | ----------------- | ------------- | ------------------- | ----------------- | +| 1 | 40.4 | 24.7 | 7.2 | 6.1 | 8.3 | 8.7 | 2.44 | 20.0 | +| 2 | 25.0 | 12.7 | 11.2 | 11.0 | 12.9 | 20.2 | 3.542 | 9.1 | +| 3 | 13.2 | 3.3 | 3.9 | 4.3 | 4.4 | 5.5 | 0.578 | 3.6 | +| 4 | 22.3 | 6.7 | 5.6 | 3.7 | 6.0 | 7.4 | 0.176 | 7.3 | +| 5 | 34.3 | 11.8 | 7.1 | 7.1 | 8.0 | 8.9 | 1.726 | 27.5 | +| 6 | 35.6 | 12.5 | 16.4 | 16.7 | 22.8 | 29.3 | 3.017 | 26.6 | +| 7 | 22.0 | 7.8 | 9.9 | 10.2 | 12.6 | 17.6 | 0.847 | 10.6 | +| 8 | 48.4 | 13.4 | 10.9 | 9.9 | 10.9 | 13.9 | 1.772 | 17.8 | +| 9 | 40.6 | 19.1 | 19.8 | 19.0 | 29.7 | 39.6 | 2.449 | 35.8 | +| 10 | 24.8 | 8.0 | 9.8 | 8.9 | 11.9 | 16.2 | 0.789 | 13.7 | +| 11 | 12.5 | 9.7 | 4.2 | 4.2 | 4.6 | 6.5 | 0.874 | 3.9 | +| 12 | 1.8 | 0.6 | 0.7 | 0.7 | 0.8 | 1.1 | 0.056 | 1.0 | +| 13 | 32.3 | 13.9 | 9.4 | 8.3 | 9.8 | 13.3 | 2.126 | 17.1 | +| 14 | 38.5 | 9.1 | 11.3 | 9.5 | 12.2 | 16.4 | 1.327 | 11.6 | + +```tsl +// 首先选取数据并且对数据做标准化z-score,消除量纲对结果的影响 +X := data[:][0:3]; +Y := data[:][4:7]; +return corr_canonical(X, Y, 0.1, 1); +``` + +数据返回结论分析: + +首先说明XCenter和YCenter返回结果都为零是因为做了数据标准化的结果。从Cor我们可以看出X和Y这两组随机变量之间具有很高的相似度,第一对典型相关系数达到100%的相似度。在这里想说明的是,如果在对类似数据进行回归分析的时候,回归诊断发现了比较严重的多重共线性的时候,此时可以运用典型相关分析的方法,提取出典型相关成都最高的第一对典型相关组合U或者V来代替之前出现多重共线性的随机变量,从而消除和改进回归模型的病态和精度。 + +###### corr_Spearman + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +算法ρ=∑(Rxi-Rx)(Ryi-Ry)∑(Rxi-Rx)2(Ryi-Ry)2 + +其中:Rx、Ry分别是x和y的位次,位次按照从大到小排序后,这个数所在的位置。 + +Rx、Ry分别表示平均位次。范例 + +```tsl +x := array(3, 8, 4, 7, 2); +y := array(5, 10, 8, 10, 6); +return corr_Spearman(x, y); +``` + +结果:0.87208 + +###### 相对重要性 + +####### 内容 + +- Regress_domin_formula +- Regress_domin_marginal + +####### Regress_domin_formula + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := rand(10); +x := rand(10, 3); +mr := Regress_Domin_Formula(y, x); +return array( +'详情':mr, +'---':'---', +'贡献和':sum(mr[:, '贡献度']), +'R2':Regression(y, x, 0.05, 1)['R-Squared'] +); +``` + +####### Regress_domin_marginal + +用途:进行数值统计计算。 +参数: + +返回:处理后的结果值。 + +算法 + +1、快速R2边际效用法:为完整回归的R2减去不包含变量 k 的回归的R2的差 + +2、平均R2边际效用法:考虑剔除回归的顺序 + + 自变量较多时较消耗效率,一般在自变量不多于30个时使用范例 + +```tsl +Y := array(11.73913, 6.400963, 5.016723, 9.033813, 8.083731, 4.62963, +10.49114, 17.20612, 13.08374, 7.745568); +X := array( +(37.0, 48.0, 5.333333, 0.0, 69.33332900000001), +(37.0, 40.0, 5.25, 0.0, 60.0), +(42.0, 40.0, 1.25, 0.0, 16.25), +(43.0, 42.0, 1.75, 1.0, 22.75), +(42.0, 48.0, 17.75, 1.0, 200.0), +(39.0, 30.0, 2.25, 1.0, 29.25), +(37.0, 40.0, 19.0, 0.0, 247.0), +(40.0, 45.0, 14.16667, 1.0, 150.0), +(40.0, 8.0, 5.5, 1.0, 71.5), +(40.0, 50.0, 2.25, 1.0, 29.25)); +return Regress_Domin_Marginal(Y, X, nil, 1); +// 结果 +array( +("变量名":0, "贡献度":0.03, "贡献率(%)":7.87, "排名":4), +("变量名":1, "贡献度":0.02, "贡献率(%)":6.93, "排名":5), +("变量名":2, "贡献度":0.13, "贡献率(%)":37.94, "排名":1), +("变量名":3, "贡献度":0.06, "贡献率(%)":15.86, "排名":3), +("变量名":4, "贡献度":0.11, "贡献率(%)":31.4, "排名":2)); +``` + +###### Cov2CorrMatrix + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := Covariance(rand(4, 3)); +return Cov2CorrMatrix(A); +``` + +###### CorrMatrixAdjust + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +A := Corr(rand(6, 6)); +return CorrMatrixAdjust(A, 1, 5); +``` + +###### corr_Kendall + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(3, 8, 4, 7, 2); +y := array(5, 10, 8, 10, 6); +return corr_Kendall(x, y); +``` + +结果:0.7379 + +###### HISTC + +用途:多元统计分析相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +a := rand(1000) * 5; +b := array(0, 1, 2, 3, 4, 5); +return HISTC(a, b); +``` + +##### 回归 + +###### 内容 + +- 回归检验 +- 回归公用函数 +- 最小二乘法回归 +- 测试 + +###### 回归检验 + +####### 内容 + +- Regress_Ridge +- Regress_AdjustedR2 +- Regress_Logistic +- Regression +- Regress_DWTest +- Regress_Stepwise +- Regress_Constraint +- Regress_White +- Regress_MLS +- Regress_CMLS +- Regress_JBTest +- Regress_pri +- Regress_FTest +- Regression_WLS +- Regress_Binary +- Regress_TTest +- Regress_NLM +- Regress_WLS +- Regress_AicAndSbic +- Regress_RSquare +- Regress_QRlsq +- boxcox +- Regress_HettestSpearman +- Regress_VIF +- Regress_TTest_RWLS +- Regress_TTest_White +- Regress_TTest_NW +- Regression_OLS_White +- Regression_OLS_NW +- NW_Adjustment_Simplification +- Robustfit_M +- Regress_GRStest + +####### Regress_Ridge + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(49.00, 50.2, 50.5, 48.5, 47.5, 44.5, 28.00, 31.5, 34.5, 35.00, 38.00, 38.5, 15.00, 17.00, 20.5, 29.5); +x := array( +(1300.00, 7.5, 0.012, 9750.00, 15.6, 0.09), +(1300.00, 9.00, 0.012, 11700.00, 15.6, 0.108), +(1300.00, 11.00, 0.0115, 14300.00, 14.95, 0.1265), +(1300.00, 13.5, 0.013, 17550.00, 16.9, 0.1755), +(1300.00, 17.00, 0.0135, 22100.00, 17.55, 0.2295), +(1300.00, 23.00, 0.012, 29900.00, 15.6, 0.276), +(1200.00, 5.3, 0.04, 6360.00, 48.00, 0.212), +(1200.00, 7.5, 0.038, 9000.00, 45.6, 0.285), +(1200.00, 11.00, 0.032, 13200.00, 38.4, 0.352), +(1200.00, 13.5, 0.026, 16200.00, 31.2, 0.351), +(1200.00, 17.00, 0.034, 20400.00, 40.8, 0.578), +(1200.00, 23.00, 0.041, 27600.00, 49.2, 0.943), +(1100.00, 5.3, 0.084, 5830.00, 92.4, 0.4452), +(1100.00, 7.5, 0.098, 8250.00, 107.8, 0.735), +(1100.00, 11.00, 0.092, 12100.00, 101.2, 1.012), +(1100.00, 17.00, 0.086, 18700.00, 94.6, 1.462)); +k := array(); +i := 0; +for nI := 0 to 6e - 3 step 1e - 5 do k[i++] := nI; +return ret := Regress_Ridge(y, x, k, false); // 输出岭迹 +// return ret:= Regress_Ridge(y,x); // 输出x对y的岭回归,方差扩大因子法选取k +``` + +参考Regression Regress_pri Regress_Stepwise Regress_VIF boxcox + +####### Regress_AdjustedR2 + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Regress_AdjustedR2(0.942066, 9, 1); +// 结果:0.93379 +``` + +参考Regress_CMLS Regression Regress_RSquare + +####### Regress_Logistic + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +在一次关于某城镇居民上下班使用交通工具的社会调查中, + +因变量y =1表示居民主要乘坐公共汽车上下班;y=0表示主要骑自行车上下班; + +自变量x1表示被调查者的年龄; + +x2表示被调查者的月收入; + +x3表示被调查者的性别(x3=1为男性,x3=0为女性) + +试建立y与自变量间的Logistic回归 + +TSL代码: + +```tsl +y := array(0.00, 0.00, 1.00, 1.00, 1.00, 0.00, 1.00, 1.00, 1.00, 0.00, 1.00, 1.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 1.00, 1.00); +x := `array((18, 21, 23, 23, 28, 31, 36, 42, 46, 48, 55, 56, 58, 18, 20, 25, 27, 28, 30, 32, 33, 33, 38, 41, 45, 48, 52, 56), (850, 1200, 850, 950, 1200, 850, 1500, 1000, 950, 1200, 1800, 2100, 1800, 850, 1000, 1200, 1300, 1500, 950, 1000, 1800, 1000, 1200, 1500, 1800, 1000, 1500, 1800), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); +constant := true; +alpha := 0.05; +return Regress_Logistic (y, x, constant, alpha); +``` + +["Coefficient"]: + +则logistics回归函数为11+e-(-3.65536889+0.08218454x0+0.00151704x1+2.50195582x2) + +["-2LogLikeHood"]: + +-2对数似然值是25.97065221,用来描述模型对因变量的预测能力。数值越大,预测越差。 + +["Wald Test"]: + +对每个变量的显著性检验 + +Wald-Stat:Wald统计量 + +Z-Stat:Wald统计量的平方根 + +P-Value:卡方检验p值,即接受零假设的临界值 + +Hypothesis:是否通过检验,0或1参考Regress_Binary Regress_CMLS Regression + +####### Regression + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.001, 0.564, 0.193, 0.809, 0.585, 0.48, 0.35, 0.896, 0.823, 0.747); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +// u作为变参返回 +return Regression(y, x, 0.05, 1); +``` + +参考Regress_CMLS Regress_RSquare Regress_AdjustedR2 Regress_FTest Regress_TTest +Regress_DWTest Regress_JBTest Regress_AicAndSbic + +####### Regress_DWTest + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +U := array(0.245863, 0.056726, -0.145411, -0.287547, -0.410684, 0.012821, 0.073042, 0.201905, 0.136768); +return Regress_DWTest(u); // 结果:0.7874 +``` + +参考Regress_CMLS Regression + +####### Regress_Stepwise + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +判断股票涨幅与各财务指标的相关系 + +```tsl +endt := inttodate(20100910); +stklist := GetBKByDate('sh000300', endt); +y := array(); +x := array(); +for i := 0 to length(stklist) - 1 do +begin + setsysparam(pn_stock(), Stklist[i]); + setsysparam(pn_date(), endt); + setsysparam(pn_rate(), 1); + RDate := NewReportDateOfEndT2(EndT); + y[i] := stockzf3(); + x[i][0] := Last12MData(RDate, 9900000); // 每股收益 + x[i][1] := Last12MData(RDate, 9900003); // 每股净资产 + x[i][2] := Last12MData(RDate, 9900100); // 净资产收益 + x[i][3] := Last12MData(RDate, 9900108); // 净利润率 + x[i][4] := Last12MData(RDate, 9900203); // 资产负债率 + x[i][5] := Last12MData(RDate, 9900004); // 净资产增长率 + x[i][6] := ln(StockMarketValue(EndT)); // 流通市值 +end; +return Regress_Stepwise(y, x, 0.05, 0.1); +``` + +ret["x"]:array(4,2) + +ret["regress"]:和[Regression]的输出结果是一样的格局参考Regression Regress_pri +Regress_Ridge Regress_VIF boxcox + +####### Regress_Constraint + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.425306623295765, 1.36119535984939, 0.330434097687351, 0.693363166256445, 1.12135794381143, 0.992864415538359, 0.599585222220468, 1.03157839185033, 0.817720425216125, 0.613581071515125); +x := array( (0.0437987553887069, 0.865901106735691, 0.637902588583529), +(0.991149639012292, 0.402538175228983, 0.830022667301819), (0.794031135737896, 0.866388283902779, 0.336671882774681), +(0.715198307996616, 0.416468291543424, 0.581486012088135), +(0.0273062069900334, 0.24702803301625, 0.983555873855948), +(0.529860897222534, 0.200076438020915, 0.59641290246509), +(0.813422230072319, 0.370269910665229, 0.23934360453859), +(0.888038919074461, 0.293901670724154, 0.613906089449301), +(0.311180313583463, 0.752806227421388, 0.332180465571582), +(0.31012851675041, 0.979520652908832, 0.346078625647351)); +constant := 1; // 包含常数项 +a := array(); +b := array(); +aeq := array((1, 1, 1)); // 加入等式约束,之和为 1.2 +beq := array(1.2); +alpha := 0.05; +option := 0; // 残差平方和最小 +lb := array(); +ub := array(); +return Regress_Constraint(y, x, constant, A, b, aeq, beq, alpha, option, lb, ub); +``` + +参考Regress_CMLS Regression Regress_NLM Regress_Binary + +####### Regress_White + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array(554.61, 562.47, 584.42, 587.43, 600.71, 622.9, 610.19, 624.33, 608.8, 584.74, 590.36, 601.76, 607.39, 617.27, 622.9, 621.8, 587.21, 575.07, 572.99, 569.38, 565.17, 560.42, 553.3); +y := array(1894.61, 1889.64, 1965.41, 2001.5, 2018.66, 2090.77, 2037.74, 2079.12, 2031.68, 1954.21, 1964.37, 1975.01, 1976.82, 2015.69, 2018.46, 1987.76, 1897.22, 1863.8, 1852.42, 1851.52, 1850.48, 1832.91, 1820.81); +z := array(64, 60, 60.1, 59.95, 61.5, 71.5, 70.5, 75.05, 77.5, 73.2, 75.3, 76.5, 78.2, 79.2, 78.8, 75.9, 73, 72.7, 72.7, 72.7, 73.85, 73.8, 73.6); +w := array(4.255, 4.235, 4.438, 4.534, 4.568, 4.768, 4.669, 4.792, 4.648, 4.47, 4.482, 4.548, 4.52, 4.622, 4.639, 4.552, 4.343, 4.276, 4.255, 4.25, 4.238, 4.191, 4.151); +xzw := `array(x, z, w); +alpha := 0.05; +return Regress_White(y, xzw, 0, alpha); +``` + +参考Regress_CMLS Regression + +####### Regress_MLS + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.001, 0.564, 0.193, 0.809, 0.585, 0.48, 0.35, 0.896, 0.823, 0.747); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +// u作为变参返回 +return Regress_MLS(y, x, u); +``` + +参考Regress_CMLS Regression Regress_QRlsq + +####### Regress_CMLS + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.001, 0.564, 0.193, 0.809, 0.585, 0.48, 0.35, 0.896, 0.823, 0.747); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +// u作为变参返回 +return Regress_CMLS(y, x, u, 1); +``` + +参考Regress_MLS Regression Regress_QRlsq + +####### Regress_JBTest + +范例 + +```tsl +Y := array(0.564, 0.693, 0.809, 0.985, 1.18, 1.896, 2.3, 2.747, 3); +return regress_jbtest(y, 0.05); +``` + +参考Regress_CMLS Regression Regress_FTest Regress_TTest + +####### Regress_pri + +范例 + +| 解释变量1 | 解释变量2 | 解释变量3 | 解释变量4 | 解释变量5 | 解释变量6 | +| --------- | --------- | --------- | --------- | --------- | --------- | +| 1.431 | 0.424 | 28.439 | 182.3 | 110.831 | -293.756 | +| 1.651 | 0.318 | 33.287 | 250.835 | 152.497 | -162.076 | +| 1.027 | 0.003 | 22.314 | 209.87 | 127.592 | -153.508 | +| 1.081 | 0.001 | 24.029 | 176.446 | 107.272 | -142.257 | +| 1.117 | 0.164 | 25.75 | 145.37 | 88.379 | -294.591 | +| 1.484 | 0.188 | 32.626 | 166.437 | 101.187 | -360.097 | +| 1.325 | 0.442 | 25.108 | 173.032 | 105.196 | -327.462 | +| 1.519 | 0.804 | 27.114 | 183.501 | 111.561 | -289.782 | +| 1.329 | 0.621 | 20.759 | 113.244 | 68.848 | -658.805 | +| 1.02 | 0.549 | 16.086 | 114.542 | 69.637 | -619.165 | +| 1.209 | 0.633 | 19.215 | 150.918 | 91.752 | -194.209 | +| 1.573 | 0.741 | 24.169 | 210.993 | 128.275 | -133.067 | +| 0.943 | 0.6 | 14.548 | 204.009 | 124.029 | -155.778 | +| 0.829 | 0.667 | 12.946 | 204.971 | 124.614 | -134.152 | +| 0.927 | 0.812 | 14.594 | 398.204 | 242.091 | -122.255 | +| 0.167 | 0.61 | 2.422 | 286.634 | 174.261 | -133.654 | +| -0.293 | 0.49 | -4.122 | 89.503 | 54.414 | -236.781 | +| -0.446 | 0.576 | -6.198 | -66.142 | -40.212 | -56.116 | +| -0.053 | 0.571 | -0.716 | 44.514 | 27.063 | 611.885 | +| -0.133 | 0.213 | -1.783 | -51.718 | -31.442 | -41.645 | +| -0.039 | 0.367 | -0.536 | -102.793 | -62.494 | -58.664 | +| 0.181 | 0.409 | 2.751 | -16.555 | -10.065 | -18.585 | +| 0.025 | 0.16 | 0.442 | -66.158 | -40.221 | -47.71 | +| -0.134 | 0.22 | -1.817 | -159.184 | -96.777 | -68.74 | +| 0.045 | 0.155 | 0.85 | -20.311 | -12.348 | -21.893 | +| 0.059 | 0.076 | 1.038 | -52.438 | -31.88 | -41.981 | +| -0.188 | 0.006 | -2.626 | -50.366 | -30.62 | -34.58 | +| 0.354 | 0.114 | 5.15 | 140.769 | 85.582 | -206.032 | +| 0.324 | -0.242 | 6.233 | 291.18 | 177.026 | -148.341 | + +| 解释变量7 | 解释变量8 | 解释变量9 | 解释变量10 | 解释变量11 | 被解释变量 | +| ---------- | --------- | --------- | ---------- | ---------- | ---------- | +| -576.35 | 3038.437 | 1847.244 | -8949.161 | -17558.29 | 0.6 | +| -282.297 | 3992.413 | 2427.222 | -6484.493 | -11294.439 | 0.667 | +| -418.446 | 2704.007 | 1643.925 | -4163.383 | -11348.898 | 0.812 | +| -1260.496 | 2281.625 | 1387.134 | -3257.498 | -28863.787 | 0.61 | +| 605.611 | 2095.182 | 1273.784 | -6196.863 | 12739.329 | 0.49 | +| 1117.915 | 2610.283 | 1586.944 | -9428.13 | 29269.472 | 0.576 | +| 2568.14 | 2626.929 | 1597.064 | -8628.615 | 67670.492 | 0.571 | +| -11379.056 | 2724.996 | 1656.685 | -7920.047 | -311001.92 | 0.213 | +| 185.692 | 1834.922 | 1115.557 | -12147.208 | 3423.841 | 0.367 | +| 233.605 | 1857.328 | 1129.179 | -11556.339 | 4360.099 | 0.409 | +| 9312.993 | 2205.132 | 1340.629 | -4298.943 | 206149.543 | 0.16 | +| -338.246 | 2781.867 | 1691.26 | -3712.606 | -9437.154 | 0.22 | +| -298.984 | 2363.908 | 1437.159 | -3695.792 | -7093.291 | 0.155 | +| -224.157 | 2133.811 | 1297.269 | -2874.695 | -4803.394 | 0.076 | +| -144.225 | 2633.445 | 1601.026 | -3230.017 | -3810.463 | 0.006 | +| -202.274 | 1925.562 | 1170.662 | -2588.069 | -3916.818 | 0.114 | +| 228.624 | 1661.155 | 1009.914 | -3992.523 | 3854.983 | -0.242 | +| -31.182 | 612.07 | 372.113 | -336.585 | -187.029 | -0.255 | +| 42.943 | 1629.952 | 990.943 | 10256.156 | 719.794 | -0.248 | +| -25.383 | 919.83 | 559.218 | -373.312 | -227.538 | -0.042 | +| -40.435 | 903.872 | 549.517 | -523.253 | -360.658 | -0.181 | +| -9.953 | 991.052 | 602.519 | -170.109 | -91.103 | -0.274 | +| -30.643 | 1038.49 | 631.359 | -485.897 | -312.083 | -0.169 | +| -52.728 | 856.257 | 520.569 | -583.427 | -447.526 | -0.11 | +| -12.573 | 1144.935 | 696.073 | -234.303 | -134.559 | -0.079 | +| -27.054 | 1138.099 | 691.917 | -465.796 | -300.176 | -0.025 | +| -25.356 | 1008.787 | 613.301 | -339.702 | -249.089 | 0.095 | +| -2097.228 | 1472.114 | 894.984 | -3061.924 | -31167.74 | 0.185 | +| -197.858 | 1757.787 | 1068.662 | -2622.88 | -3498.408 | 0.358 | + +return s:= regression(y,x,0.05,1); + +tr:=s["Coefficient"]; + +return x:\*(`(tr[1:length(tr)-1]))+tr[0] | y; + +预测效果图: + +R:=corr(x,1);//检验多重共线性 + +return regress_vif(X); + +array("VIF":(0.508,0.452,0.166,0.00,0.00,0.324,2.405, + +2.428,0.401,0.292,7.472),"Cond":INF) + +s:=regress_pri(y,x,0.85,0.05);//主成分回归 + +return s; + +tr:= s["Coefficient"]; + +return x:\*(`(tr[1:length(tr)-1]))+tr[0] | y; //主成分回归预测值与实际值的比较 + +主成分回归结果: + +参考Regression Regress_Ridge Regress_Stepwise Regress_VIF boxcox + +####### Regress_FTest + +范例 + +```tsl +U := array(0.245863, 0.056726, -0.145411, -0.287547, -0.410684, 0.012821, 0.073042, 0.201905, 0.136768); +Y := array(0.564, 0.693, 0.809, 0.985, 1.18, 1.896, 2.3, 2.747, 3); +return regress_FTest(y, u, 1, 0.05); +``` + +参考Regress_CMLS Regression Regress_RSquare Regress_AdjustedR2 Regress_TTest +Regress_JBTest + +####### Regression_WLS + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +加权最小二乘法算法说明: + +因变量y和自变量x长度都是n,假设满足最小二乘回归的经典假设时,y对x进行回归,形如: + +yi=β0+β1x1+β2x2+…+βkxk+μi,i=1,2,3,...,n + +用矩阵形式表示为: + +Y=Xβ+μ + +其中,ββ为系数矩阵,Y为因变量的n个观测值组成的n×1的列向量,X为一个n×(k+1)的矩阵。 + +一般的多元线性回归中,假设满足最小二乘回归的经典假设时,β系数的计算公式为: + +β=(X'X)-1 X'Y + +但是,当误差项μi存在异方差时,违反了经典假定中的同方差性的假定条件,加权离差平方和为: + +Qw=i=1nwi(yi-β0-β1x1-β2x2-…-βkxk)^2 + +其中,wi为给定的第i个观测值的权数,加权最小二乘法就是寻找β0,β1,β2,…,βkβ0,β1,β2,…βk的估计值使Qw达到最小,记: + +Wdiag=w1wn + +加权最小二乘估计WLS的矩阵可表达为 + +βw=(X'WdiagX)-1X'WdiagY范例 + +```tsl +Y := array(55.0, 65.0, 70.0, 80.0, 79.0, 84.0, 98.0, 95.0, 90.0, 75.0, 74.0, 110.0, 113.0, 125.0, 108.0, 115.0, 140.0, 120.0, 145.0, 130.0, 152.0, 144.0, 175.0, 180.0, 135.0, 140.0, 178.0, 191.0, 137.0, 189.0, 55.0, 70.0, 75.0, 65.0, 74.0, 80.0, 84.0, 79.0, 90.0, 98.0, 95.0, 108.0, 113.0, 110.0, 125.0, 115.0, 130.0, 135.0, 120.0, 140.0, 140.0, 152.0, 140.0, 137.0, 145.0, 175.0, 189.0, 180.0, 178.0, 191.0); +x := array((80.0), (100.0), (85.0), (110.0), (120.0), (115.0), (130.0), (140.0), (125.0), +(90.0), (105.0), (160.0), (150.0), (165.0), (145.0), (180.0), (225.0), (200.0), (240.0), +(185.0), (220.0), (210.0), (245.0), (260.0), (190.0), (205.0), (265.0), (270.0), (230.0), +(250.0), (80.0), (85.0), (90.0), (100.0), (105.0), (110.0), (115.0), (120.0), (125.0), +(130.0), (140.0), (145.0), (150.0), (160.0), (165.0), (180.0), (185.0), (190.0), (200.0), +(205.0), (210.0), (220.0), (225.0), (230.0), (240.0), (245.0), (250.0), (260.0), (265.0), +(270.0)); +wweight := 1 / (x[:, 0] ^ 1.5); +return Regression_WLS(Y, X, 0.05, 1, 1, nil, nil, nil, wweight); +``` + +####### Regress_Binary + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +在一次关于某城镇居民上下班使用交通工具的社会调查中,因变量y +=1表示居民主要乘坐公共汽车上下班;y=0表示主要骑自行车上下班;自变量x1表示被调查者的年龄;x2表示被调查者的月收入;x3表示被调查者的性别(x3=1为男性,x3=0为女性) + +| 交通工具 | 年龄 | 月收入 | 性别 | 交通工具 | 年龄 | 月收入 | 性别 | +| -------- | ---- | ------ | ---- | -------- | ---- | ------ | ---- | +| 0 | 18 | 850 | 0 | 0 | 20 | 1000 | 1 | +| 0 | 21 | 1200 | 0 | 0 | 25 | 1200 | 1 | +| 1 | 23 | 850 | 0 | 0 | 27 | 1300 | 1 | +| 1 | 23 | 950 | 0 | 0 | 28 | 1500 | 1 | +| 1 | 28 | 1200 | 0 | 1 | 30 | 950 | 1 | +| 0 | 31 | 850 | 0 | 0 | 32 | 1000 | 1 | +| 1 | 36 | 1500 | 0 | 0 | 33 | 1800 | 1 | +| 1 | 42 | 1000 | 0 | 0 | 33 | 1000 | 1 | +| 1 | 46 | 950 | 0 | 0 | 38 | 1200 | 1 | +| 0 | 48 | 1200 | 0 | 0 | 41 | 1500 | 1 | +| 1 | 55 | 1800 | 0 | 1 | 45 | 1800 | 1 | +| 1 | 56 | 2100 | 0 | 0 | 48 | 1000 | 1 | +| 1 | 58 | 1800 | 0 | 1 | 52 | 1500 | 1 | +| 0 | 18 | 850 | 1 | 1 | 56 | 1800 | 1 | + +使用极大似然法估计模型中的各个参数: + +```tsl +y := array(0.00, 0.00, 1.00, 1.00, 1.00, 0.00, 1.00, 1.00, 1.00, 0.00, 1.00, 1.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 0.00, 0.00, 0.00, 0.00, 1.00, 0.00, 1.00, 1.00); +x := `array((18, 21, 23, 23, 28, 31, 36, 42, 46, 48, 55, 56, 58, 18, 20, 25, 27, 28, 30, 32, 33, 33, 38, 41, 45, 48, 52, 56), (850, 1200, 850, 950, 1200, 850, 1500, 1000, 950, 1200, 1800, 2100, 1800, 850, 1000, 1200, 1300, 1500, 950, 1000, 1800, 1000, 1200, 1500, 1800, 1000, 1500, 1800), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); +constant := true; +alpha := 0.05; +ret := Regress_Binary(y, x, "logit", 3, constant, alpha); +``` + +下面我们继续看看样本内的误判率: + +```tsl +a := (ones(length(x))|x): * `ret["Coefficient"]; +a: := 1 / (1 + exp(-mcell)); +a := a[:, 0]; +a: := mcell >= 0.5; +// 预测值 +// return y|a; +b := y - a; +// 误判的为0或1 +b: := abs(mcell); +return sum(b) / length(b); +``` + +得到的结果: + +阈值设为0.5,误判率是0.17857参考Regress_CMLS Regression Regress_NLM + +####### Regress_TTest + +范例 + +```tsl +U := array(0.245863, 0.056726, -0.145411, -0.287547, -0.410684, -0.012821, 0.073042, 0.201905, 0.136768); +X := `array(1, 2, 3, 4, 5, 6, 7, 8, 9); +a := array(0.318137); +return regress_TTest(x, a, u, 0, 0.05, 0); +``` + +参考Regress_CMLS Regression Regress_JBTest Regress_FTest + +####### Regress_NLM + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +| 年份 | 消费价格指数CPI
X1(以1978年为100) | 人均可支配收入
X2(元) | 上年人均消费支出
X3(元) | 人均消费支出
Y(元) | +| ---- | -------------------------------------- | -------------------------- | ---------------------------- | ----------------------- | +| 1993 | 273.100 | 2577.400 | 1671.730 | 2110.810 | +| 1994 | 339.000 | 3496.200 | 2110.810 | 2851.340 | +| 1995 | 396.900 | 4283.000 | 2851.340 | 3537.570 | +| 1996 | 429.900 | 4838.900 | 3537.570 | 3919.470 | +| 1997 | 441.900 | 5160.300 | 3919.470 | 4185.640 | +| 1998 | 438.400 | 5425.100 | 4185.640 | 4331.600 | +| 1999 | 432.200 | 5854.020 | 4331.600 | 4615.900 | +| 2000 | 434.000 | 6280.000 | 4615.900 | 4998.000 | +| 2001 | 437.000 | 6859.600 | 4998.000 | 5309.000 | +| 2002 | 433.500 | 7702.800 | 5309.000 | 6029.880 | +| 2003 | 438.700 | 8472.200 | 6029.880 | 6510.940 | +| 2004 | 455.800 | 9421.600 | 6510.940 | 7182.100 | +| 2005 | 464.000 | 10493.000 | 7182.100 | 7942.880 | +| 2006 | 471.000 | 11759.500 | 7942.880 | 8696.550 | +| 2007 | 493.600 | 13785.800 | 8696.550 | 9997.470 | + +回归方程: + +Y1:=log(Y); + +X1:=log(X); + +return Regression(Y1,X1); + +注:根据Hypothesis,0表示显著,1表示不显著,则T检验最后一个变量通不过! + +return Regress_VIF(x1); // array("VIF":(7.83,66.409,95.241),"Cond":269.959) + +注:当VIF>10或Cond>30时,认为存在严重的多重共线性,第1,2个变量存在严重多重共线性,?第1,2个变量影响是相似的,则可以降维减少特征数量。 + +return Regress_Stepwise(Y1,X1,0.05,0.1)//逐步回归选取第0,1个解释变量 + +逐步回归结果: + +x:=x[:,0:1]; + +return Regress_NLM('Demo_Regress_NLM_CallBack',x,y,array(-0.2,0.2,0.8));或 + +return Regress_NLM('Demo_Regress_NLM_CallBack',x,y, array(-0.1,0.2,0.9)); + +其中Demo_Regress_NLM_CallBack函数 + +Function Demo_Regress_NLM_CallBack(beta,x); + +Begin + +return beta[0]_(x[0]^beta[1])_(x[1]^beta[2]); + +End; + +结果都是: + +估计参数残差序列雅克比矩阵(解释变量)可决系数拟合值拟合值和实际值的比较参考Regress_CMLS +Regression Regress_Binary + +####### Regress_WLS + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 对序列s跟gdp进行加权最小二乘法估计,权重数列为1/gdp// +s := array(2010.02, 1055.17, 2660.93, 919.23, 847.89, 1835.54, 898.45, 1322.37, 2409.39, 4808.67, 3467.46, 1310.3, 2119.58, 999.28, 4940.67, 2546.46, 1994.77, 1572.89, 4156.67, 877.93, 275.99, 990.05, 1976.68, 649.33, 887.49, 72.19, 1107.7, 538.62, 245.84, 245.22, 864.27); +gdp := array(3212.71, 2051.16, 6122.53, 2017.54, 1734.31, 5458.22, 2246.12, 3882.16, 5408.76, 10631.75, 7796, 3569.1, 4682.01, 2450.48, 10552.06, 6168.73, 4975.63, 4340.94, 11769.73, 2455.36, 604.13, 1971.3, 4875.12, 1185.04, 2232.32, 161.42, 2035.96, 1161.43, 341.11, 329.28, 1598.28); +w := 1 / (gdp); +// u作为变参返回 +return Regress_WLS(s, gdp, w, u); +``` + +参考Regress_CMLS Regression + +####### Regress_AicAndSbic + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +U := array(0.245863, 0.056726, -0.145411, -0.287547, -0.410684, 0.012821, 0.073042, 0.201905, 0.136768); +return Regress_AicAndSbic(u, 1, 9); +``` + +参考Regress_CMLS Regression + +####### Regress_RSquare + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +U := array(0.245863, 0.056726, -0.145411, -0.287547, -0.410684, -0.012821, 0.073042, 0.201905, 0.136768); +Y := array(0.564, 0.693, 0.809, 0.985, 1.18, 1.896, 2.3, 2.747, 3); +return Regress_RSquare(y, u); +// 结果:0.9421 +``` + +参考Regress_CMLS Regression Regress_AdjustedR2 + +####### Regress_QRlsq + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.564, 0.693, 0.809, 0.985, 1.18, 1.896, 2.3, 2.747, 3); +X := `array(1, 2, 3, 4, 5, 6, 7, 8, 9); +// u作为变参返回 +return Regress_QRlsq(y, x, u, 1); +``` + +参考Regress_CMLS Regression + +####### boxcox + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +data := rand(100); +return boxcox(data); +``` + +参考Regress_Stepwise Regress_pri Regress_Ridge Regress_VIF + +####### Regress_HettestSpearman + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +做y关于x的普通最小二乘回归,求出εi的估计值,即ei的值 + +取ei的绝对值,即|ei|,将xi与|ei|按递增或递减的次序排列并分等级 + +根据公式 rs=1-6n(n2-1)i=1ndi2 算出等级相关系数,其中n为样本量;di对应于xi与|ei|的等级差数 + +做等级相关系数的显著性检验。在n>8的情况下,用t=n-2rs1-rs对相关系数进行t检验,若|t|≤tα/2(n-2),则认为异方差问题不存在;否则说明xi与|ei|之间存在系统关系,异方差问题存在。范例 + +```tsl +y := array(49.00, 50.2, 50.5, 48.5, 47.5, 44.5, 28.00, 31.5, 34.5, 35.00, 38.00, 38.5, 15.00, 17.00, 20.5, 29.5); +x := array( +(1300.00, 7.5, 0.012, 9750.00, 15.6, 0.09), +(1300.00, 9.00, 0.012, 11700.00, 15.6, 0.108), +(1300.00, 11.00, 0.0115, 14300.00, 14.95, 0.1265), +(1300.00, 13.5, 0.013, 17550.00, 16.9, 0.1755), +(1300.00, 17.00, 0.0135, 22100.00, 17.55, 0.2295), +(1300.00, 23.00, 0.012, 29900.00, 15.6, 0.276), +(1200.00, 5.3, 0.04, 6360.00, 48.00, 0.212), +(1200.00, 7.5, 0.038, 9000.00, 45.6, 0.285), +(1200.00, 11.00, 0.032, 13200.00, 38.4, 0.352), +(1200.00, 13.5, 0.026, 16200.00, 31.2, 0.351), +(1200.00, 17.00, 0.034, 20400.00, 40.8, 0.578), +(1200.00, 23.00, 0.041, 27600.00, 49.2, 0.943), +(1100.00, 5.3, 0.084, 5830.00, 92.4, 0.4452), +(1100.00, 7.5, 0.098, 8250.00, 107.8, 0.735), +(1100.00, 11.00, 0.092, 12100.00, 101.2, 1.012), +(1100.00, 17.00, 0.086, 18700.00, 94.6, 1.462)); +alpha := 0.05; +constant := 0; +return Regress_HettestSpearman(y, X, alpha, constant); +``` + +| Statistic | 1.227706414781371 | +| ---------- | ------------------ | +| P-Value | 0.2398000476741131 | +| Hypothesis | 1 | + +####### Regress_VIF + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return Regress_VIF(rand(100, 10)); +``` + +参考Regress_Stepwise Regress_pri Regress_Ridge boxcox + +####### Regress_TTest_RWLS + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +算法OLS:普通最小二乘法回归,不需要给权重参数weight,不需要给约束参数restrictiveness + +WLS:加权最小二乘法回归,需要给权重参数weight,不需要给约束参数restrictiveness + +ROLS:线性约束的普通最小二乘法,不需要给权重参数weight,需要给约束参数restrictiveness + +RWLS:线性约束的加权最小二乘法,需要给权重参数weight,需要给约束参数restrictiveness范例 + +```tsl +x := rand(10, 3); +a := rand(3); +u := rand(10); +k := 3 - 1; +return Regress_TTest_RWLS(x, a, u, k, 0.05, 0); +``` + +####### Regress_TTest_White + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.001, 0.564, 0.193, 0.809, 0.585, 0.48, 0.35, 0.896, 0.823, 0.747); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +coe := Regress_CMLS(y, x, u, true, x0, Y0); // 最小二乘回归 +return Regress_TTest_White(x, coe, u, 0.05, true, V_OLS); +``` + +####### Regress_TTest_NW + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Y := array(0.001, 0.564, 0.193, 0.809, 0.585, 0.48, 0.35, 0.896, 0.823, 0.747); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +coe := Regress_CMLS(y, x, u, true, x0, Y0); // 最小二乘回归 +return Regress_TTest_NW(x, coe, u, 0.05, true, 2, V_OLS); +``` + +####### Regression_OLS_White + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.001, 0.56, 0.193, 0.80, 0.58, 0.48, 0.35, 0.89, 0.82, 0.74); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +return Regression_OLS_White(y, x); +``` + +####### Regression_OLS_NW + +范例 + +```tsl +y := array(0.001, 0.56, 0.193, 0.80, 0.58, 0.48, 0.35, 0.89, 0.82, 0.74); +X := array( +(0.174, 0.859), +(0.711, 0.514), +(0.304, 0.015), +(0.091, 0.364), +(0.147, 0.166), +(0.989, 0.446), +(0.119, 0.005), +(0.009, 0.378), +(0.532, 0.571), +(0.602, 0.607)); +return Regression_OLS_White(y, x); +``` + +####### NW_Adjustment_Simplification + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := array(0.001, 0.56, 0.193, 0.80, 0.58, 0.48, 0.35, 0.89, 0.82, 0.74); +return NW_Adjustment_Simplification(y); +``` + +####### Robustfit_M + +算法采用迭代加权最小二乘估计得到最优权重,使得偏差大的样本点权重小、偏差小的样本点权重大,从而降低异常点对于回归的影响。迭代过程如下: + +选取LS估计的β0=XTX-1XTY为迭代初始值,求出初始残差e=Y-Xβ0 + +残差标准化得到u,u=e/tune*s*sqrt1-h + +tune为默认调节常数 + +s为尺度因子,s=medianabse0-mediane00.6745 + +h为杠杆向量,H=X(XTX)-1XT,h为H的对角线元素 + +使用加权函数wfunx求出权重向量W,其第i个元素为wi=w(ui0) + +利用β=(XTWX)-1XTWY求得β(1)代替β(0),求得新残差e + +返回步骤(2),依次迭代计算β(i),当相邻两步的回归系数的差的绝对值的最大值小于预先设定的标准误差时,迭代结束,即max?β(i)-β(i-1)<ε范例 + +```tsl +x := 1 - > 100; +y := 3 * x + 100; +y[:5] := 1000; +return robustfit_M(y, x, 0.05, 1, 'andrews', 1.339); +``` + +####### Regress_GRStest + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 截距项矩阵alpha +Alpha := array((0.1288), (-0.0731), (0.0606), (-0.1398), (-0.2368)); +// 回归残差矩阵 +eps := array(( 0.2391, 2.8350, 0.1298, -0.1303, -0.4705), +( 0.3388, 0.8279, 0.8726, 1.0098, -0.1260), +( 1.2022, 0.7552, 0.1406, 0.9817, -0.5472), +(-1.2390, -0.8745, -0.8203, -0.7948, -0.9886), +(-0.1682, 0.3842, -0.1333, -0.0479, -0.5298), +( 0.4537, 0.2827, 0.4283, 0.5073, -0.0321), +(-0.6363, 0.3396, -0.4626, -0.2871, -0.5787), +( 0.3037, -0.9632, 0.0126, -0.0788, 0.9519), +( 1.6618, -1.7807, 0.2230, 0.6233, 1.4380), +(-0.2783, 0.4255, -0.3253, -0.2529, -1.0784)); +// 因子暴露矩阵 +mu := array(( 1.9006, 1.4588, -0.8829), +( 2.4169, 1.2151, -1.1462), +( 0.4599, 0.9646, -0.5166), +( 0.8420, 0.9289, 0.2966), +( 0.1703, -1.6531, 0.0567), +( 1.3330, 1.3360, -1.1067), +(-0.7639, -0.5524, 0.1642), +( 0.4294, -0.2513, 0.2316), +( 2.7809, 1.2122, -0.5281), +( 0.5903, 1.6501, -0.5097)); +return Regress_GRStest(alpha, eps, mu); +// array("FGRS":1.97496665,"pGRS":0.36939759) +``` + +###### 回归公用函数 + +####### 内容 + +- LeastSquares_CurveFitting + +####### LeastSquares_CurveFitting + +用途:回归相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +若Y中存在空值或者nan,去除F和Y相应位置上的值,然后两者进行矩阵的左除范例 + +```tsl +f := array((0.01, 0.49, 0.71), +(0.38, 0.54, 0.08), +(0.07, 0.74, 0.2), +(0.5, 0.97, 0.12), +(0.53, 0.45, 0.73)); +y := array(0.71, 0.3, 0.01, 0.05, 0.44); +return LeastSquares_CurveFitting(f, y); +// 结果: +``` + +###### 最小二乘法回归 + +####### 内容 + +- 单元回归 +- 多项式回归 +- 多元回归 + +####### 单元回归 + +######## 内容 + +- SingleRegression +- 中间函数 + +######## SingleRegression + +算法 + +采用字符串的方式调用CallBack函数得到F,利用最小二乘法进行回归得到系数矩阵范例 + +```tsl +x := array(0.00, 1.00, 2.00); +y := array(1.00, 2.00, 3); +CallBack := 'SingleLinearRegression_CallBack'; +return SingleRegression(x, y, CallBack); +// 结果: +``` + +######## 中间函数 + +######### 内容 + +- SingleLinearRegression_CallBack + +######### SingleLinearRegression_CallBack + +算法 + +返回第一项为1,第二项为对应位置X的数组范例 + +```tsl +x := array(0.00, 1.00, 2.00); +return SingleLinearRegression_CallBack(x); +// 结果: +``` + +####### 多项式回归 + +######## 内容 + +- PolynomialRegression + +######## PolynomialRegression + +算法 + +(1)计算每个X对应的由0到M为指数的指数函数值F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +x := array(0.00, 1.00, 2.00); +y := array(1.00, 2.00, 3); +return PolynomialRegression(x, y, 1); +// 结果: +``` + +####### 多元回归 + +######## 内容 + +- MultipleRegression +- 中间函数 + +######## MultipleRegression + +算法 + +采用字符串的方式调用CallBack函数得到F,运用最小二乘法进行回归得到系数矩阵范例 + +```tsl +x := array((0.00, 0.00), (0.00, 1.00), (1.00, 0.00), (1.00, 1.00)); +y := array(1.00, 2.00, 2.00, 3.00); +CallBack := 'MultipleRegression_CallBack'; +return MultipleRegression(x, y, CallBack); +// 结果: +``` + +######## 中间函数 + +######### 内容 + +- LnRegression_CallBack +- MultipleRegression_CallBack + +######### LnRegression_CallBack + +算法 + +返回第一项为1,若X中元素小于等于0,其余项对应位置为0,否则其余项对应位置为X中取自然对数后的值的数组范例 + +```tsl +x := array((0.00, 0.00), (0.00, 1.00), (1.00, 2.00), (2.00, 1.00)); +return LnRegression_CallBack(x); +// 结果: +``` + +######### MultipleRegression_CallBack + +算法 + +返回第一项为1,其余项为对应位置X的取值的数组范例 + +```tsl +x := array((0.00, 0.00), (0.00, 1.00), (1.00, 2.00), (2.00, 1.00)); +return MultipleRegression_CallBack(x); +// 结果: +``` + +###### 测试 + +####### 内容 + +- 最小二乘法回归 + +####### 最小二乘法回归 + +######## 内容 + +- 单元回归 +- 多项式回归 +- 多元回归 + +######## 单元回归 + +######### 内容 + +- SingleUnLineralRegression_Pgm +- SingleLineralRegression_Pgm +- 中间函数 + +######### SingleUnLineralRegression_Pgm + +算法 + +(1)采用字符串的方式调用函数得到F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +X := array(0.00, 0.5, 2.00, -2.00); +Y := array(1.00, 1.625, 40, -39); +return SingleUnLineralRegression_Pgm(X, Y); +// 结果: +``` + +######### SingleLineralRegression_Pgm + +算法 + +(1)采用字符串的方式调用函数得到F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +X := array(1.00, -5.00, 6.00); +Y := array(7.00, -5.00, 17.00); +return SingleLineralRegression_Pgm(X, Y); +// 结果: +``` + +######### 中间函数 + +########## 内容 + +- SingleUnLineralRegression_CallBack + +########## SingleUnLineralRegression_CallBack + +算法 + +计算X^3的数值范例 + +```tsl +X := array(1.00, -5.00, 6.00); +return SingleUnLineralRegression_CallBack(X); +// 结果: +``` + +######## 多项式回归 + +######### 内容 + +- PolynomialRegression_Pgm + +######### PolynomialRegression_Pgm + +算法 + +(1)计算每个X对应的由0到M为指数的指数函数值F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +X := array(0.5, 1, 1.5, 2, 2.5, 3); +Y := array(1.71, 2.45, 3.81, 4.8, 7, 8.6); +return PolynomialRegression_Pgm(X, y, 2); +// 结果: +``` + +######## 多元回归 + +######### 内容 + +- MultipleRegression_Pgm +- MultipleUnLinearRegression_Pgm +- 中间函数 + +######### MultipleRegression_Pgm + +算法 + +(1)采用字符串的方式调用函数得到F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +X := array((5960, 44967, 1873), +(9000, 27860, 928), +(9500, 31439, 1126), +(10000, 39592, 1265), +(18000, 72827, 2214), +(8500, 27317, 912), +(8000, 29856, 899), +(23000, 47752, 1803), +(8100, 39117, 1204), +(9000, 29349, 1725), +(7300, 40116, 1080), +(8000, 31679, 1529), +(20000, 58510, 2455), +(8000, 23454, 1151), +(8000, 20897, 1173), +(10500, 56248, 1960), +(4000, 20859, 1344), +(4500, 22610, 988), +(3400, 35948, 1076), +(1500, 5779, 962)); +Y := array(68900, 48500, 55500, 62000, 116500, 45000, 38000, 83000, 59000, 47500, 40500, 40000, +97000, 45500, 40900, 80000, 56000, 37000, 50000, 22400); +return MultipleRegression_Pgm(X, Y); +// 结果: +``` + +######### MultipleUnLinearRegression_Pgm + +算法 + +(1)采用字符串的方式调用函数得到F; + +(2)运用最小二乘方法进行回归得到系数矩阵;范例 + +```tsl +X := array((15.2, 2.6), +(13.9, 2.14), +(15.8, 1.52), +(12.8, 3.12), +(6.9, 2.48), +(14.6, 3.08), +(15.4, 2.92), +(17.3, 2.76), +(13.7, 2.36), +(12.7, 2.36), +(15.3, 2.56), +(15.2, 2.8), +(12.00, 2.72), +(15.3, 1.92), +(13.7, 1.92), +(13.3, 1.6)); +Y := array(25, 20, 15, 34, 20, 33, 28, 30, 23, 24, 25, 26, 26, 20, 20, 13); +CallBack := 'MultiUnLineralRegression_CallBack'; +return MultipleUnLinearRegression_Pgm(X, Y, CallBack); +// 结果: +``` + +######### 中间函数 + +########## 内容 + +- MultiUnLineralRegression_CallBack + +########## MultiUnLineralRegression_CallBack + +算法 + +返回第一项为常数,第二项为X1,第二项为X2,第三项为X1\*X2的数组范例 + +```tsl +X := array((15.2, 2.6), +(13.9, 2.14), +(15.8, 1.52), +(12.8, 3.12), +(6.9, 2.48), +(14.6, 3.08), +(15.4, 2.92), +(17.3, 2.76), +(13.7, 2.36), +(12.7, 2.36), +(15.3, 2.56), +(15.2, 2.8), +(12.00, 2.72), +(15.3, 1.92), +(13.7, 1.92), +(13.3, 1.6)); +return MultiUnLineralRegression_CallBack(X); +// 结果: +``` + +##### 灰色系统 + +###### 内容 + +- GM_Initial +- GM_Corr +- GM_AGO +- GM_Icorr +- GM_Scorr + +###### GM_Initial + +用途:灰色系统相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +初值化:代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +un := array(); +return GM_Initial(x, "ini", un); +``` + +均值化: + +TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +un := array(); +return GM_Initial(x, "mean", un); +``` + +按行区间值化 + +TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +un := array(); +return GM_Initial(x, "rrange", un); +``` + +归一化 + +TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +un := array(1, 2); +return GM_Initial(x, "norm", un); +``` + +参考GM_Corr GM_AGO GM_Icorr GM_Scorr GM_Estimate + +###### GM_Corr + +用途:灰色系统相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +return GM_Corr(x, 0); +``` + +参考GM_Initial GM_AGO GM_Icorr GM_Scorr GM_Estimate + +###### GM_AGO + +用途:灰色系统相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +TSL代码如下 + +```tsl +x := array(1, 2, 3, 4); +return GM_AGO(x, "add", 2); +``` + +2. TSL代码如下 + +```tsl +x := array(1, 2, 3, 4); +return GM_AGO(x, "sub", 2); +``` + +参考GM_Initial GM_Corr GM_Icorr GM_Scorr GM_Estimate + +###### GM_Icorr + +用途:灰色系统相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +return GM_Icorr(x, 1); +``` + +参考GM_Initial GM_Corr GM_AGO GM_Scorr GM_Estimate + +###### GM_Scorr + +用途:灰色系统相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +灰色绝对关联度: TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +return GM_Scorr(x, "abs"); +``` + +灰色相对关联度: TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +return GM_Scorr(x, "ret"); +``` + +灰色综合关联度: TSL代码如下 + +```tsl +x := array((1, 2, 3), (2, 3, 4)); +return GM_Scorr(x, "com"); +``` + +参考GM_Initial GM_Corr GM_AGO GM_Icorr GM_Estimate + +##### 主成分分析 + +###### 内容 + +- PrincaipalComponentAnalysis +- 中间函数 + +###### PrincaipalComponentAnalysis + +用途:主成分分析相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +将Zt标准化得到zT_s,然后进行转置获得新的数组Z,根据数组Z获得相关系数矩阵R,根据数组R获得特征值和特征向量,获得载荷矩阵Cm,对其进行旋转得到RM,根据R和RM获得因子得分系数矩阵Cs,根据Cs和zT_s获得样本公共因子得分矩阵Farr,根据Farr和主因子对应的特征根获得主因子及其得分范例 + +```tsl +// 设置样本矩阵 +zt := array((0.7592, 1.7593, 21.9279, 48.5626, 55.1679), +(0.0490, 0.4457, 2.2255, 82.2658, 192.4348), +(-2.2313, -1.3096, -59.8883, 3.9922, -80.2419), +(0.1364, 0.539, 4.3910, 55.1438, 46.0612), +(0.7233, 1.9467, 15.6127, 111.3018, 58.3969)); +return PrincaipalComponentAnalysis(zt); +// 结果: +``` + +###### 中间函数 + +####### 内容 + +- Mbbub +- ComponentScoreMatrix +- FactorScoreMatrix +- Eastrq +- ComponentMatrix +- RotatedComponentMatrix +- Eigen_Jacobi +- GetEigenValue +- FScoreResult + +####### Mbbub + +算法 + +获取n=数组p的长度,k=0,m=n-1; + +从nI=0到m-1进行循环,将nI的值赋值给数组z对应下标为nI的值,当kepsi,r = r / c,否则结束;返回xN; + +###### 无约束优化算法 + +####### 内容 + +- Hooke_Jeeves_Method + +####### Hooke_Jeeves_Method + +算法 + +(1)N=数组X0的长度,X0的值赋值给X,X的值赋值给Y,将D0赋值给Dt,采用字符串的方式调用TZZHCallBack函数得到函数初始值F0,并赋值给Fy; + +(2)把Y的值赋值给X,Fy赋值给Fs; + +# (3)从nI=0到N-1进行循环,将X和Dt对应位置数据相加得到新的数组X,调用TZZHCallBack函数得到函数值Fx;若Fx0,则v=v1/v2;否则,v=0; + +若v1<0,且v2<0,则v=-v; + +返回v。范例 + +```tsl +// 返回-1与-2的比率。 +return RatioValue(-1, -2); +// 结果:-0.5 +``` + +###### OutPutValueByUnit + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +若DataType\_="Real",则v=Data/DataUnit; + +若DataType\_<>"Real",则v=Data; + +返回v。范例 + +```tsl +// 返回1234.5以10为单位转换后的结果 +return OutPutValueByUnit(1234.5, 'Real', 10); +// 结果:123.45 +``` + +###### OutPutLnGrowRatio + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1>0且v2>0,返回(v1的自然对数 - v2的自然对数)\*100; + +否则,返回0。范例 + +```tsl +// 取3与4的对数增长率 +return OutPutLnGrowRatio(3, 4); +// 结果:-28.77 +``` + +###### OutPutGrowValue + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1与v2都为实数,返回v1-v2; + +否则,返回0。范例 + +```tsl +// 返回13与14的差值 +return OutPutGrowValue(13, 14); +// 结果:-1 +``` + +###### OutPutGrowValue2 + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1与v2都为不等于0的实数,返回v1-v2; + +否则,返回0。范例 + +```tsl +// 返回13与14差值 +return OutPutGrowValue2(13, 14); +// 结果:-1 +``` + +###### OutPutGrowRatio + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1与v2都为不等于0的实数,返回(v1-v2)/v2的绝对值\*100; + +否则,返回0。范例 + +```tsl +// 返回13到14的增长率(%) +return OutPutGrowRatio(14, 13); +// 结果:7.69 +``` + +###### OutPutGrowRatio2 + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +若v1与v2都为不等于0的实数,返回(v1-v2)/v2的绝对值\*100; + +若v1与v2其中有一个为0,返回"-"; + +否则,返回0。范例 + +```tsl +// 返回13到14的增长率(%) +return OutPutGrowRatio2(14, 13); +// 结果:7.69 +``` + +###### MultyValue + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法 + +若v1与v2都是实数,则v=v1\*v2;否则,v=0; + +若v1<0,且v2<0,则v=-v; + +返回v。范例 + +```tsl +// 返回取-3与-5的乘积。 +return MultyValue(-3, -5); +// 结果:-15 +``` + +###### OutPutGrowValue3 + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1与v2都为大于等于0的实数,返回v1-v2; + +否则,返回空字符串。范例 + +```tsl +// 返回13与14的差值 +return OutPutGrowValue3(13, 14); +// 结果:-1 +``` + +###### OutPutGrowRatio3 + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +算法若v1与v2都为实数,且v2>0,返回(v1-v2)/v2的绝对值\*100; + +否则,返回空字符串。范例 + +```tsl +// 返回14到13的增长率(%) +return OutPutGrowRatio3(14, 13); +// 结果:7.69 +``` + +###### RatioValue_Math + +用途:增长率与比率相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return RatioValue_Math(0, 0); +// 结果:0 +``` + +##### 概率分布 + +###### 内容 + +- 线性变换 + +###### 线性变换 + +####### 内容 + +- Norm_LinearTransform + +####### Norm_LinearTransform + +用途:概率分布相关函数。 +参数: + +返回:处理后的结果值。 + +算法假设随机变量X服从正态分布,其线性组合Y依然服从正态分布 + +(1)X、Y为单个变量,X~N(μ,σ2),μ与σ2为实数,Y=a+bX,则 + +EY=a+bμ + +DY=b2σ2 + +(2)X、Y为多元变量,假设 + +X=X1,X2,?,XnT~Nμ,Σ , μ=μ1,μ2,?,μnT, Σ=var(X1)cov(X1,Xn)cov(X1,Xn)var(Xn) + +Y=Y1Ym=a1+b11*X1+b12*X2+?+b1n*Xnam+bm1*X1+bm2*X2+?+bmn*Xn=A+B\*X + +其中,A=a1am, B=b11b1nbm1bmn,则 + +EY=A+Bμ + +DY=BΣBT范例 + +范例01: + +```tsl +A := 1.5; +B := 2; +Mu := 1; +Sigma := 10; +return Norm_LinearTransform(Mu, Sigma, A, B); +``` + +范例2: + +```tsl +A := array(1.5, 1.5, 1.5); +B := array((1, 1, 1), (2, 2, 2), (3, 3, 3)); +Mu := array(1, 2, 3); +Mu := `Mu; +sigma := array((0.5, 3, 1), (0.2, 1, 0.4), (3, 0.1, 2)); +return Norm_LinearTransform(Mu, Sigma, A, B); +``` + +array( + +"变换后均值":((7.5),(13.5),(19.5)), + +"变换后方差": + +((11.2,22.4,33.6),(22.4,44.8,67.2),(33.6,67.2,100.8))); + +##### 信号处理 + +###### 内容 + +- filter_hp + +###### filter_hp + +用途:信号处理相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +y := MarketTradeDayQk(20220101T, 20220131T); +return filter_hp(y, 10); +``` diff --git a/data/tsl_reference_catalog_source/platform.md b/data/tsl_reference_catalog_source/platform.md new file mode 100644 index 00000000..de776da7 --- /dev/null +++ b/data/tsl_reference_catalog_source/platform.md @@ -0,0 +1,560 @@ +#### 平台函数 + +##### 内容 + +- 自有数据维护函数 +- 平台函数简介 +- 平台执行信息 +- 用户和函数相关函数 +- 平台与客户端交互函数 + +##### 自有数据维护函数 + +###### 内容 + +- LoadTableEx +- UserDB +- LoadTable +- SaveTable +- TestTable +- SaveBk +- DeleteBk +- ListTable +- DeleteTable + +###### LoadTableEx + +用途:自有数据维护函数相关函数。 +参数:arg1(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +return LoadTableEx('repitle'); +``` + +返回:repitle为保存好的用户数据 + +###### UserDB + +####### 内容 + +- UserDataUpLoad +- HexToString +- TransFileName + +####### UserDataUpLoad + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// dir为用户本地用户数据的存贮目录 +Filedir := 'C:\\Users\\xxxx\\Tinysoft\\Analyse.NET\\D254A848\\xxx\\UserDB\\hex_74657374646174613031.stm'; +return UserDataUpLoad(Filedir); // 返回上传结果提示信息。 +``` + +####### HexToString + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +// 将用户数据名转化为可读串 +str := 'hex_74657374646174613031.stm'; +return HexToString(str); // 返回testdata01 +``` + +####### TransFileName + +用途:自有数据维护函数相关函数。 +参数: + +返回:整数。 + +范例 + +```tsl +// 获取本地用户数据列表 +dir := 'C:\\Users\\xxxx\\Tinysoft\\Analyse.NET\\D254A848\\xxx\\UserDB'; +return TransFileName(dir); // 返回用户数据列表 +``` + +###### LoadTable + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 将savetable范例中保存的用户数据testA提取出来 +return LoadTable('testA'); +``` + +参考TestTable SaveTable ListTable DeleteTable + +###### SaveTable + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +注意: + +在保存用户数据的时候可以分目录保存,只需在目录层次间添加‘\\’即可;在不同的目录下可以将数据保存为相同的数据名称。 + +另外,该目录的分类方法在左上角工具栏中的“数据”可查看到分类,但是在资源管理器中,只以"目录名\数据表名"显示 + +范例 + +范例一:直接在根目录下保存 + +```tsl +// 将r保存为用户数据testA +r := rand(10, 10); +return SaveTable('testA', r); +// 结果:-1 +``` + +范例二:保存到指定目录下 + +```tsl +// 将生成的10行10列的随机数据保存到目录:mydata\目录下,保存 +// 文件名称为testA +r := rand(10, 10); +ret := SaveTable('mydata\\testA', r); +return ret; +// 结果:-1 +``` + +用户数据的查看: + +用户可以在左上角菜单栏的‘数据’中查看保存的数据,如果保存后即时查看,服务器还没有把数据推送到客户端,用户需要主动查询用户数据,点击左上角菜单栏‘系统’->‘检查用户数据’,右下角弹出最新更新的用户数据后,再点击菜单栏‘数据’,即可看到刚刚存入的数据。 + +范例三:新旧流格式数据保存操作及结果对比,在新版客户端+下一代服务器下执行以下操作 + +```tsl +t := getdatademo(); // 返回一个数组--测试者数据举例 +r1 := SaveTable("TestSTData01", t); // 缺省情况下保存用户数据 +r2 := SaveTable("TestSTData02", t, 0); // 指定保存为原始流格式 +r3 := SaveTable("TestSTData03", t, 1); // 指定保存为新流格式 +return array(r1, r2, r3); +``` + +保存后,用户数据中列表大小显示如下:新流格式数据大小为源始流格式的55%,数据大小有明显的变小 + +关于新流格式: + +新一代客户端上传用户数据采用快速流,为了客户端保持和古旧的平台的兼容性,原有客户端上传的数据依旧采用原始流模式。 + +如果同时使用老旧的客户端(2020年6月之前的版本)和新的客户端,老旧客户端无法处理新的流模式。 + +新版本的执行返回结果集使用用的是快速流格式,快速流模式空间需求小,且加载效率快300%。 + +参考TestTable LoadTable ListTable DeleteTable + +###### TestTable + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return TestTable('testA'); // 测试用户数据"testA"是否存在。返回值为1,即存在,0即不存在。 +``` + +参考SaveTable LoadTable ListTable DeleteTable + +###### SaveBk + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +SaveBk("MySector", "我的一级分类\\我的二级分类", array("SZ000001", "SZ000002")); +{在"我的一级分类\\我的二级分类"目录生成一个名为"MySector "的板块,该板块的成分为SZ000001,SZ000002} +``` + +参考DeleteBk + +###### DeleteBk + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +DeleteBk("MySector"); +``` + +参考SaveBk +http://www.tinysoft.com.cn/TSDN/HelpDoc/SearchContent.tsl?r=ref&KeyWord= + +###### ListTable + +用途:自有数据维护函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return ListTable(); +``` + +结果如下: + +参考TestTable SaveTable LoadTable DeleteTable + +###### DeleteTable + +用途:自有数据维护函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一:删除指定目录下的用户数据 + +```tsl +// 删除存在目录:“mydata\目录下”的用户数据testA +ret := DeleteTable('mydata\\testA'); +return ret; +// 结果:-1 +``` + +范例二:删除同一规则命名的用户数据 + +```tsl +// 删除存在目录:“mydata\目录下”以test开头命名的用户数据 +data := listTable(); +for i := 0 to length(data) - 1 do +begin + if pos('mydata\\test', data[i]) > 0 then + begin + DeleteTable(data[i]); + end; +end; +return listtable(); +``` + +参考TestTable SaveTable LoadTable ListTable + +##### 平台函数简介 + +平台函数指天软金融分析.NET平台专用函数(证券相关等函数也是平台专用函数) + +##### 平台执行信息 + +###### 内容 + +- TSCanGrid +- Isbackground +- tsAppServer +- TsAppServerName +- SendToClient +- TS_ModuleInfo + +###### TSCanGrid + +###### Isbackground + +###### tsAppServer + +用途:平台执行信息相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +a := rand(10, 10); +return tsAppServer(); +// 结果:192.168.101.45:3328(Z:\server\bin5) +``` + +###### TsAppServerName + +用途:平台执行信息相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return TsAppServerName(); +``` + +结果:192.168.101.26:z:\server\bin\exec64.exe + +###### SendToClient + +用途:平台执行信息相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 1)执行命令:return 100+1 +return SendToClient("getdo", "return 100 + 1;", nil, nil); +// 结果:101 +// 2)采用系统参数取得数据,将取得的数据相加,并设置超时时间为30s +return SendToClient("getdo", "return getsysparam('a') + getsysparam('b');", nil, array("a":10, "b":30), 30); +// 结果:40 +``` + +参考平台和客户端交互。 + +###### TS_ModuleInfo + +用途:平台执行信息相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return TS_ModuleInfo(); +``` + +差异说明Windows:任何版本。 + +Linux:自2024-07-10之后的版本,开始支持;之前的版本不支持。 + +##### 用户和函数相关函数 + +###### 内容 + +- User +- UserName +- FunctionType +- FunctionName +- FunctionVer +- UserConfig +- SetUID +- SUDO + +###### User + +用途:用户和函数相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 执行用户jrtzsupport 共享的大师策略的函数Show_DSXG_211 +begt := inttodate(20130101); +endt := inttodate(20140101); +return User('jrtzsupport').Show_DSXG_211(begt, endt, 0); +``` + +参考SYSTEM + +###### UserName + +###### FunctionType + +参考FunctionName FunctionVer + +###### FunctionName + +参考FunctionType FunctionVer + +###### FunctionVer + +参考FunctionType FunctionName + +###### UserConfig + +###### SetUID + +###### SUDO + +##### 平台与客户端交互函数 + +###### 内容 + +- 在平台模型运行时打印信息到客户端/Web端 +- 平台模型远程调用客户端函数,访问客户端的资源 +- SendToClient提供调用本地命令 + +###### 在平台模型运行时打印信息到客户端/Web端 + +在运行平台模型的时候,为了调试方便,也为了监控模型的正常运行,往往需要知道模型运行的状态,这样我们需要在模型运行过程中输出一些信息到终端,而不是等待模型执行完毕得到最终结果。 + +这就需要使用打印信息到客户端的功能。 + +我们看一个案例,这个案例就是获得每个股票的Beta值: + +```tsl +Stks := GetBk("深证A股;上证A股"); +Result := array(); +for i := 0 to length(Stks) - 1 do +begin + SetSysParam(pn_Stock(), Stks[i]); + Result[i]["StockID"] := Stks[i]; + Result[i]["Beta"] := StockBeta4("SH000300", 10); // 最近一年的Beta + Echo Result[i]["StockID"], "->", Result[i]["Beta"]; +end; +return Result; +``` + +由于调用Beta的时候,计算效率会稍微低,我们利用Echo把当前运行的信息打印到了客户端,客户端的窗口内容如下: + +利用这样的方法,我们就可以实时知道当前模型运行的状况了。我们在很多地方可以用到这个功能,例如我们可以简单地打印几个时间或者运行的时间长短来知道运行的效率。 + +对于运行中间得到的结果是一个复杂结果的,例如数组等内容,那么就没办法直接Echo这个结果,这就要结合tostn函数来输出调试了。 + +```tsl +Stks := GetBk("深证A股;上证A股"); +Result := array(); +for i := 0 to length(Stks) - 1 do +begin + SetSysParam(pn_Stock(), Stks[i]); + Result[i]["StockID"] := Stks[i]; + Result[i]["Beta"] := StockBeta4("SH000300", 10); // 最近一年的Beta + Echo tostn(Result); +end; +return Result; +``` + +每一行的内容会显示在右边部分,这个时候我们可以利用转换数据按钮把字符串以数据的方式来显示。 + +除了Echo以外,我们还可以利用Writeln或者Write函数来输出这些内容。 + +当我们不是在终端上运行这些模型,而是在WEB端或者独立解释器里调用运行这个模型,信息会直接输出到浏览器或者控制台中。 + +参考:echo + +###### 平台模型远程调用客户端函数,访问客户端的资源 + +我们在使用平台模型的时候,经常有需要要访问客户端本地资源。打个比方,我们需要导出计算的数据,而等待整个模型的返回特别长,所以可能我们需要边运行,边导出数据。又或者整个的数据结果集非常大,无法单次返回,需要分开成小结果集运行时导出到客户端,而导出数据可以通过ExecSql输出到数据库,也可以是通过ExportFile来导出文件,我们还可以通过WriteFile等文件读写函数来直接操作文件。以及通过封装好的系统或者用户写的TSL函数。 + +平台提供了两个关键字RDo和RDo2来解决这个问题。RDo和RDo2可以在平台运行模型的时候远端调用客户端的函数运行。 + +例如:我们在运行的时候要导出一组股票的交易明细数据到客户机上。 + +```tsl +Stks := GetBK("深证A股;上证A股"); +Day := Today(); +for i := 0 to length(Stks) - 1 do +begin + SetSysParam(pn_Stock(), Stks[i]); + if not isTradeDay(Day) then continue; // 如果没有交易则下一个 + Data := select DateTimeToStr(["date"]) as"Time", ["close"], ["vol"] from tradetable DateKey Day to Day + 1 of Stks[i] where ["vol"] > 0 end; // 取出时间,收盘价,成交量 + RDo2 + ExportFile(ftCSV(), "", "C:\\DataStore\\" + IntToStr(DateToInt(Day)) + "\\" + Stks[i] + ".csv", Data); // 导出数据 +end; +``` + +以上代码为将上证和深证A股的当天的交易明细导出到本地。ExportFile是一个导出的函数,但是在平台上运行的时候导出到的位置是在服务器上,而且需要在服务器上设置权限。而用RDo2则使导出命令在客户端上运行,所以输出会在客户端本地。 + +由于要对本地文件进行读写,或者调用本地的其他资源,终端为了安全起见,默认禁止了这类远端调用,于是系统左上角会出现如下界面: + +系统还会终止模型的运行并且返回出错信息。 + +用户可以通过菜单进入系统设置,也可以点击进入系统信任中心,界面如下: + +信任中心的初始是最高安全性,禁止了远程模型对本地资源的访问。如果我们只需要导出数据到本地或者执行本地的数据库查询语句,那么我们可以选择高安全性,高安全性允许RDO/RDO2执行的函数是ExportFile和ExecSQL。 + +如果我们还需要从本地导入数据,调用ImportFile函数,则应该设置为中安全性。低安全性则是允许RDo/RDo2调用任何本地函数。而最低安全性则还允许使用SendToClient函数用”do”或者”getdo”命令组成命令串执行,这就可以不需要把命令串封装成函数来执行。 + +如果信任中心拒绝了调用,系统会自动禁止该调用,并且会有一个禁止掉的提示小窗口。而当信任中心允许调用的时候,如果用户没有进行许可设置,系统依旧会对远程模型的本地资源调用进行安全提示。 + +我们可以信任某个用户来源的所有的函数的调用,也可以信任该来源函数的调用,还可以仅仅信任该调用(例如信任导出的调用必须导出的文件名都是一致的),我们还可以临时允许该调用或者拒绝该调用。这样下次当调用发生的时候,该信任管理窗口依旧会出现。 + +对于导入和导出的调用,还有一个信任路径的设置。当设置了信任路径以后,在该信任路径下以及该路径下的子目录下的所有导入/导出命令将会被允许而不再提示。 + +无论是拒绝还是信任了,在运行信息中总是会显示收到的命令。此外,对于已经设置了信任的调用方式,如果用户需要修改,可以进入系统设置中,打开信任配置文件来修改INI文件,找到相应项目删除掉就可以了。 + +RDo和RDo2的差异在于RDo2会返回函数的执行结果,因此RDo2是同步执行的方式,一定会等待客户端执行完毕才返回。而RDo则是不返回结果,直接把命令提交给客户端处理,至于执行的正确与否,RDo是不理会的,会出现模型执行完毕了,而客户端的命令仍然在排队执行的情况。 + +在绝大多数情况下,RDo2会更安全可靠,但是RDo的效率有时候会更高。但是平台会约束RDo送回到客户端的内容的带宽,并且系统也无法保障RDo的执行是否是正确的。 + +而且有些函数是必须用RDo2的,例如ImportFile,因为不用RDo2,该调用毫无意义。而ExportFile,ExecSQL的调用,有点却不一定需要等待返回,所以也可以采用RDo,但是我们依旧推荐用户使用RDo2,除非用户确实需要使用RDo。 + +如果RDo2所调用的函数使用了系统参数(客户端执行的函数并不多见),则可以使用With关键字把系统参数带进去。 + +例如A:=RDo2 LocalFunctionTest() with array("abcd":123,"bcd":234); + +而LocalFunctiontest函数的内容则为: + +Return GetSysParam("abcd")+GetSysParam("bcd"); + +则返回的结果是357 + +RDo2调用的默认是300秒超时的,也就是说默认情况下当客户端未能在300秒内处理完请求(包括客户端无人响应确认),系统会抛出超时的异常。 + +如果需要设置超时的时间,可以用TimeOut来设置超时,例如RDo2 +ImportFile(ftCsv(),"","C:\\1.csv",Data) TimeOut 30; +调用ImportFile函数的超时时间为30秒。 + +参考:RDo,RDo2 + +###### SendToClient提供调用本地命令 + +RDo和RDo2提供了调用本地函数的功能,但是有时候一个计算不一定要用函数,例如:执行一个1+1的操作。这类需求利用SendToClient可以完成。 + +SendToClient提供了很灵活的调用方法,事实上RDo,RDo2也是通过SendToClient函数来实现的。SendToClient实现了如下命令: + +echo 显示信息 + +import 导入 + +export 导出 + +rdo 远程调用 + +rdo2 远程调用并返回 + +do 远程执行命令串 + +getdo 远程执行命令串并返回 + +由于echo命令、import、export、rdo、rdo2命令在之前都有相应的简单的替代方案,因此,我们就只讲do、getdo命令的使用。 + +例如,我们要用本地计算一个1+1的值,我们可以采用如下方法: + +Return SendToClient("getdo","return 1+1;",nil,nil); + +如果在计算中需要采用系统参数,将参数放入第四个参数即可: + +Return SendToClient("getdo","return +getsysparam('a')+GetSysParam('b');",nil,array("a":1,"b":2)); + +如果计算数据的超时时间需要设置,再在后边加入一个超时的秒数的参数: + +Return SendToClient("getdo","return +getsysparam('a')+GetSysParam('b');",nil,array("a":1,"b":2),30);//超时为30秒。 + +do命令和getdo命令类似,但是do命令不等待结果的返回,这点和RDo与RDo2的差异类似。 + +参考:SendToClient diff --git a/data/tsl_reference_catalog_source/resource.md b/data/tsl_reference_catalog_source/resource.md new file mode 100644 index 00000000..48c7a820 --- /dev/null +++ b/data/tsl_reference_catalog_source/resource.md @@ -0,0 +1,3913 @@ +#### 资源访问函数 + +##### 内容 + +- 资源访问函数简介 +- 数据库访问函数 +- 文件访问函数 +- 网络访问以及相关函数 +- INI文件处理函数 +- 进程相关函数 +- 本地资源相关函数 + +##### 资源访问函数简介 + +资源访问函数一般仅为TSL本地解析器所支持,例如CGI,WORD模板的TSL语句以及其他本地TSL语言解析器。 + +对于服务器运算的金融分析.NET,由于资源访问函数基本上都需要访问到服务器上的一些特有资源,例如文件访问,数据库访问等,而因为服务器上的数据库以及文件的保密性,这些函数在一般情况不为在线版本的用户开放,仅仅只有当用户购买了服务器版本,由系统管理员在服务器上为用户开放了之后才可以使用。 + +##### 数据库访问函数 + +###### 内容 + +- ExecSQL +- SQLBeginTrans +- SQLInTrans +- SQLCommit +- SQLRollBack +- SQLErrorMsg +- SQLCloseConn +- 数据库配置 +- Openforwardonly模式 + +###### ExecSQL + +用途:数据库访问函数相关函数。 +参数:arg1,arg2,arg3,arg4(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +范例01:同时返回结果集与字段结构信息,并将字段转换为大写(以MySQL为例) + +```tsl +f31 := 0; // 不缓存 +f30 := 0x40000000; // 不访问元数据 +f29 := 0x20000000; // 转为大写 +f28 := 0x10000000; // 转大小写有效 +df := 2; // 同时返回结果集与字段结构信息 +Flags := f31 + f30 + f29 + f28 + df; +echo Flags; +echo 'FLAGS高四位:', Flags .& 0x80000000 <> 0, Flags .& 0x40000000 <> 0, Flags .& 0x20000000 <> 0, Flags .& 0x10000000 <> 0; +echo 'FLAGS低位值:', Flags .& 3; +// test表中数据为浦发银行2023-8-31至2023-9-13的收盘价 +sqlstr := 'select * from test where close<(select avg(close) from test)'; +ret := rdo2 ExecSQL(Flags, 'mysql', sqlstr, result); +if ret then return result; +else return rdo2 SQLErrorMsg(); // 报错信息 +``` + +其中, + +Result[0]返回结果: + +Result[1]返回字段结构信息: + +范例2: + +```tsl +// 表名:SZ000002cy_5m +// 数据库别名:cfsql (SQL和天软交互时配置的数据库别名) +s := "select * from SZ000002cy_15m;"; +ret := rdo2 ExecSQL("cfsql", s, data); +if ret then return data; +``` + +范例03:存贮过程的调用,参数名TestParamName是一个输入输出参数,最后param的结果会被修改。 + +```tsl +param := array("TestParamName":("Value":"ParamNameValue", "Direction":3)); +ExecSQL(param, "test", "myStoredProctest", result); +``` + +Sys_refcursor输出参数: + +API链接方式支持oracle存贮过程的sys_refcursor输出参数,会作为多结果集返回。 + +假定oracle存贮过程如下: + +create or replace procedure testproc(b out sys_refcursor,c out sys_refcursor) is + +begin + +open b for + +select \* from TESTTABLE; + +open c for + +select \* from TESTTABLE; + +end testproc; + +可以使用如下代码来获得两个结果集: + +a:=array( + +"b":("Direction":2,"Type":22), + +"c":("Direction":2,"Type":22) + +); + +execsql(a,"ora2","TESTPROC",r); + +注:ADO模式无法支持此种类型返回参数。 + +范例04:Array DML 方式批量插入数据范例 + +```tsl +// 获取数据模型 +r := TSFL_SQL_GetData(20130101T, 20131231T); +{Insert语句,注意下列数据中EndDate,StockID,StockName,price,vol是占位符,对应param数组中的占位符。与数据库表中列名无关,此处没有指定Test的列名,按照数据库表中列的顺序给定数据。如需指定列名,在Test后带上列名} +s := "insert into Test values(:EndDate,:StockID,:StockName,:price,:vol)"; +{插入数据列值:EndDate,StockID,StockName,price,vol是占位符, +} +param := array("EndDate":array("Direction":1, "Value":r[:, 'EndDate']), +"StockID":array("Direction":1, "Value":r[:, 'StockId']), +"StockName":array("Direction":1, "Value":r[:, 'StockName']), +"price":array("Direction":1, "Value":r[:, 'Close']), +"vol":array("Direction":1, "Value":r[:, 'Vol'])); +// 执行SQL操作 +ret := rdo2 ExecSQL(param, 'SQLAlias', s, result); +return result; +``` + +范例05:输出转为WideString类型 + +```tsl +SQLStr1 := "select * from test"; +// 数据库别名使用widestring宽字节 +DBname := L'pgsql'; +ExecSQL(DBname, SQLStr1, t); +echo tostn(t); +return t; +``` + +源串中字符串为宽字节: + +更多关于数据库的详细说明及范例,见专题: + +http://www.tinysoft.com.cn/tsdn/helpdoc/index.tsl?itemid=15106 + +###### SQLBeginTrans + +###### SQLInTrans + +###### SQLCommit + +###### SQLRollBack + +###### SQLErrorMsg + +###### SQLCloseConn + +###### 数据库配置 + +数据库配置主要分本地配置和服务器配置两种方式。本地配置主要用于本地的文件或共享给本地的文件的交互,服务器配置主要用于对服务器端的文件或者共享给服务器的文件的交互。一般用户只需要在本地配置即可。 + +####### 内容 + +- 配置说明 + +####### 配置说明 + +| 项目 | 本地配置 | 服务器配置 | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| 交互对象 | 本地文件,本地共享文件 | 服务器文件,服务器共享文件 | +| 调用函数或类 SQL 方式 | 在模型前加关键字 rdo2 | 直接调用,不加 rdo2 | +| 配置文件 | 安装目录下,如 `C:\\Program Files\\Tinysoft\\Analyse.NET\\Plugin\\execsql.ini` | 服务器目录下所有 bin,如 `D:\\Tinysoft\\bin\\plugin\\execsql.ini` | +| 配置程序 | 与 execsql.ini 同目录下的 ConnectMan.exe,执行后继续下面的选择 | 同左 | +| 提供程序 | 选择与数据库匹配的 | 同左 | +| 服务器名称 | 本地服务器可用 127.0.0.1/localhost,其他输入服务器名 | 同左 | +| 用户名 | 用户登录数据库的用户名 | 同左 | +| 密码 | 用户登录数据库的密码 | 同左 | +| 空白密码 | 不勾选 | 同左 | +| 允许保存密码 | 勾选 | 同左 | +| 数据库 | 选择需要操作的数据库 | 同左 | +| 测试连接 | 连接成功 | 同左 | +| 复制连接串 | `Provider=SQLOLEDB.1;Password=testpw;Persist Security Info=True;User ID=testusername;Initial Catalog=test;Data Source=THINKPAD`
说明:该语句不能换行 | 同左 | +| Execsql.ini 完整配置 | `[test]`
`ConnectStr=Provider=SQLOLEDB.1;Password=testpw;Persist Security Info=True;User ID=testusername;Initial Catalog=test;Data Source=THINKPAD`
`permit=local`
说明:`test` 为数据库别名;`ConnectStr` 为连接字符串;`Permit` 为提交用户,local 表示本地客户端登录用户 | 同左 | + +###### Openforwardonly模式 + +在不需要对已访问过的数据进行再次访问时,设置openforwardonly游标模式,可以减少数据库访问的中间结果集对内存的开销,大数量级的数据访问中可以有效地提高交互性能。 + +####### 内容 + +- TS-SQL语句中设置Openforwardonly模式 +- ExecSQL函数中设置Openforwardonly模式 + +####### TS-SQL语句中设置Openforwardonly模式 + +在TS-SQL语法中,可以通过设置selectopt为0x8000000的方式来指定Openforwardonly模式。 + +如: + +Return Select selectopt(0x8000000) _ from sqltable 'select _ from +TSP_AccountTradeDetails where Action=10' of TSP_GetAlias() end; + +则表示从数据库中提取TSP_AccountTradeDetails的部分数据时,游标开启只进模式,提取到结果集后,不再对该结果集进行缓存。 + +####### ExecSQL函数中设置Openforwardonly模式 + +######## 内容 + +- 第一种:当前交互语句设置为Openforwardonly模式 +- 第二种:设置当前环境缺省为Openforwardonly模式 + +######## 第一种:当前交互语句设置为Openforwardonly模式 + +通过设置Flags参数的第27位为真(即0x8000000)生效。 + +SQLStr:="select \* from Test where EndDate>='2013-06-30'"; + +Flags:=0x8000000; //选择Openforwardonly模式 + +Ret:=rdo2 ExecSQL(Flags,'SQLAlias',SQLStr,t); + +if ret then + +return result; + +else + +return rdo2 SQLErrorMsg();//报错信息 + +例如:执行下列SQL语句时,服务器端不会缓存该语句访问的结果集。 + +######## 第二种:设置当前环境缺省为Openforwardonly模式 + +在ExecSQL的方式中,还可以通过配置改变当前交互环境的默认方式为Openforwardonly模式。 + +支持配置ExecSql交互的缺省方式与指定数据库交互的缺省方式。 + +当配置为Openforwardonly模式后,可以通过指定设置Flags参数的第26位为真(即0x4000000)来取消,即临时指定为Notopenforwardonly模式。 + +配置方法: + +[ExecSql Config] + +ExecSqlForwardOnly=1 + +########设置此处则,默认任何别名在EXECSQL均启用openforwardonly模式 + +[DBAlias] + +ExecSqlForwardOnly=1 + +########设置此处则,默认数据库别名DBAlias在EXECSQL均启用openforwardonly模式在天软安装目录下的plugin\ExecSql.ini文件中,添加以下配置 + +注:以上缺省方式的设置仅支持ExecSql的操作,不支持TS-SQL语句。 + +SQLStr:="select \* from Test where EndDate>='2013-06-30'"; + +Ret:=rdo2 ExecSQL('SQLAlias',SQLStr,t); + +if ret then + +return result; + +else + +return rdo2 SQLErrorMsg();//报错信息使用范例:在配置了上述缺省方式之后,操作如下 + +即,由于ExecSQL执行的当前环境缺省为Openforwardonly模式,所以默认情况下上述执行的sql语句不会缓存结果集。 + +SQLStr:="select \* from Test where EndDate>='2013-06-30'"; + +Flags:=0x4000000; //指定为Notopenforwardonly模式 + +Ret:=rdo2 ExecSQL(Flags,'SQLAlias',SQLStr,t); + +if ret then + +return result; + +else + +return rdo2 SQLErrorMsg();//报错信息 + +在这种环境下,当提取的某次结果集,在后面的过程中还需要被再次或多次访问时,我们又希望它能够被缓存,来提高访问效率,此时,我们可以在本次执行的ExecSQL操作中进行单次取消Openforwardonly模式,进入Notopenforwardonly模式进行执行,例如: + +##### 文件访问函数 + +###### 内容 + +- FileList +- FileAge +- RemoveDir +- FileSize +- SetFileAttr +- FileDelete +- Sysdbfwrite +- FileTime +- SetFileAge +- WriteFile +- WriteToLog +- FileExists +- 目录别名 +- FileCopy +- SetFileTime +- ReadExcelSheets +- CreateDir +- FileAttr +- ReadFile +- Sysdbfread +- FileRename +- ImportFile +- ExportFile +- 导入导出类型函数 +- 文件读写类型函数 +- ExportFile2 +- ImportFile2 +- FileMode +- SetFileMode +- FileAttrToStr +- FileModeToStr +- StrToFileAttr +- StrToFileMode +- Filemove + +###### FileList + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 FileList("", "c:\\test11.txt"); +return ret; +``` + +###### FileAge + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 FileAge("", "c:\\test11.txt"); +return FileDateToDateTime(ret); +// 返回41153 ,日期2012-09-01 +``` + +###### RemoveDir + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件夹:C:\test +ret := rdo2 RemoveDir("", "c:\\test"); +return ret; +// 结果:1 +``` + +###### FileSize + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 读取本地文件大小:C:\test11.txt +ret := rdo2 FileSize("", "c:\\test11.txt"); +return ret; +// 结果:253 +``` + +###### SetFileAttr + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 将本地文件c:\test11.tst设置为‘只读’文件 +ret := rdo2 SetFileAttr("", "c:\\test11.txt", 1); +return ret; +// 结果:0 ,设置成功,可右键文件查看属性 +``` + +###### FileDelete + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test22.txt +ret := rdo2 FileDelete("", "c:\\test22.txt"); +return ret; +// 结果:1 +``` + +###### Sysdbfwrite + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:将数据导为dbf文件,各列数据类型自动判别。 + +```tsl +t := `array('A':(1, 1, 1), 'B':('a', 'b', 'c')); +return rdo2 Sysdbfwrite('', ' D:\\testdbf.dbf ', t); +// 导出的数据结果: +``` + +范例02:将数据导为dbf文件,按指定数据结构定义。 + +```tsl +t := `array('A':(1, 1, 1), 'B':('a', 'b', 'c')); +c := array("A":("Type":"C", "Width":10, "Dec":0), "B":("Type":"C", "Width":18, "Dec":0)); +return rdo2 Sysdbfwrite('', ' D:\\testdbf.dbf ', t, c); +// 在结构定义c中,将第A列的值数据类型导出为字符串,而非原数据的整型。 +// 导出的数据结果(A列为字符串类型): +``` + +###### FileTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +// 读取本地文件更新时间:C:\test11.txt +ret := rdo2 FileTime("", "c:\\test11.txt"); +return datetimetostr(ret); +``` + +###### SetFileAge + +用途:文件访问函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 SetFileAge("", "c:\\test11.txt", +DateTimeToFileDate(strtodatetime("2012-09-01 14:00:00"))); +return ret; +// 返回:0 (文件时间设置成功) +``` + +###### WriteFile + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 写入一个二维字符数组 +a := array(("aa", 21, "beijing"), +("bb", 22, "beijing"), +("vv", 23, "beijing"), +("ff", 24, "beijing"), +("ww", 25, "beijing") +); +ret := rdo2 WriteFile(rwobj(), "", "c:\\test11.txt", 0, 1000, a); +return ret; +// 结果:1 (表示数据写入成功) +``` + +###### WriteToLog + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +retun WriteToLog('测试', 'testlocal', '成功'); +// 结果:在虚拟目录’testlocal’下生成了名为’测试2018-09-07.log’的txt文件,内容为’ 16:34:12->成功’。 +``` + +###### FileExists + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +ret := rdo2 FileExists("", "c:\\test11.txt"); +return ret; +// 结果:1 (表示文件存在) +``` + +###### 目录别名 + +目录别名是在服务器上定义好的字符串,该字符串会对照到服务器上一个指定的目录,该目录的读写权限是由服务器设置的。用户使用这个目录别名可以理解为某个服务器上指定的目录。 + +与本地的文件进行交互,用户需在调用函数前加关键字 rdo2。 + +###### FileCopy + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt,且不存在文件:C:\test123.txt +ret := rdo2 FileCopy("", "c:\\test11.txt", "", "c:\\test123.txt", 1); +return ret; +// 结果:1 +``` + +###### SetFileTime + +用途:日期时间处理函数。 +参数: + +返回:日期或时间值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 SetFileTime("", "c:\\test11.txt", DateTimeToFileDate(strtodatetime("2012-09-01 13:00:01"))); +return ret; +// 返回:0 (文件时间设置成功) +``` + +###### ReadExcelSheets + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 读取本地文件的sheet列表名 +rdo2 ReadExcelSheets('', 'd:\\test\\test.xls', r, 0); +return r; +// 结果:array("Sheet1","Sheet2","Sheet3") +``` + +参考文件访问函数 + +###### CreateDir + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建本地目录:C:\test +ret := rdo2 CreateDir("", "c:\\test"); +return ret; +// 结果:1 +``` + +###### FileAttr + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 FileAttr("", "c:\\test11.txt"); +return ret; +// 结果:16 +``` + +###### ReadFile + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 按原始类型读出文件的数据 +size := rdo2 filesize("", "c:\\test.txt"); // 获取文件大小 +ret := rdo2 ReadFile(rwraw(), "", "c:\\test.txt", 0, size, data); +if ret then return data; +``` + +###### Sysdbfread + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:读取本地文件testdbf.dbf的内容 + +```tsl +ret := rdo2 Sysdbfread("", "D:\\testdbf.dbf", t); +if ret then return t; +else return ‘读取本地数据失败’; +// 若ret为1 (表示读取成功,此时读取的D:\\testdbf.dbf的数据存在变量t中) +// 返回结果: +A +B +1 +a +1 +b +1 +c +``` + +范例02://读取本地文件testdbf.dbf的结构定义 + +```tsl +ret := rdo2 Sysdbfread("", "D:\\testdbf.dbf", t, 1); +if ret then return t; +else return ‘读取本地数据失败’; +// 若ret为1 (表示读取成功,此时读取的结构定义存在变量t中) +// 返回结果: +type +Width +Dec +A +N +10 +0 +B +C +18 +0 +``` + +###### FileRename + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 FileRename("", "c:\\test11.txt", "c:\\test12.txt"); +return ret; +// 结果:1 +``` + +差异说明当重命名的名称与本地文件同名时,windows下表现为重命名操作失败,而Linux中表现为直接覆盖已存在的同名文件,该差异由操作系统行为不同导致。 + +所以,在Linux中,最好先检测是否存在同名文件,再做重命名操作。 + +如若需要处理成:当指定路径下已存在该文件时,重命名操作失败。 + +则其实现可参考如下: + +```tsl +// 原文件路径与名称 +snFilePath := "/home/tinysoft/newFile.txt"; +// 重命名文件路径与名称 +rFilePath := "/home/tinysoft/rawFile.txt"; +if FileExists(rFilePath) then return 0; // 若新名称文件已存在,则返回0 +r := FileRename('', rFilePath, snFilePath); +return r; +``` + +###### ImportFile + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +Data1 := rand(10, 5); +ret1 := rdo2 exportfile(ftxls(), "", "c:\\test.xls", data1); +if ret1 then +begin + ret2 := rdo2 ImportFile(ftxls(), "", "c:\\test.xls", data2); + if ret2 then return data2; + else return "导出失败"; +end +else return 0; +``` + +范例02: + +```tsl +// 导入excel中的INF及NAN +ret := rdo2 ImportFile(ftXLS(), '', 'C:\\testdata.xlsx', data); +if ret then return Data; +else return ret; +``` + +Excel中的数据: + +导入到天软中的数据: + +范例03: + +```tsl +// .xls文件与.xlsx 文件行列最大限制不一样,xls文件最大256列,.xlsx文件最大限制16384 +// 列,此处有数据16000列的.xlsx文件,后缀名改为.xls文件,仍可以导入16000列,说明//该函数可以自动识别.xls或者.xlsx的文件格式 +ret := rdo2 ImportFile(ftXLS(), '', 'C:\\testdata4.xls', data); +if ret then return Data; +else return ret; +``` + +结果 + +范例04:导入csv文件 + +```tsl +LJ := "D:\\Test\\20241204.csv"; +r := rdo2 ImportFile(ftcsv(), "", LJ, t); +return t; +``` + +###### ExportFile + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01: + +```tsl +data := rand(10, 5); +ret := rdo2 ExportFile(ftxls(), "", "c:\\test.xls", data); +if ret then return 1; +else return 0; +// 结果:1 (表示数据导出成功,可以在c盘看到test.xls文件) +``` + +范例02: + +```tsl +// 导入excel中的INF及NAN +data := `array('a':(1, 2, 3), 'b':array(4, 5, 6), 'c':array(1 / 0, 0.0 / 0.0, 0)); +ret := rdo2 ExportFile(ftXLS(), '', 'C:\\testdata2.xlsx', data); +if ret then return Data; +else return ret; +``` + +结果 + +天软数据: + +导出到Excel中的数据: + +范例03:导出数据为csv格式 + +```tsl +t := rand(10, array("A", "B", "C")); +LJ := "D:\\Test\\20241204.csv"; +r := rdo2 ExportFile(ftcsv(), "", LJ, t); +return r; +``` + +###### 导入导出类型函数 + +导入导出类型函数决定导入导出的文件类型。目前支持有逗号分割文件,EXCEL电子表格文件,天软对象流文件,天软对象字符串文件。这些函数用于ExportFile,ImportFile的Type参数。 + +####### 内容 + +- ftCSV +- ftXLS +- ftXls2 +- ftXls3 +- ftStream +- ftString +- ftXML +- ftdbf + +####### ftCSV + +参考导入导出类型函数 + +####### ftXLS + +参考导入导出类型函数 + +####### ftXls2 + +参考导入导出类型函数 + +####### ftXls3 + +参考导入导出类型函数 + +####### ftStream + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例(t): + +导出操作: + +```tsl +data := rand(10, array("A", "B", "C")); +r := rdo2 Exportfile(ftStream(), '', 'E:\\test\\tsdata.stm', data); +if r = 1 then return "导出成功"; +else return r; // 导出失败 +``` + +导入操作: + +```tsl +r := rdo2 Importfile(ftStream(), '', 'E:\\test\\tsdata.stm', data); +if r = 1 then return data; +else return r; // 导出失败 +``` + +参考导入导出类型函数 + +####### ftString + +参考导入导出类型函数 + +####### ftXML + +参考导入导出类型函数 + +差异说明Linux中,暂不支持导入导出该文件类型 + +####### ftdbf + +参考导入导出类型函数 + +###### 文件读写类型函数 + +文件读写类型函数是决定用户在调用文件读写函数的时候,读出或者写入的数据类型。这些文件读写类型函数用于ReadFile,WriteFile的DataType参数。 + +####### 内容 + +- rwByte +- rwInt +- rwReal +- rwStr +- rwObj +- rwRaw +- rwBinary + +####### rwByte + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +size := rdo2 filesize("", "c:\\test.txt"); // 获取文件大小 +ret := rdo2 readFile(rwByte(), "", "c:\\test.txt", 0, size, data); +ret := rdo2 readFile(rwraw(), "", "c:\\test.txt", 0, size, data1); +if ret then return data1; +``` + +参考文件读写类型函数 + +####### rwInt + +参考文件读写类型函数 + +####### rwReal + +参考文件读写类型函数 + +####### rwStr + +参考文件读写类型函数 + +####### rwObj + +参考文件读写类型函数 + +####### rwRaw + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例(t): + +写出到本地txt文件中 + +```tsl +str := 'Hello demo!!'; +r := rdo2 WriteFile(rwraw(), '', "d:\\test.txt", -1, length(str), str); +if r = 1 then return "写出成功"; +else return r; +``` + +读取本地txt文件内容 + +```tsl +r := rdo2 ReadFile(rwraw(), '', 'd:\\test.txt', 0, 10000, data); +if r = 1 then return data; +else return r; // 读取失败 +``` + +参考文件读写类型函数 + +####### rwBinary + +参考文件读写类型函数 + +###### ExportFile2 + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +导出10\*5全1矩阵,到C:\\test.xlsx 文件的Sheet3,C2单元格。 + +```tsl +data := ones(10, 5); +ret := rdo2 ExportFile2(ftxls(), "", "C:\\test.xlsx", data, 1, 0, "Sheet3", "C2"); +return ret; +// 结果:1 (表示数据导出成功,可以在c盘看到test.xlsx文件) +``` + +###### ImportFile2 + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +导入"C:\\test.xlsx"文件中的Sheet3的"C2:E5"数据,包含字段名称。 + +```tsl +ret := rdo2 ImportFile2(ftxls(), "", "C:\\test.xlsx", data, 1, 0, 0, "Sheet3", "C2:E5"); +if ret then return data; +else return "导入失败"; +``` + +Excel的数据: + +###### FileMode + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 本地文件:C:\test11.txt +ret := rdo2 FileMode("", "c:\\test11.txt"); +return ret; +// 结果:32 +``` + +###### SetFileMode + +用途:文件访问函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 将本地文件c:\test11.tst设置为‘只读’文件 +ret := rdo2 SetFileMode("", "c:\\test11.txt", 1); +return ret; +// 结果:0 ,设置成功,可右键文件查看属性 +``` + +###### FileAttrToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +// 本地存在备份文件c:\test11.txt +attr := rdo2 FileAttr("", "c:\\test11.txt"); +ret := rdo2 FileAttrToStr(attr); +return ret; +// 结果:”A” +``` + +###### FileModeToStr + +用途:将输入值转换为字符串。 +参数: + +返回:字符串。 + +范例 + +```tsl +// 本地存在备份文件c:\test11.txt +attr := rdo2 FileMode("", "c:\\test11.txt"); +ret := rdo2 FileModeToStr(attr); +return ret; +// 结果:” A” +``` + +###### StrToFileAttr + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +Str1 := "A"; +return rdo2 StrToFileAttr(Str1); +// 结果:32 +``` + +###### StrToFileMode + +用途:将字符串转换为对应类型。 +参数: + +返回:转换后的数值或日期。 + +范例 + +```tsl +Str1 := "A"; +return rdo2 StrToFileMode(Str1); +// 结果:32 +``` + +###### Filemove + +用途:移动文件,支持跨卷移动(相比 FileRename 可跨盘)。 +参数: + +返回:成功返回 1,失败返回 0。 + +范例 + +范例01:同盘移动 + +```tsl +LJ0 := "E:\\test\\testdat3.xlsx"; // 源文件路径及文件名 +LJ1 := "E:\\TestExcel\\testdat4.xlsx"; // 目标路径及文件名 +r := rdo2 Filemove("", Lj0, "", LJ1); +return r; +``` + +返回1则移动成功,返回0则移动失败 + +范例02:跨盘移动 + +```tsl +LJ0 := "E:\\test\\TestB2.txt"; // 源文件路径及文件名 +LJ1 := "C:\\test\\TestB.txt"; // 目标路径及文件名 +r := rdo2 Filemove("", Lj0, "", LJ1, 2); +return r; +``` + +返回1则移动成功,返回0则移动失败 + +注:若移动失败,可先确认以下几点: + +1、指定的目标路径是否存在 + +2、目标文件中是否存在同名文件而移动模式没有选择替换模式。 + +3、目标文件是否跨盘,而移动模式没有选择复制模式。 + +##### 网络访问以及相关函数 + +###### 内容 + +- GetHttp +- PostHttp +- InternetRequest +- ParseHtml +- GetURL +- CreateHttpSession +- SetHttpMode +- SetHttpCallBack +- GetHttpContent +- GetHttpResponseHeader +- SysSendMail + +###### GetHttp + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例一: + +```tsl +// 访问tinysoft主页 +ret := rdo2 GetHttp("http://tinysoft.com.cn", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +范例二:使用微软库进行连接 + +```tsl +// 访问tinysoft主页 +ret := rdo2 GetHttp(0, "http://tinysoft.com.cn", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +范例三:使用TCP直接连接 + +```tsl +// 访问tinysoft主页 +ret := rdo2 GetHttp(1, "http://tinysoft.com.cn", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +###### PostHttp + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:整数。 + +范例 + +范例一:获取指定网页内容 + +```tsl +// 访问tinysoft主页 +ret := rdo2 PostHttp("http://tinysoft.com.cn", "Hello", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +范例二:使用微软库进行连接 + +```tsl +// 访问tinysoft主页 +ret := rdo2 PostHttp(0, "http://tinysoft.com.cn", "Hello", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +范例三:使用TCP直接连接 + +```tsl +// 访问tinysoft主页 +ret := rdo2 PostHttp(1, "http://tinysoft.com.cn", "Hello", 500, data, code); +if ret then return array(ret, data, code); +else return "获取失败"; +``` + +###### InternetRequest + +###### ParseHtml + +###### GetURL + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```text +GetURL('http://www.tinysoft.com.cn','index.html') + +//结果为:http://www.tinysoft.com.cn/index.html +``` + +###### CreateHttpSession + +- GetHttp +- PostHttp +- InternetRequest +- ParseHtml +- GetURL +- CreateHttpSession +- SetHttpMode +- SetHttpCallBack +- GetHttpContent +- GetHttpResponseHeader +- SysSendMail + +###### SetHttpMode + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +多段模式下获取指定网址中的内容,实时吐词方式 + +```tsl +sid := createhttpsession(); +SetHttpMode(sid, 1); // 分段模式 +url := " http://www.baidu.com"; +r := GetHttp(url, 60000, v, code); +echo "\r\ndone->", r, '->', code, '->', length(v), "\r\n"; +echo v; +// 分段未结束时GetHttp返回值为1,code值为1000 +while r and code = 1000 do +begin + r := GetHttp(url, 60000, v, code); + echo v; +end; +if r <> 1 then return "网页访问失败"; +return code; +``` + +实时打印显示:(分段未结束时code=200) + +###### SetHttpCallBack + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +回调函数说明: + +进度(progress)回调模式的回调函数定义为: + +| 定义 | function progresscallback(session,TotalDown,Downloaded,TotalUpload,Uploaded); | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 参数 | Session:session ID
TotalDown:整型,下载总字节数
Downloaded:整型,已下载总字节数
TotalUpload:整型,上传总字节数
Uploaded:整型,已上传总计字节数 | +| 说明 | 进度回调过程中,下载总字节数,已下载总字节数,上传总字节数,已上传总计字节数等不一定在每一次回调都会变化,
因为会间隔一段时间进行进度更新,即便没有发生进度变化。 | +| 返回 | 回调函数的返回值为0表示继续,如果返回为非0则结束请求。若提前结束请求时,此时GETHTTP等函数的返回值与code值为0 | + +header模式的回调函数定义为: + +| 定义 | function headercallback(session,headerline); | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 参数 | Session:session ID
headerline:字符串,当前行内容 | +| 说明 | 获取头部信息。HEADERLINE是每来一行的内容,HEADER的结束是获得一个独立的回车换行。 | +| 返回 | 回调函数的返回值为0表示继续,非0则结束请求。如果仅仅只需要取完HEADER即可,可以当headerline为回车换行时返回-1即可。若提前结束请求时,此时GETHTTP等函数的返回值与code值为0 | + +范例 + +下载过程中通过进度回调获取实时下载进度,通过头部回调获取头部信息 + +```tsl +sid := createhttpsession(); +SetHttpCallBack(sid, findfunction("DownProg")); // 进度回调 +SetHttpCallBack(sid, findfunction("head"), "header"); // 头部回调 +s := "http://www.baidu.com"; // 小型下载 +m := "http://www.tinysoft.com/download/setup64.exe"; // 具备下载总量的下载 +l := "http://speed.cloudflare.com/__down?bytes=123456789"; // 头部没有content-length的下载 +r := GetHttp(s, 60000, v, code); // 可以用s/m/l看看区别 +echo "\r\n=>done ", r, '->', code, '->', length(v), "\r\n"; +return 1; +// 进度回调函数 +function DownProg(sid, AlldnB, dnB, AllupB, upB); // progresscallback +begin + if dnB > 0 then//如果已开始下载则打印 + begin + R := AlldnB > 0?dnB / AlldnB * 100:0; + S := "->" + DupeString(#8, Ceil(R / 10)); + echo S, int(R), "% ", dnB$"/", AlldnB, "\r\n"; + end; + return 0; // 请求继续,返回其它,如return 1;则表示请求到此处就结束 +end; +// 头部回调模型 +function head(sid, hline); +begin + echo hline; + // if hline="\r\n" then //return -1; // 如果返回header后就结束请求打开这两行即可 + return 0; // 请求继续 +end; +``` + +打印效果: + +###### GetHttpContent + +用途:网络访问以及相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +下载过程中,一边下载一边导出到本地 + +```tsl +sid := createhttpsession(); +sethttpcallback(sid, findfunction("DownProg")); // 进度回调 +s := "http://www.baidu.com"; // 小型下载 +GetHttp(s, 60000, v, code); +echo "\r\n---->done", '->', code, '->', length(v); +return 1; +// 进度回调函数 +function DownProg(sid, AlldnB, dnB, AllupB, upB); // progresscallback +begin + if dnB > 0 then//如果已开始下载则保存到本地 + begin + if dnB > sysparams["__DownProg_dnB"] then begin + hc := GetHttpContent(sid); // 获取当前内容 + ret := WriteFile(rwRaw(), '', "E:\\test\\log_Data.txt", 0, Length(hc), hc); + end; + sysparams["__DownProg_dnB"] := dnB; + echo "->", dnB$"/", AlldnB, "\r\n"; + end; + return 0; // not done +end; +``` + +导出效果如下: + +###### GetHttpResponseHeader + +用途:网络访问以及相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +获取指定网页的头部信息 + +```tsl +sid := createhttpsession(); +url := "http://www.baidu.com"; +r := GetHttp(url, 60000, v, code); +hd := GetHttpResponseHeader(); +return hd; +``` + +返回如下: + +###### SysSendMail + +用途:通过 SMTP 服务器发送邮件。 +参数:见下方定义与参数说明。 +返回:发送成功返回 true,失败返回 false;可通过 Msg 获取错误信息。 + +说明:利用SMTP服务器发送邮件,成功返回真,否则返回假。如果有MSG这个参数,则当失败的时候返回失败的具体信息到MSG参数。 + +定义一:SysSendMail(AHost,ASubject,ATo,AFrom,AText:String;[Var +Msg:String]):Boolean; + +参数: + +定义二:SysSendMail(AHost,ASubject,ATo,AFrom,AText,ACharSet,ABccList,ACCList:String; +APriority:Integer;[[…]][Var Msg:String]):Boolean; + +参数: + +附件可选参数,AttachmentName和AttachmentContent任意对参数组合。 + +AttachmentName..:添加的附件在邮件里的文件名称。 + +AttachmentContent..:添加的附件的内容,如果该内容为字符串类型且存在该文件,则将文件内容作为附件内容。 + +MSG:用于接收错误信息的参数,可省略。 + +返回:如果发送成功,则返回1,否则返回0; + +范例: + +```tsl +// 范例一: +ret := rdo2 SysSendMail("www.tinysoft.com.cn", +'客户端发邮件测试', +'xulihua@tinysoft.com.cn', +'support@tinysoft.com.cn', +'Tinysoft hello', +msg); +return ret; +// 结果:1 +// 范例二: +ret := rdo2 SysSendMail("www.tinysoft.com.cn", +'客户端发邮件测试', +'xulihua@tinysoft.com.cn', +'support@tinysoft.com.cn', +'邮件测试:Tinysoft', +'gb2312', +'wuxinxing@tinysoft.com.cn', +'chenjuan@tinysoft.com.cn', +1, +'附件测试', +'D:\\test1\\test.tsl', +msg); +return ret; +// 返回:1,发送的附件为 "附件测试.dat" +``` + +范例三:通过QQ邮箱发送邮件。注意,通过QQ邮箱发送邮件,需要使用QQ账户和账户授权码。授权码的获取参照步骤说明进行配置并获取: + +http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256 + +```tsl +// 通过调用类smtp设置配置信息及发送邮件 +function SendEmailTest_QQ(); +begin + return rdo2 SendEamailTest(); +end; +function SendEamailTest(); +begin + obj := CreateObject("smtp"); + obj.UserName := '510543292'; // 邮箱账号(用户QQ账号) + obj.Password := 'abcdefg'; // 安全验证码(用户QQ的授权码) + obj.UseTLS := 1; // 安全传输协议 + obj.Host := 'smtp.qq.com'; // smtp服务器 + // obj.AuthType := 1; + obj.port := 465; // smtp服务器端口 465或587 + try + Ret := obj.Connect(); + echo ret; + except + return echo "\r\nconnect fail\r\n"; + end; + msg := CreateObject("MailMsg"); + msg.subject := "邮件发送测试"; // 文件标题 + msg.from := "510543292@qq.com"; + msg.ContentType := 'text/html; charset="gb2312"'; + msg.body := "定时任务调度"; // 文件内容 + msg.Sender := "510543292@qq.com"; // 邮件发送人 + msg.Recipients := "510543292@qq.com"; // 邮件接收人 + try + echo obj.send(msg); + echo msg; + except + echo '\r\n邮件错误信息', obj.LastCmdResult(); + return echo '\r\n邮件发送失败:', ExceptObject.errinfo; + end; + return echo 'over'; +end; +``` + +范例四:通过QQ邮箱发送邮件。注意,通过QQ邮箱发送邮件,需要使用QQ账户和账户授权码。授权码的获取参照步骤说明进行配置并获取: + +http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256 + +```tsl +//发送邮件的用户名及授权码的配置写在\tinysoft\analyse.net\plugin\fileMgr.ini 文件里 +{ fileMgr.ini 文件中配置语句如(端口465或587): +[Smtp Settings] +smtp.QQ.COM:UseTLS=1 +smtp.QQ.COM:Port=465 +smtp.QQ.COM:UserName=510543292 +smtp.QQ.COM:Password=abc +smtp.QQ.COM := smtp.QQ.COM +} +ret := SysSendMail("smtp.qq.com", +'客户端发邮件测试', +'510543292@qq.com', +'510543292@qq.com', +'Tinysoft hello', +msg); +return msg; +``` + +####### 内容 + +- SMTP登录以及配置文件 + +####### SMTP登录以及配置文件 + +一旦SMTP服务器需要登录,我们必须先在配置文件中设置好,才可以使用SYSSENDMAIL指定的HOST。 + +配置文件为PLUGIN\FileMgr.INI,在其中加入如下配置: + +[Smtp Settings] + +MOFT.COM:Port=25 + +MOFT.COM:UserName=Bill + +MOFT.COM:Password=Gates + +MOFT.COM=Mail.MOFT.COM + +端口默认为25,地址默认为HOST别名相同,密码允许采用加密存贮,如需要加密请使用CONNECTMAN工具进行加密。 + +##### INI文件处理函数 + +INI文件处理函数主要读取INI文件的结名称、键名称、键值。用中括号[]括起来即结名称,每个节名称下面的是相关的键名键值等。 + +###### 内容 + +- IniReadBool +- IniReadDate +- IniReadDateTime +- IniReadFloat +- IniReadInteger +- IniReadTime +- IniReadString +- IniReadBinaryStream +- IniReadSection +- IniReadSections +- IniReadSectionValues +- IniSectionExists +- IniValueExists +- IniWriteBool +- IniWriteDate +- IniWriteDateTime +- IniWriteFloat +- IniWriteInteger +- IniWriteTime +- IniWriteString +- IniWriteBinaryStream +- IniDeleteKey +- IniEraseSection +- 宽字节处理函数 + +###### IniReadBool + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata1的键名称为bool的键值,返回布尔值。 +节内容为: +[IniData1] +bool := 1 +} +ret := rdo2 IniReadBool("", +"C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini","Inidata1","bool",0); +return ret; +//结果:1 +``` + +###### IniReadDate + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata2,键名称为date的日期值,如果该值不是标准的日期格式‘年-月-日’,则返回默认的日期defualt +节内容为: +[IniData2] +date := 2014-1-1 +} +day := today(); +ret := rdo2 IniReadDate("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata2","date",day); +return ret; +//结果:41640 ,即日期 2014-01-01 +``` + +老版本使用范例: + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata2,键名称为date的日期值,如果该值不是标准的日期格式‘年/月/日’,则返回默认的日期defualt +节内容为: +[IniData2] +date := 2014/1/1 +} +day := today(); +ret := rdo2 IniReadDate("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata2","date",day); +return ret; +//结果:41640 ,即日期 2014-01-01 +``` + +新旧版本的过渡,在新版本中可以通过setformatlocalcode(936)来设定当前的转换规则,达到老版本的效果,比如配置文件内容为: + +{[IniData2] + +date=2014/1/1 + +} + +在新版客户端中执行代码: + +```tsl +day := today(); +rdo2 setformatlocalcode(936); +ret := rdo2 IniReadDate("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini", "Inidata2", "date", day); +return ret; +``` + +返回: 41640 ,即日期 2014-01-01 + +###### IniReadDateTime + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata3,键名称为datetime的日期值,如果该值不是标准的日期格式‘年-月-日 时:分:秒’,则返回默认的日期时间defualt +节内容为: +[IniData3] +datetime := 2014-1-1 14:00:00 +} +day := today(); +ret := rdo2 IniReadDateTime("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata3","datetime",day); +return ret; +//结果:41640.58333333 ,即日期时间 2014-01-01 14:00:00 +``` + +老版本使用范例: + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata3,键名称为datetime的日期值,如果该值不是标准的日期格式‘年/月/日时:分:秒’,则返回默认的日期时间defualt +节内容为: +[IniData3] +datetime := 2014/1/1 14:00:00 +} +day := today(); +ret := rdo2 IniReadDateTime("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata3","datetime",day); +return ret; +//结果:41640.58333333 ,即日期时间 2014-01-01 14:00:00 +``` + +新旧版本的过渡,可参考:IniReadDate + +###### IniReadFloat + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata4,键名称为Float的实数值,如果该值不是实数,则返回默认值defualt +节内容为: +[IniData4] +float := 3.14 +} +ret := rdo2 IniReadFloat("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata4","float",2.5); +return ret; +//结果:3.14 +``` + +###### IniReadInteger + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata5,键名称为INT的整数值,如果该值不是整数,则返回默认值defualt +节内容为: +[IniData5] +INT := 3 +} +ret := rdo2 IniReadInteger("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata5","INT",5); +return ret; +//结果:3 +``` + +###### IniReadTime + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata6,键名称为time的时间值,如果该值不是时间型‘hh:mm:ss’,则返回默认值defualt +节内容为: +[IniData6] +time := 14:00:00 +} +ret := rdo2 IniReadTime("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata6","time",0.5); +return ret; +//结果:0.58333333 ,即时间 14:00:00 +{注意,返回的值跟小数的设置有关,小数点越大,数据越精确,后面获得的时间类型也越准确} +``` + +###### IniReadString + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata7,键名称为String的字符串 +节内容为: +[IniData7] +String := Tinysoft +} +ret := rdo2 IniReadString("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata7","String",'error'); +return ret; +//结果:Tinysoft +``` + +###### IniReadBinaryStream + +用途:INI文件处理函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +以下范例中,都是对下面的bs.ini文件进行的操作,bs.ini文件内容如下: + +范例01:不传入第五个参数,读取ini文件中Test节点中的Bs01键对应的内容 + +```tsl +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 读取data +rt := IniReadBinaryStream("", iniFilePath, "Test", "Bs01"); +return rt; +``` + +范例02:第五个参数值为0,读取ini文件中Test节点中的Bs02键对应的内容 + +```tsl +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 读取data +rt := IniReadBinaryStream("", iniFilePath, "Test", "Bs02", 0); +return rt; +``` + +范例03:第五个参数值为1,读取ini文件中Test节点中的Bs03键对应的内容 + +```tsl +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 读取data +rt := IniReadBinaryStream("", iniFilePath, "Test", "Bs03", 1); +return rt; // 返回值:"Be7iArVxfj8q" +``` + +范例04:第五个参数值为2,读取ini文件中Test节点中的Bs04键对应的内容 + +```tsl +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 读取data +rt := IniReadBinaryStream("", iniFilePath, "Test", "Bs04", 2); +return String(rt); // 返回值:"Be7iArVxfj8q" +``` + +范例05:第五个参数类型为TStream类型,读取ini文件中Test节点中的Bs05键对应的内容 + +```tsl +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 创建TStream对象,用于读取 +rs := new TMemoryStream(); +rt := IniReadBinaryStream("", iniFilePath, "Test", "Bs05", rs); +{ +// 由于读到的stream类型的内容是存放在rs变量中,由于steam类型的数据流不可读, +// 本案例中将其数据值导出到本地的stm文件中,然后再导入该数据进行结果的展示 +// 操作如下: +} +// 将rs导出为STM文件 +rs.SaveToFile("", "D:\\test\\rsData.STM"); +// 读取STM文件 +if not importFile(ftStream(), "", "D:\\test\\rsData.STM", re)then return "获取导入数据失败"; +return array(rt, re); // rt为rs内容的字节长度,re为转为STM格式后的数值 +``` + +###### IniReadSection + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{ +读取本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\filemgr.ini中节名称为test的所有键名。 +节内容为: +[test] +Dir := d:\test1permitRead=tsmodel +permitWrite := tsmodel +UserPrivate := 0 +} +ret := rdo2 IniReadSection("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\filemgr.ini","test"); +return ret; +``` + +###### IniReadSections + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{ +// 读取本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\test.ini中的所有节名称 +} +ret := rdo2 IniReadSections("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini"); +return ret; +``` + +###### IniReadSectionValues + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\filemgr.ini中节名称为test的所有键名及键名内容 +节内容为: +[test] +Dir := d:\test1permitRead=tsmodel +permitWrite := tsmodel +UserPrivate := 0 +} +ret := rdo2 IniReadSectionValues("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\filemgr.ini","test"); +return ret; +``` + +###### IniSectionExists + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +// 判断是否存在节名称为Inidata8的数据配置 +} +ret := rdo2 IniSectionExists("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini", "Inidata8"); +return ret; +// 结果:1 +``` + +###### IniValueExists + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{读取本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +// 判断是否存在节名称为Inidata8,且键名为byte的数据配置 +} +ret := rdo2 IniValueExists("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini", "Inidata8", "byte"); +return ret; +// 结果:1 +``` + +###### IniWriteBool + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData9] +bool := 1 +} +ret := rdo2 IniWriteBool("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata9","bool",1); +return ret; +//结果:0,写入成功 +``` + +文件写入: + +###### IniWriteDate + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData2] +date := 2014/1/12 +} +ret := rdo2 IniWriteDate("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata2","date",41651); +return ret; +//结果:0 ,设置成功 +``` + +文件修改: + +###### IniWriteDateTime + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData3] +datetime := 2014/1/12 14:00:00 +} +ret := rdo2 IniWriteDateTime("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata3","datetime",41651.5833334); +return ret; +//结果:0,修改成功 +``` + +文件修改: + +###### IniWriteFloat + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData4] +float := 9.9 +} +ret := rdo2 IniWriteFloat("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata4","float",9.9); +return ret; +//结果:0,修改成功 +``` + +文件修改: + +###### IniWriteInteger + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData5] +INT := 100 +} +ret := rdo2 IniWriteInteger("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata5","INT",100); +return ret; +//结果:0,修改成功 +``` + +文件修改: + +###### IniWriteTime + +用途:日期时间处理函数。 +参数:无。 +返回:日期或时间值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData6] +time := 12:00:00 +} +ret := rdo2 IniWriteTime("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","Inidata6","time",0.5); +return ret; +//结果:0,修改成功 +``` + +文件修改: + +###### IniWriteString + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{写本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini, +设置节内容为: +[IniData7] +String := Hello Tinysoft +} +ret := rdo2 IniWriteString("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini","IniData7","String",'Hello Tinysoft'); +return ret; +//结果:0,修改成功 +``` + +文件修改: + +###### IniWriteBinaryStream + +用途:INI文件处理函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:写入数据类型为数组,数据写入至ini文件中Write节点的Bs01键中 + +```tsl +data := array(1, 2, 3, 4); +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 写入data +ret := IniWriteBinaryStream("", iniFilePath, "Write", "Bs01", data); +return ret; // 返回值:0 +``` + +ini文件内容: + +范例02:写入数据类型为字符串,数据写入至ini文件中Write节点的Bs02键中 + +```tsl +data := "Be7iArVxfj8q"; +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 写入data +ret := IniWriteBinaryStream("", iniFilePath, "Write", "Bs02", data); +return ret; // 返回值:0 +``` + +ini文件内容: + +范例03:写入数据类型为Binary,数据写入至ini文件中Write节点的Bs03键中 + +```tsl +data := binary("Be7iArVxfj8q"); +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 写入data +ret := IniWriteBinaryStream("", iniFilePath, "Write", "Bs03", data); +return ret; // 返回值:0 +``` + +ini文件内容: + +范例04:写入TStream类型的数据,数据写入至ini文件中Write节点的Bs04键中 + +Data.STM中内容为"Be7iArVxfj8q" + +```tsl +// 创建TStream对象,用于写入 +ws := new TMemoryStream(); +// 从Data.STM文件中加载数据 +ws.LoadFromFile("", "D:\\test\\Data.STM"); +// INI文件地址 +iniFilePath := "D:\\test\\bs.ini"; +// 写入data +ret := IniWriteBinaryStream("", iniFilePath, "Write", "Bs04", ws); +return ret; // 返回值:0 +``` + +ini文件内容: + +###### IniDeleteKey + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{删除本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节Inidata9的键名为bool的内容} +ret := rdo2 IniDeleteKey("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini", "Inidata9", "bool"); +return ret; +// 结果:0,删除成功 +``` + +###### IniEraseSection + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +{删除本地文件:C:\program Files\Tinysoft\Analyse.NET\Plugin\test.ini中节名称为Inidata8的内容,包括节名称、键名、键值 +} +ret := rdo2 IniEraseSection("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini", "Inidata8"); +return ret; +// 结果:0,删除成功 +``` + +###### 宽字节处理函数 + +####### 内容 + +- IniReadSectionsw + +####### IniReadSectionsw + +用途:INI文件处理函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +// 读取本地文件:C:\Program Files\Tinysoft\Analyse.NET\Plugin\test.ini中的所有节名称 +ret := rdo2 IniReadSectionsw("", +"C:\\Program Files\\Tinysoft\\Analyse.NET\\plugin\\test.ini"); +return ret; +// 返回 +``` + +##### 进程相关函数 + +###### 内容 + +- SysPutenv +- 子进程相关函数 +- SysGetLastError +- SysExec +- SysParamStr +- SysErrorMessage +- Sysgetenv +- SysWaitForMultipleObjects +- SysTerminate +- SysCreateMutex +- SysCloseHandle +- SysCmdLine +- SysReleaseMutex +- 运行进程的环境变量 +- SysProcessID +- SysParamcount +- SysThreadID +- Sleep +- SysWaitForSingleObject +- SysGetenvs +- SysexecReadpipe +- SysexecGetenvs +- SysexecDeletepipe +- SysexecSetenvs +- SysexecNewpipe +- SysExecWritepipe +- 获取COM进程 +- TSL解释器对网格计算的支持 +- SysExec定义二 +- dbglocalrunning +- dbglocalcancel +- SysThreadSelf +- syslinuxkrnlclosemutex +- SysSetThreadPriority +- SysGetThreadPriority +- SysSetProcessPriority +- SysGetProcessPriority +- SysGetProcessList +- SysGetProcessListw +- SysGetProcessNamePath +- SysGetProcessNamePathw +- SysGetProcessCmdLine +- SysGetProcessCmdLinew +- SysSetThreadName +- SysGetThreadName +- SysGetThreads +- SysPPid +- SysGetSubProcesses +- SysKill +- SysPidOfTid +- SysPidOfHandle +- SysHandleOfPid + +###### SysPutenv + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +以笔者的电脑环境为例,来展示该函数的功能: + +如图所示,本地现有名为OS的环境变量: + +并且在powerShell等控制台中可以获取到: + +在TSL执行环境中,我们可以使用SysGetenv函数获取指定环境变量,如下: + +范例01:将原环境变量值替换为设置值。 + +从下面的截图中,可以看出,SysPutenv只能设置当前TSL运行环境的环境变量。 + +在客户端中用代码实现如下: + +```tsl +res := SysGetenv("OS"); // 获取本地原有环境变量OS的值 +echo res; // 打印原有环境变量OS的值 +ret := SysPutenv("OS=Test"); // 更改当前运行环境的环境变量OS的值 +if ret = 0 then return SysGetenv("OS"); // 更改成功,获取更改后的环境变量OS的值 +``` + +返回字符串“Test” + +范例02:将新增值添加到原有环境变量中 + +在客户端中用代码实现如下: + +```tsl +res := SysGetenv("OS"); // 获取本地原有环境变量OS的值 +echo res; // 打印原有环境变量OS的值 +res := "OS="$res$";Test"; // 原有环境变量与设置值拼接 +ret := SysPutenv(res); // 更改当前运行环境的环境变量OS的值 +if ret = 0 then return SysGetenv("OS"); // 更改成功,获取更改后的环境变量OS的值 +// 结果:返回字符串" Windows_NT;Test" +``` + +参考Sysgetenv 、 Sysgetenvs + +###### 子进程相关函数 + +运行控制台进程设置输入输出的管道 + +默认情况下,控制台进程的输入是键盘,控制台进程的输出是控制台的屏幕。如果我们需要实现一些特殊的操作,例如给控制台程序发送命令,或者得到控制台程序的输出内容,这样我们就需要用到管道来实现这个功能。 + +###### SysGetLastError + +###### SysExec + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:播放视频 + +```tsl +// 调用windows media player的进程,播放文件D :\\test1\\when_ever.flv +toolPath := "C:\\Program Files\\Windows Media Player"; +ret := rdo2 SysExec(toolPath + "\\wmplayer.exe", "D:\\test1\\when_ever.flv", toolPath, 1, return code); +return ret; +``` + +参考SysCloseHandle SysTerminate、 SysexecNewpipe + +###### SysParamStr + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +本地test.tsl文件中代码如下: + +```tsl +test(); +function test(); +begin + r := array(); + for i := 1 to SysParamcount() do + begin + echo SysParamStr(i), '\r\n'; + end; +end; +``` + +在cmd中打开文件所在文件夹,输入命令:tsl test.tsl 1 2 3 + +###### SysErrorMessage + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return rdo2 SysErrorMessage(200); +// 结果:代码段不可大于或等于 64K。 +``` + +###### Sysgetenv + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 读取本地已有系统环境变量OS的值 +return Sysgetenv("OS"); +// 返回字符串“Windows_NT” +``` + +注:更具体的应用可参考Sysputenv中的范例。参考Sysputenv 、 Sysgetenvs + +###### SysWaitForMultipleObjects + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +SysexecNewpipe(); // 创建管道 +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +doS1 := array('C:\\TinySoftNG\\AnalyseNG.NET\\tsl.exe', 'C:\\DoTSL\\otherTest\\TestEnv.tsl'); +doS2 := array('C:\\TinySoftNG\\AnalyseNG.NET\\tsl.exe', 'C:\\DoTSL\\otherTest\\TestEcho.tsf'); +// 创建一个被挂起的进程,两个会返回的进程 +hand1 := SysExec(path, 'TSL', nil, array('wait':false, 'in':'c := "333"\r\n'), code); +hand2 := SysExec(path, doS1, nil, false, code); +hand3 := SysExec(path, doS2, nil, false, code); +r := SysWaitForMultipleObjects(array(hand1, hand2, hand3), 0, 10 * 1000); // 仅需任意一个对象等待成功 +t := SysexecReadpipe(); // 读取管道内容 +SysTerminate(code, hand1); // 终止进程 +SysTerminate(code, hand2); // 终止进程 +SysTerminate(code, hand3); // 终止进程 +return array(r, t); +``` + +返回:返回为1,说明hand1没有等待成功,而至少hand2是有等待成功了。注:其中的TestEnv.tsl与TestEcho.tsf实现分别如下:TestEnv.tsl: + +```tsl +sleep(500);t := Sysgetenvs();echo "sys: ", tostn(t), '\r\n';return 1; +``` + +TestEcho.tsf: + +```tsl +sleep(2 * 1000); // 停2秒echo 'TestEchoIN\r\n';return 1; +``` + +参考SysExec、 SysWaitForSingleObject + +###### SysTerminate + +参考SysCloseHandle SysExec + +###### SysCreateMutex + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建一个名称为tinysoft的互斥锁 +ret := rdo2 SysCreateMutex("tinysoft"); +return ret; +// 结果:2632 +``` + +###### SysCloseHandle + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 启动windows平台下的windows命令处理程序,然后关闭启动该程序时返回的句柄 +toolPath := "C:\\Program Files\\Windows Media Player"; +ret := rdo2 sysExec(toolPath + "\\wmplayer.exe", "D:\\test1\\when_ever.mp3", toolPath, 1, return code); +ret1 := rdo2 SysCloseHandle(ret); +return ret1; +// 结果:1 +``` + +参考SysExec SysTerminate + +###### SysCmdLine + +###### SysReleaseMutex + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 释放互斥锁,参数为创建互斥锁时返回的互斥锁编号 +ret := rdo2 SysCreateMutex("tinysoft"); +ret1 := rdo2 SysReleaseMutex(ret); +return ret1; +// 结果:1 +``` + +###### 运行进程的环境变量 + +一个进程的环境块会影响一个进程的行为,一些是通用的系统环境块,例如windows里的path和linux里的PATH以及LD_LIBRARY_PATH,另外一些是进程所依赖的特殊的环境,例如java有java运行的特殊环境变量 + +注意:在windows里常用的环境变量为path,是运行和加载DLL的查找路径 + +在linux里PATH表明执行的路径,LD_LIBRARY_PATH用来标识加载DLL的查找路径 + +在多路径的分隔符,windows里采用“;”进行分割,而linux采用“:”进行分割 + +Linux里的环境变量等名称大小写相关,而windows环境变量大小写不相关 + +例如在windows里sysgetenv("path")和sysgetenv("PATH")的结果是一样的 + +而在linux里必需使用sysgetenv("PATH") + +###### SysProcessID + +用途:获取当前进程 ID(PID)。 +参数:无。 +返回:进程 ID(整数)。 + +范例 + +```tsl +{获得天软客户端程序当前的进程ID,即在任务管理器中查看到的进程对应的PID。每个电脑的进程不一样} +return rdo2 SysProcessID(); +``` + +###### SysParamcount + +用途:获取命令行传入参数的个数。 +参数:无。 +返回:整数。 + +范例 + +本地test.tsl文件中代码如下: + +```tsl +test(); +function test(); +begin + // 获取命令行传入参数个数 + echo SysParamcount(); +end; +``` + +在cmd中打开文件所在文件夹,输入命令:tsl test.tsl 1 2 3 + +###### SysThreadID + +用途:获取当前线程 ID。 +参数:无。 +返回:线程 ID(整数)。 + +范例 + +```tsl +// 获得天软客户端程序当前的进程运行的线程ID +return rdo2 SysThreadID(); +``` + +###### Sleep + +用途:让当前线程休眠指定毫秒数。 +参数: + +返回:无。 + +范例 + +```tsl +// 以下代码先打印123,接着回暂停2S,然后接着打印456 +echo 123; +Sleep(2000); +echo 456; +``` + +###### SysWaitForSingleObject + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +SysexecNewpipe(); // 创建管道 +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +doS := array('C:\\TinySoftNG\\AnalyseNG.NET\\tsl.exe', 'C:\\DoTSL\\otherTest\\TestEnv.tsl'); +hand1 := SysExec(path, doS, nil, array('wait':false, 'in':'d := "123"\r\n'), code); +r := SysWaitForSingleObject(hand1, 10 * 1000); // 等待线程的状态 +t := SysexecReadpipe(); // 读取管道内容 +return array(r, t); +``` + +返回:其中,TestEnv.tsl文件的实现如下: + +```tsl +// 当前sys的环境变量t:=Sysgetenvs();echo "sys: ",tostn(t),'\r\n';s:=Readln(); // 读取echo 'IN:',s,'\r\n';return 1; +``` + +参考SysExec、 SysWaitForMultipleObjects + +###### SysGetenvs + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例读取当前运行环境的所有环境变量 + +```tsl +return SysGetenvs(); +``` + +部分结果截图: + +参考Sysputenv 、 Sysputenv + +###### SysexecReadpipe + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例非阻塞模式下输出内容的读取 + +```tsl +pyPath := "D:\\Program Files\\Python\\Python38\\python.exe"; +pyCmd := "py -u D:\\project\\python\\test.py"; +// 创建读写管道 +ret := SysexecNewpipe(0); +if ret then handle := SysExec(pyPath, pyCmd, nil, false, code); +// 获取SysExec进程所在管道的输出内容 +Res := ""; +while res = ""do +begin + res := SysexecReadpipe(handle); + sleep(100); // 100毫秒读取一次 +end; +SysTerminate(code, handle); // 终止进程 +return res; +``` + +注:其中test.py的内容如下: + +参考SysExec、 SysexecNewpipe 、 Sysexecdeletepipe 、 Sysexecdeletepipe 、 SysExecWritePipe + +###### SysexecGetenvs + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +Sysexecsetenvs(array("test=test", "test1=test1"), 2); +return SysexecGetenvs(); +``` + +注:更多应用可参考Sysexecsetenvs参考SysExec、 Sysexecsetenvs + +###### SysexecDeletepipe + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建读写管道 +SysexecNewpipe(0); +path := "D:\\Program Files\\Analyse.NET\\TSL.exe"; +// 非阻塞执行,返回进程句柄 +hand := SysExec(path, "tsl", nil, false, code); +// 获取SysExec进程所在管道的输出内容 +t1 := ""; +while t1 = ""do +begin + t1 := SysexecReadpipe(hand); +end; +deRet := SysexecDeletepipe(hand); +// 删除成功,尝试向指定进程所在管道写入内容 +if deRet then +begin + try + SysexecWritepipe(hand, " datetostr(20221130T)\r\n"); + return false; + except + // 写入失败,管道删除成功 + return true; + end; +end; +SysTerminate(code, hand); // 终止进程 +return false; +``` + +参考SysExec、 SysexecNewpipe 、 Sysexecdeletepipe 、 Sysexecreadpipe 、 SysExecWritePipe + +###### SysexecSetenvs + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:仅设置的环境变量有效,不使用本地系统环境变量 + +```tsl +// 设置环境变量,不使用系统环境变量 +SysexecSetenvs(array("test=test", "test1=test1"), 0); +return SysexecGetenvs(); +``` + +范例02:设置环境变量,添加到系统环境变量之后 + +```tsl +SysexecSetenvs(array("test=test", "test1=test1"), 1); +return SysexecGetenvs(); +``` + +部分结果截图: + +范例03:设置子进程中的环境变量 + +```tsl +// 创建读写管道 +SysexecNewpipe(); +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +doS := array('C:\\TinySoftNG\\AnalyseNG.NET\\tsl.exe', 'C:\\DoTSL\\otherTest\\TestEnv.tsl'); +SysexecSetenvs(array('Test=D:\\Test', 'Test1=D:\\Test1'), 0); +b1 := SysexecGetenvs(); +// 第一个子进程:非阻塞执行,返回进程句柄 +hand := SysExec(path, doS, nil, 0, code); +// 获取SysExec进程所在管道的输出内容 +t1 := ''; +while t1 = ''do +begin + t1 := SysexecReadpipe(hand); // 循环读取进程的输出内容 + sleep(100); // 100毫秒读取一次 +end; +return t1; +``` + +返回:子进程环境变量设置成功 + +其中,TestEnv.tsl脚本的内容如下: + +```tsl +t := Sysgetenvs(); +echo "sys: ", tostn(t), '\r\n'; +t := Sysexecgetenvs(); +echo "sysExec: ", tostn(t), '\r\n'; +``` + +范例04:设置多个子进程中的环境变量 + +```tsl +// 创建读写管道 +SysexecNewpipe(); +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +SysexecSetenvs(array('Test=D:\\Test', 'Test1=D:\\Test1'), 0); +b1 := SysexecGetenvs(); // 第一个子进程:非阻塞执行,返回进程句柄 +hand := SysExec(path, 'tsl', nil, array('wait':false, 'in':'a := "第一个进程"\r\n'), code); +// 通过管道获取子进程中的当前环境变量 +SysexecWritepipe(hand, "sys1 := Sysgetenvs()\r\n"); +sleep(500); // 等待命令执行 +// 获取SysExec进程所在管道的输出内容 +t1 := ''; +while t1 = ''do +begin + t1 := SysexecReadpipe(hand); // 循环读取第一个进程的内容 + sleep(100); // 100毫秒读取一次 +end; +SysexecNewpipe(); // 再次创建管道 +// 重设子进程的环境变量组 +SysexecSetenvs(array('Test=D:\\AAATest', 'BBB=D:\\Test1'), 0); +b2 := SysexecGetenvs(); +// 第二个子进程: +hand2 := SysExec(path, 'tsl', nil, array('wait':false, 'in':'b := "第二个进程"\r\n'), code); +// 通过管道获取子进程中的当前环境变量 +SysexecWritepipe(hand2, "sys2 := Sysgetenvs()\r\n"); +sleep(500); // 等待命令执行 +// 获取SysExec进程所在管道的输出内容 +t2 := ''; +while t2 = ''do +begin + t2 := SysexecReadpipe(hand2); // 循环读取第二个进程的内容 + sleep(100); // 100毫秒读取一次 +end; +SysTerminate(code, hand); // 终止进程 +SysTerminate(code, hand2); // 终止进程 +return t1 + t2; +``` + +返回:对Sysexec进程设置的环境变量有生效 + +参考SysExec、 Sysexecgetenvs + +###### SysexecNewpipe + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建读写管道 +SysexecNewpipe(0); +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +// 非阻塞执行,返回进程句柄 +hand := SysExec(path, "tsl", nil, 0, code); +// 获取SysExec进程所在管道的输出内容 +t1 := ""; +while t1 = ""do +begin + t1 := SysexecReadpipe(hand); + sleep(100); // 100毫秒读取一次 +end; +// 向SysExec进程所在管道写入内容 +SysexecWritepipe(hand, "datetostr(today())\r\n"); +sleep(500); // 等待写入的内容执行完成,也可写成上面的循环的方式获取 +// 获取管道执行写入内容后的输出内容 +t2 := SysexecReadpipe(hand); +t3 := SysTerminate(code, hand); // 终止进程 +return array(hand, t1, t2); +``` + +返回结果如下图: + +参考SysExec、 Sysexecdeletepipe 、 Sysexecdeletepipe 、 Sysexecreadpipe 、 SysExecWritePipe + +###### SysExecWritepipe + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +// 创建读写管道 +SysexecNewpipe(0); +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +// 非阻塞执行,返回进程句柄 +hand := SysExec(path, "tsl", nil, false, code, 5000); +// 向SysExec进程所在管道写入内容 +SysExecWritepipe(hand, "datetostr(20221130T)\r\n"); +// 获取SysExec进程所在管道的输出内容 +t1 := ""; +while t1 = ""do +begin + t1 := SysexecReadpipe(hand); + sleep(100); // 100毫秒读取一次 +end; +SysTerminate(code, hand); // 终止进程 +return t1; +``` + +参考SysExec、 SysexecNewpipe 、 Sysexecdeletepipe 、 Sysexecdeletepipe 、 Sysexecreadpipe + +###### 获取COM进程 + +在一些应用开发过程中,比如office文档的调用实现中,由于office程序的不稳定现象,当我们在程序中调用了office的com进程时,office发生了错误,则会引发许多异常问题,如一直等待、或程序无法退出,或进程被挂起等等异常,此时,我们就非常希望能过将该异常的进程进行强制退出。那么,在多个进程的环境下,如何才能准确找到我需要终止的进程呢? + +为此,天软提供了SyxGetPidOfCom等函数,可以通过指定Com对象,得到该Com服务的进程ID,从而实现精准强制终止的操作。 + +####### 内容 + +- 进程ID与获取方式 +- SysGetPidOfCom +- SysGetWndOfCaption +- SysGetPidtidOfWnd +- 实例展示 + +####### 进程ID与获取方式 + +进程ID(PID)是大多数操作系统的内核用于唯一标识进程的一个数值。这一数值可以作为许多函数调用的参数,从而可以实现调整进程优先级、资源分配、关闭进程等的进程控制。 + +由于com结构中,进程ID只做了16位二进制的记录,导致其获取到的进程大小存在限制,即当进程ID<65535才有效,一旦返回值为65535则表示进程ID超过65535,就获取不到真实的进程ID,此时,我们可以通过获取窗口的进程ID来解决这个问题。 + +窗口句柄,每个窗口在被创建出来之后就会被赋予一个句柄,该句柄(句柄实则上是一个指针)指向一个数据结构体,结构体里明确表示着该窗口的各种信息,窗口大小,窗口名等,当我们得到这个句柄时就可以请求操作系统对它做一系列操作,例如:移动窗口,关闭窗口,最小化最大化等。 + +所以,获得进程ID和窗口句柄就可以灵活实现各种功能。 + +因此,天软提供两种获取Com服务进程ID的方式,如下: + +####### SysGetPidOfCom + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取TSL创建的word.application对象的进程ID。 + +```tsl +getoleobject("Word.application", 0, v); // 获取ComObj对象 +PID := SysGetPidOfCom(v); // 通过COM对象获取进程ID +Echo PID; +``` + +####### SysGetWndOfCaption + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +获取标题是”test.docx”的窗口句柄。 + +```tsl +V := SysGetWndOfCaption("test.docx"); +Echo V; +``` + +####### SysGetPidtidOfWnd + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +获取标题是”test.docx”的窗口的word的进程ID。 + +```tsl +// 获取标题是”test.docx”的窗口句柄 +Wnd := SysGetWndOfCaption("test.docx"); +// 通过窗口句柄获得进程ID +V := SysGetPidtidOfWnd(wnd[0]); +Echo v; +``` + +####### 实例展示 + +######## 内容 + +- 通过窗口句柄实现对窗口最大化、最小化 +- 通过进程id实现对进程关闭 + +######## 通过窗口句柄实现对窗口最大化、最小化 + +通过TSL获取窗口句柄后,可以使用一些windows自带的API接口对其进行操作。 + +以下就是通过Windows用户界面相关应用程序接口user32.dll中的ShowWindow,对一个test.docx窗口进行最大化,最小化(默认已经打开了此窗口)的样例代码。 + +```tsl +// 获取窗口句柄 +wnd := SysGetWndOfCaption("test.docx"); +// 是否获取成功,不成功就退出。 +if not ifarray(wnd) then return 1; +// 最小化 +ShowWindow(wnd[0], 2); +sleep(2000); +// 最大化 +ShowWindow(wnd[0], 3); +sleep(2000); +// 最小化 +ShowWindow(wnd[0], 2); +sleep(2000); +// 最大化 +ShowWindow(wnd[0], 3); +sleep(2000); +return 1; +// TSL调用user32.dll中的ShowWindow函数。 +function ShowWindow(hwnd:integer;nCmdShow:integer):boolean;external"user32.dll"name"ShowWindow"; +``` + +######## 通过进程id实现对进程关闭 + +通过进程id对进程的关闭,比如,office中因为某些原因导致崩溃或者挂起时,就可以通过获取程ID将其关闭。 + +以下就是通过进程ID关闭整个winword进程。 + +```tsl +// 通过"test.docx"获得窗口句柄("test.docx"已打开) +wnd := SysGetWndOfCaption("test.docx"); +if not ifarray(wnd) then return 1; +// 通过窗口句柄获得winword进程的pid +pid := SysGetPidtidOfWnd(wnd[0]); +if pid <= 0 then return 1; +// 通过taskkill系统命令关闭winword进程 +execHandle := sysExec('C:\\Windows\\System32\\taskkill.exe', ' /pid '$inttostr(pid)$' /f', 0, 0, return code); +return 1; +``` + +###### TSL解释器对网格计算的支持 + +天软本地脚本执行支持多线程,多线程执行采取的是线程池模式。语法与客户端使用的一样简单。只需要在一个函数或者语句前面加一个#就是把它抛给了某个线程去执行了。所以代码由普通模式改成网格模式不需要原代码作很大修改。 网格使用格式:R[i]:=#函数名(参数…) +with array(”PN1”:p1,”PN2”:p2,…) + +其中,with后面可以带入其它参数,如需要带入主程中的相关环境等系统参数时可用,在被调子程序中可通过getsysparam(“pName”)或getsysparams()等方式获取。 + +本地解释器默认是启动了网格的状态,且默认为128个最大线程。 + +若用户需要另外修改该配置,可以通过添加TSL.ININ文件的方式进行配置相关参数。 + +####### 内容 + +- TSL.INI配置说明 +- 使用范例 + +####### TSL.INI配置说明 + +第一步:在天软安装目录下,添加TSL.INI文件(存放目录与TSL.exe解释器文件保存一致)。 + +第二步:配置TSL.INI文件内容与参数 + +[multitask] + +#######本地网格计算启动的最大线程数---用户可修改其值 + +maxthread=128 + +#######最大计算任务的等待队列---用户可修改其值 + +maxpending=16777216 + +#######未完成的任务等待判断间隔毫秒数---用户可修改其值 + +busyinterval=3000 + +#######最大等待的次数---用户可修改其值 + +busyretry=100000格式如下: + +其中,maxthread即是设置最大网格线程数,当设置为maxthread=10时,则网格线程数不能超过10个。 + +第三步:保存后,重启客户端或重启解释器,就能生效。 + +例如:dosumN函数需要占用约1秒钟的时间,并发执行10次dosumN函数,大约2秒左右可以完成 + +```tsl +mtic; +r := array(); +for i := 0 to 9 do r[i] := # dosumN(i); +b := array(); +for j := 0 to length(r) - 1 do b[j] := dupvalue(r[j]); // 对并发结果进行访问,即对各网格进行等待获取结果 +echo 'time-', mtoc, '\r\n'; +echo tostn(b); +return 1; +function dosumN(n); +begin + sleep(1 * 1000); // 暂停1秒 + return sum(0 - > n); +end; +``` + +运行表现如下: + +####### 使用范例 + +在设置为5个最大线程数的情况下,运行10个线程,每个线程暂停5秒并返回id编号和线程号。 + +最后,打印所有的线程id编号和线程号,和程序运行时间,运行时间10秒多一点说明,最大线程数设置成功。 + +代码如下: + +```tsl +mtic; +a := array(); +for i := 0 to 9 do +begin + a[i] := #multirun(i); // 语句前增加标识#即可执行多线程。 +end; +echo tostn(a); +echo "总花费秒数为:", mtoc; +return 1; +function multirun(id); +begin + sleep(5000); + return array(id, systhreadid()); +end; +``` + +###### SysExec定义二 + +范例: + +范例01:阻塞方式调用子进程执行命令 + +```tsl +path := "D:\\Program Files\\Python\\Python38\\python.exe"; +// 创建管道 +ret := Sysexecnewpipe(); +// 创建成功,执行命令:获取python的版本号 +if ret then handle := SysExec(path, "py -V", nil, true, code, 5000); +else return false; +return code; +``` + +范例02:调用子进程执行TSL语言脚本 + +主程序代码: + +```tsl +path := "D:\\Program Files\\AnalyseNG.NET\\TSL.exe"; +filepath := "D:\\test\\csv\\test.tsl"; +// 创建管道 +ret := Sysexecnewpipe(); +// 创建成功,执行TSL语言脚本 +if ret then handle := SysExec(path, "tsl "$filepath, nil, true, code, 5000); +else return false; +return code; +``` + +test.tsl代码: + +```tsl +data := array((1, 2, 3), (4, 5, 6), (7, 8, 9)); +ret := ExportFile(ftxls(), "", "D:\\test\\csv\\test.xlsx", data); +// 导出成功,返回码为1 +if ret = 1 then +begin + echo "ExportFile Success"; + systerminate(1); +end else +begin + echo "ExportFile Fail:"$ret; + // 导出成功,返回码为0 + systerminate(0); +end; +return; +``` + +导出文件内容: + +范例03:非阻塞方式下执行命令并获取输出内容 + +```tsl +path := "D:\\Program Files\\Python\\Python38\\python.exe"; +// 创建管道 +ret := Sysexecnewpipe(); +// 创建成功,执行命令:获取python的版本号 +if ret then handle := SysExec(path, "py -V", nil, false, code); +else return false; +// 循环获取执行后的输出内容 +t1 := ""; +while t1 = ""do +begin + t1 := SysexecReadpipe(handle); + sleep(100); // 等待100毫秒 +end; +SysTerminate(code, handle); // 终止进程 +return t1; +``` + +范例04:非阻塞模式下通过”in”与管道输入串 + +```tsl +// 创建读写管道 +SysexecNewpipe(0); +path := "D:\\TinySoftNG\\AnalyseNG.NET\\TSL.exe"; +// 非阻塞执行,返回进程句柄,并输入命令a:="abc",'\r\n'表示回车功能 +hand := SysExec(path, "tsl", nil, array('wait':0, 'in':'a := "abc"\r\n'), code); +// 向SysExec进程所在管道写入内容 +SysexecWritepipe(hand, "datetostr(20221130T)\r\n"); +sleep(500); // 等待'in'传入的命令执行完成 +// 向管道写入获取变量a的值 +SysexecWritepipe(hand, "a\r\n"); +// 获取SysExec进程所在管道的输出内容 +t1 := ""; +while t1 = ""do +begin + t1 := SysexecReadpipe(hand); + sleep(100); // 100毫秒读取一次 +end; +SysTerminate(code, hand); // 终止进程 +return t1; +``` + +返回: + +###### dbglocalrunning + +用途:返回本地解释器正在运行的任务列表与调用栈信息。 +参数:无。 +返回:任务信息数组(包含 StartInfo/CallStack)。 + +范例 + +在本地脚本中运行下面代码: + +```tsl +t := dbglocalrunning(); +echo tostn(t); +return 1; +``` + +打印信息如下: + +array( + +("StartInfo": + +("id":"000001b9b8e30440","info":"C:\\Users\\xxxxx\\Tinysoft\\Analyse.NET\\editer\\cmpCachesnewfile\\new12.tsl","createtm":45602.6995526042),"CallStack": + +( + +("NAME":"**main**","USER":"local","LINE":3)))) + +###### dbglocalcancel + +用途:根据任务 ID 终止本地运行中的任务。 +参数: + +返回:成功返回 1,失败返回 0。 + +范例 + +```tsl +tasks := dbglocalrunning(); +task_id_hex := tasks[0]["StartInfo"]["id"]; +task_id := StrToInt("0x" + task_id_hex); +return dbglocalcancel(task_id); +``` + +###### SysThreadSelf + +用途:获取当前线程 ID(Linux 下为 pthread_t)。 +参数:无。 +返回:线程 ID(整数)。 + +范例 + +在客户端中,本地执行如下代码: + +```tsl +return SysThreadSelf(); +// 返回值:线程ID,如11000 +``` + +通过cmd查看天软客户端进程与线程,结果如下: + +###### syslinuxkrnlclosemutex + +用途:关闭并清理指定互斥量(Linux),用于移除互斥相关的系统信号量与临时文件。 +参数: + +返回:成功返回 1,失败返回 0。 + +范例 + +```tsl +return syslinuxkrnlclosemutex("ts_mutex_demo", 0); +``` + +###### SysSetThreadPriority + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:设置当前线程优先级 + +```tsl +ret := SysSetThreadPriority(1); +if ret = 0 then return 1; +else return "设置线程优先级失败!"; +``` + +结果:返回1,设置成功。 + +范例02:设置指定线程优先级 + +```tsl +// 创建函数指针 +c := makeinstance(thisfunction(FuncPos), "cdecl", 1); +// 创建线程 +handle := CreateThread(nil, 10240000, c, nil, 0, tid); +ret := SysSetThreadPriority(1, tid); +if ret = 0 then return 1; +else return "设置线程优先级失败!"; +// 定义WindowsAPI的CreateThread函数声明。 +function CreateThread(attr:pointer;size:pointer;addr:pointer;p:pointer;flag:Integer;var threadid:Integer):pointer;external"kernel32.dll"name"CreateThread"; +// 自定义函数,用于创建函数指针 +function FuncPos(p:pointer):integer; +begin + sleep(random(3000)); + return 1; +end; +``` + +结果:返回1,设置成功。 + +###### SysGetThreadPriority + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取当前线程优先级 + +```tsl +ret := SysGetThreadPriority(pri); +if ret = 0 then return pri; +else return "获取线程优先级失败!"; +``` + +范例02:获取指定线程优先级 + +```tsl +tid := 18024; // 指定线程ID +ret := SysGetThreadPriority(pri, tid); +if ret = 0 then return pri; +else return "获取线程优先级失败!"; +``` + +###### SysSetProcessPriority + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:设置当前进程优先级 + +```tsl +ret := SysSetProcessPriority(32); +if ret = 0 then return 1; +else return "设置进程优先级失败!"; +``` + +结果:返回1,设置成功。 + +范例02:设置指定线程优先级 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysSetProcessPriority(32, 2932); +if ret = 0 then return 1; +else return "设置进程优先级失败!"; +``` + +结果:返回1,设置成功。 + +###### SysGetProcessPriority + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取当前进程优先级 + +```tsl +ret := SysGetProcessPriority(pri); +if ret = 0 then return pri; +else return "获取进程优先级失败!"; +``` + +范例02:获取指定线程优先级 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetProcessPriority(pri, 2932); +if ret = 0 then return pri; +else return "获取进程优先级失败!"; +``` + +###### SysGetProcessList + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +ret := SysGetProcessList(); +if ret <> 0 then return ret; +else return "当前进程列表信息失败!"; +``` + +部分结果如下: + +###### SysGetProcessListw + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +ret := SysGetProcessListw(); +if ret <> 0 then return ret; +else return "当前进程列表信息失败!"; +``` + +部分结果如下: + +###### SysGetProcessNamePath + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取指定进程路径 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetProcessNamePath(2932); +if ret then return ret; +else return "获取指定进程路径失败!"; +``` + +###### SysGetProcessNamePathw + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取指定进程路径 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetProcessNamePathw(2932); +if ret then return ret; +else return "获取指定进程路径失败!"; +``` + +###### SysGetProcessCmdLine + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取指定进程的cmd执行命令 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetProcessCmdLine(2932); +if ret then return ret; +else return "获取指定进程执行命令失败!"; +``` + +###### SysGetProcessCmdLinew + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取指定进程的cmd执行命令 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetProcessCmdLinew(2932); +if ret then return ret; +else return "获取指定进程路径失败!"; +``` + +###### SysSetThreadName + +用途:设置线程名称(Linux 仅支持当前线程)。 +参数: + +返回:成功返回 0,失败返回非 0。 + +范例 + +范例01:设置当前线程名称 + +```tsl +ret := SysSetThreadName("TinySoft"); +if ret = 0 then return 1; +else return "设置线程名称失败!"; +``` + +结果:返回1,设置成功。 + +范例02:设置指定线程名称 + +```tsl +// 创建函数指针 +c := makeinstance(thisfunction(FuncPos), "cdecl", 1); +// 创建线程 +handle := CreateThread(nil, 10240000, c, nil, 0, tid); +ret := SysSetThreadName("TinySoft", tid); +if ret = 0 then return 1; +else return "设置线程名称失败!"; +// 定义WindowsAPI的CreateThread函数声明。 +function CreateThread(attr:pointer;size:pointer;addr:pointer;p:pointer;flag:Integer;var threadid:Integer):pointer;external"kernel32.dll"name"CreateThread"; +// 自定义函数,用于创建函数指针 +function FuncPos(p:pointer):integer; +begin + sleep(random(3000)); + return 1; +end; +``` + +结果:返回1,设置成功。 + +###### SysGetThreadName + +用途:获取线程名称。 +参数: + +返回:线程名称字符串;失败返回 nil 或空串。 + +范例 + +范例01:获取当前线程名称 + +```tsl +ret := SysGetThreadName(); +if ret then return ret; +else return "获取线程名称失败!"; +``` + +范例02:获取指定线程名称 + +```tsl +tid := 18024; // 指定线程ID +ret := SysGetThreadName(tid); +if ret then return ret; +else return "获取线程名称失败!"; +``` + +###### SysGetThreads + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +范例01:获取当前进程内的线程列表 + +```tsl +ret := SysGetThreads(); +if istable(ret) then return ret; +else return "获取进程内的线程列表失败!"; +``` + +部分结果截图如下: + +范例02:获取指定进程内的线程列表 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetThreads(2932); +if istable(ret) then return ret; +else return "获取进程内的线程列表失败!"; +``` + +###### SysPPid + +用途:进程相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +范例01:获取当前进程的父进程ID + +```tsl +ret := SysPPid(); +if ret then return ret; +else return "获取进程的父进程ID失败!"; +``` + +范例02:获取指定进程的父进程ID + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysPPid(28848); +if ret then return ret; +else return "获取进程的父进程ID失败!"; +``` + +###### SysGetSubProcesses + +用途:进行字符串提取或替换处理。 +参数:无。 +返回:处理后的结果值。 + +范例 + +范例01:获取当前进程的子进程列表 + +```tsl +ret := SysGetSubProcesses(); +if istabel(ret) then return ret; +else return "获取进程的子进程列表失败!" +``` + +范例02:获取指定进程的子进程列表 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysGetSubProcesses(2932); +if istabel(ret) then return ret; +else return "获取进程的子进程列表失败!" +``` + +###### SysKill + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:终止指定进程 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysKill(2932); +if ret then return ret; +else return "获取进程的子进程列表失败!" +``` + +结果:返回1,任务管理器显示如下 + +###### SysPidOfTid + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取当前线程所属进程 + +```tsl +tid := SysThreadId(); // 获取当前线程ID +ret := SysPidOfTid(tid); +if ret then return ret; +else return "获取线程所属进程ID失败!" +``` + +###### SysPidOfHandle + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:根据进程句柄获取进程ID + +```tsl +// TSL解析器路径 +path := "D:\\Program Files\\AnalyseNG.NET\\TSL.exe"; +// 创建管道 +ret := SysExecNewPipe(); +// 创建一个TSL解析器进程 +if ret then handle := SysExec(path, "TSL", nil, 0, code); // 返回进程句柄 +ret := SysPidOfHandle(handle); +SysTerminate(rc, handle); // 关闭TSL解析器进程 +if ret then return ret; +else return "根据进程句柄获取进程ID失败!" +``` + +###### SysHandleOfPid + +用途:进程相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例01:根据进程ID获取进程句柄 + +打开记事本,在任务管理器中查找对应进程ID: + +```tsl +ret := SysHandleOfPid(35880); +if ret then return ret; +else return "根据进程ID获取进程句柄失败!" +``` + +##### 本地资源相关函数 + +###### 内容 + +- SysExecName +- PluginPath +- FileInfo +- Getlogicdrive +- GetDeviceFree +- Getdeviceinfo +- Createlink +- Realpath +- Sysclientinfo + +###### SysExecName + +用途:获取当前执行程序的完整路径。 +参数:无。 +返回:程序路径字符串。 + +范例 + +客户端中本地执行 + +```tsl +return rdo2 SysExecName(); +``` + +返回:C:\Program Files\Tinysoft\AnalyseNG.NET\TSExpert.exe + +本地解析器中运行 + +```tsl +echo SysExecName(); +``` + +打印信息:C:\Program Files\Tinysoft\AnalyseNG.NET\TSL.exe + +###### PluginPath + +用途:获取插件目录路径。 +参数:无。 +返回:插件路径字符串。 + +范例 + +客户端中本地执行 + +```tsl +return rdo2 PluginPath(); +``` + +返回:C:\Program Files\Tinysoft\AnalyseNG.NET\Plugin\ + +###### FileInfo + +用途:本地资源相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取本地TSL.exe文件的基本信息 + +```tsl +path := "D:\\Program Files\\Analyse.NET\\TSL.exe"; +return rdo2 FileInfo("", path); +``` + +范例02:获取本地已被链接的txt文件信息 + +```tsl +path := "D:\\test\\test.txt"; +return rdo2 FileInfo("", path); +``` + +###### Getlogicdrive + +用途:本地资源相关函数相关函数。 +参数:无。 +返回:处理后的结果值。 + +范例 + +```tsl +return rdo2 Getlogicdrive(); +// 有C、D盘,结果为12,即0b1100 +``` + +###### GetDeviceFree + +用途:本地资源相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +return rdo2 GetDeviceFree("", "C:/"); +``` + +###### Getdeviceinfo + +用途:本地资源相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例获取C盘的信息 + +```tsl +return rdo2 Getdeviceinfo("", "C:/"); +``` + +###### Createlink + +用途:本地资源相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:创建硬链接 + +```tsl +path := "D:\\test\\test.txt"; // 已经存在的文件 +return rdo2 Createlink("D:\\test\\txt", path, 1); // 创建一个硬链接 +``` + +结果:创建链接成功,返回1 + +范例02:创建软链接 + +```tsl +path := "D:\\test\\test.txt"; // 已存在的文件 +return rdo2 Createlink("D:\\test\\txt", path, 0); // 创建一个软链接 +``` + +结果:链接成功,返回1 + +###### Realpath + +用途:本地资源相关函数相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +范例01:获取文件的真实路径 + +```tsl +path := "D:\\test\\test.txt"; +return rdo2 Realpath(path); +``` + +范例02:获取软链接的真实路径 + +```tsl +path := "D:\\Links\\soft\\s2"; +return rdo2 Realpath(path); +``` + +范例03:获取硬链接的真实路径 + +```tsl +path := "D:\\Links\\hard\\h1"; +return rdo2 Realpath(path); +``` + +###### Sysclientinfo diff --git a/data/tsl_reference_catalog_source/system.md b/data/tsl_reference_catalog_source/system.md new file mode 100644 index 00000000..f627a289 --- /dev/null +++ b/data/tsl_reference_catalog_source/system.md @@ -0,0 +1,1598 @@ +#### 系统相关函数 + +##### 内容 + +- 数据类型函数 +- 数据类型转换函数 +- 复制函数 +- 随机函数 +- 条件选择函数 +- 表达式相关函数 +- 性能优化相关函数 +- 函数库路径 +- 调用堆栈 + +##### 数据类型函数 + +###### 内容 + +- DataType +- ifInt +- ifInt64 +- ifReal +- ifNumber +- ifString +- ifArray +- ifNil +- ifExp +- ifGraph +- ifGraphGroup +- ifBinary +- ifMatrix +- ifObj +- GetOleObject +- CreateComObject +- CreateMatrix +- MatrixToArray +- GetMatrixFields +- CreateBinary +- ConvertDataToBuf +- ConvertBufToData +- None类型 + +###### DataType + +用途:返回数据类型编号,支持数组遍历模式。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:类型编号或类型数组。 + +范例 + +```tsl +// 当参数为数组型变量时,返回数组类型对应的整数5。 +a := array(34, 12); // 定义a为一个数组 +result := DataType(a); +return result; // 5 + +// 当参数为整数型变量时,返回整数类型对应的整数0。 +a := 23; // 定义a为一个整数 +result := DataType(a); +return result; // 0 + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.14, "A", (1, 2, 3), nil); +return DataType(t, -1); + +// 对数组中每一数据进行类型判断 +t := array(1, 3.14, "A", (1, 2, 3), nil); +return DataType(t, 1); +``` + +###### ifInt + +用途:判断是否为 32 位整数类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +范例一: + +```tsl +// 判断是否为32位整数类型 +r1 := ifInt(1); +r2 := ifInt(3.14); +r3 := ifInt("A"); +r4 := ifInt(array(1, 2, 3)); +return array(r1, r2, r3, r4); +// 结果:array(1,0,0,0) +``` + +范例二: + +```tsl +// 对数组第一维度数据进行类型判断 +t := array(1, 3.14, "A", (1, 2, 3), nil); +return ifInt(t, -1); +// 结果:array(1,0,0,0,0) +``` + +范例三: + +```tsl +// 对数组中每一数据进行类型判断 +t := array(1, 3.14, "A", (1, 2.1, 3), nil); +return ifInt(t, 1); +// 结果:array(1,0,0,(1,0,1),0) +``` + +###### ifInt64 + +用途:判断是否为 64 位整数类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为整数类型变量时,返回true。 +a := 23L; // 定义a为一个64位整数 +return ifInt64(a); + +// 当参数为非整数型变量时,返回false。 +a := 2.3; // 定义a为一个非64位整数 +return ifInt64(a); + +// 对数组第一维度数据进行类型判断 +t := array(1, 3L, "A", (1, 2, 3), nil); +return ifInt64(t, -1); +// 结果:array(0,1,0,0,0) + +// 对数组中每一数据进行类型判断 +t := array(1, 3L, "A", (1, 2L, 3), nil); +return ifInt64(t, 1); +// 结果:array(0,1,0,(0,1,0),0) +``` + +###### ifReal + +用途:判断是否为 实数类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为实数类型变量时,返回true。 +a := 2.233; // 定义a为一个实数 +result := ifReal(a); +return result; + +// 当参数为非整数型变量时,返回false。 +a := array(23, 54, 67); // 定义a为一个非实数 +result := ifReal(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.56, "A", (1, 2, 3), nil); +return ifReal(t, -1); +// 结果:array(0,1,0,0,0) + +// 对数组中每一数据进行类型判断 +t := array(1, 3.56, "A", (1, 2.14, 3), nil); +return ifReal(t, 1); +// 结果:array(0,1,0,(0,1,0),0) +``` + +###### ifNumber + +用途:判断是否为 数字(整数或实数)类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为数字类型(整数或者实数)变量时,返回true。 +a := 2.233; // 定义a为一个实数 +result := ifNumber(a); +return result; + +// 当参数为非数字类型(整数或者实数)变量时,返回false。 +a := array(23, 54, 67); // 定义a为一个非数字类型 +result := ifNumber(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.56, "A", (1, 2, 3), nil); +return ifNumber(t, -1); +// 结果:array(1,1,0,0,0) + +// 对数组中每一数据进行类型判断,nan也为数字类型 +t := array(1, 3.56, "A", (nan, 2.14, "C"), nil); +return ifNumber(t, 1); +// 结果:array(1,1,0,(1,1,0),0) +``` + +###### ifString + +用途:判断是否为 字符串类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为字符串类型变量时,返回true。 +a := 'test'; // 定义a为一个字符串 +result := ifString(a); +return result; + +// 当参数为非字符串类型变量时,返回false。 +a := array(23, 54, 67); // 定义a为一个非字符串 +result := ifString(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.56, "A", (1, 2, 3), nil); +return ifString(t, -1); +// 结果:array(0,0,1,0,0) + +// 对数组中每一数据进行类型判断 +t := array(1, 3.56, "A", (nan, 2.14, "C"), nil); +return ifString(t, 1); +// 结果:array(0,0,1,(0,0,1),0) +``` + +###### ifArray + +用途:判断是否为 数组类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为数组类型变量时,返回true。 +a := array(23, 54, 67); // 定义a为一个数组 +result := ifArray(a); +return result; + +// 当参数为非数组类型变量时,返回false。 +a := 34; // 定义a为一个非数组 +result := ifArray(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.56, "A", (1, "C", 3.14), nil); +return ifArray(t, -1); +// 结果:array(0,0,0,1,0) + +// 对数组中每一数据进行类型判断 +t := array(1, 3.56, "A", (nan, 2.14, "C"), nil); +return ifArray(t, 1); +// 结果:array(0,0,0,(0,0,0),0) +``` + +###### ifNil + +用途:判断是否为 Nil类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数为空时,返回true。 +result := ifNil(nil); // 函数参数为空 +return result; + +// 当参数不为空时,返回false。 +a := 34; // 函数参数不为空 +result := ifNil(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.16, "A", (nil, "C", 3.14), nil); +return ifNil(t, -1); +// 结果:array(0,0,0,0,1) + +// 对数组中每一数据进行类型判断 +t := array(1, 3.56, "A", (nil, 2.14, "C"), nil); +return ifNil(t, 1); +// 结果:array(0,0,0,(1,0,0),1) +``` + +###### ifExp + +用途:判断是否为 表达式类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个表达式类型时,返回true。 +a := @'dfhdv' + 'dbf'; // 函数参数a为一个表达式 +result := ifExp(a); +return result; + +// 当参数不是一个表达式类型时,返回false。 +a := 'sdhv' + 'dbf'; // 函数参数a不为表达式 +result := ifExp(a); +return result; + +// 对数组第一维度数据进行类型判断 +t := array(1, 3.16, @"A", (nil, @"C", 3.14), nil); +return ifExp(t, -1); +// 结果:array(0,0,1,0,0) + +// 对数组中每一数据进行类型判断 +t := array(1, 3.56, @"A", (nil, 2.14, @"C"), nil); +return ifExp(t, 1); +// 结果:array(0,0,1,(0,0,1),0) +``` + +###### ifGraph + +用途:判断是否为 图形类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个图形类型时,返回true。 +GData := Nday2('MA5', MA( close() , 5 ) ); +g1 := graph( gtLine() , "MA5", Gdata , gfColor() , clBlue() ); +result := ifGraph(g1); +return result; + +// 当参数不是一个图形类型时,返回false。 +a := 'sdhv' + 'dbf'; // 函数参数a不为图形类型 +result := ifGraph(a); +return result; +``` + +参考TGraph + +###### ifGraphGroup + +用途:判断是否为 图形组类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个图形组合类型时,返回true。 +VolData := Nday2(GfVol() , Vol() , gfColor() , ifthen ( Close() > Open() , ClRed() , ClGreen() ) ); +MAVOL := Nday2('MA5', MA ( Vol() , 5 ) ); +VOLGraph := Graph(gtBar(), 'VOLGraph', VolData); +MAVOLGraph := Graph(gtLine(), 'MA5Graph', MAVOL, gfColor(), clBlue()); +g1 := GraphGroup(VOLGraph, MAVOLGraph, gfMinValue(), 0); +// 调用函GraphGroup创建一个图形组合类型变量g1 +result := ifGraphGroup(g1); +return result; + +GData := Nday2('MA5', MA( close() , 5 ) ); +g1 := graph( gtLine() , "MA5", Gdata , gfColor() , clBlue() ); +result := ifGraphGroup(g1); +return result; +// 返回0 +``` + +参考TGraphGroup + +###### ifBinary + +用途:判断是否为 二进制/Buffer类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个二进制类型时,返回true。 +a := binary('111111'); // 函数参数a为二进制类型 +result := ifBinary(a); +return result; + +// 当参数不是一个二进制类型时,返回false。 +a := 'sdhv'; // 函数参数a不为二进制类型 +result := ifBinary(a); +return result; + +// 对数组第一维度数据进行类型判断 +b := Binary("3.14"); +t := array(1, b, "A", (nil, b, 3.14), nil); +return ifBinary(t, -1); +// 结果:array(0,1,0,0,0) + +// 对数组中每一数据进行类型判断 +b := Binary("3.14"); +t := array(1, b, "A", (nil, 2.14, b), nil); +return ifBinary(t, 1); +// 结果:array(0,1,0,(0,0,1),0) +``` + +参考Binary + +###### ifMatrix + +用途:判断是否为 Matrix类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个Matrix类型时,返回true。 +a := CreateMatrix(3, 4); // 使用CreateMatrix创建一个Matrix类型变量 +result := ifMatrix(a); +return result; + +// 当参数不是一个Matrix类型时,返回false。 +a := 'sdhv'; // 函数参数a不为Matrix类型 +result := ifMatrix(a); +return result; +``` + +###### ifObj + +用途:判断是否为对象类型。 +参数: + +- value:输入数据 +- mode:遍历模式(可选;-1 对第一维逐项判断;1 对每个元素判断) + 返回:布尔值或布尔数组。 + +范例 + +```tsl +// 当参数是一个对象类型时,返回true。 +type Function14 = class()//声明类 +function SetName(newName); +begin + name := newName; +end; +end; +Obj := CreateObject('Function14'); // 使用CreateObject函数创建上面类Function14的对象 +result := ifObj(Obj); +return result; + +// 当参数不是一个对象类型时,返回false。 +a := 'sdhv'; // 函数参数a不为对象类型 +result := ifObj(a); +return result; +``` + +参考ComObj + +###### GetOleObject + +用途:获取已注册的 OLE/COM 对象实例(仅 Windows)。 +参数: + +- prog_id:COM ProgID(如 "Word.Application") +- flags:选项标记(可选,通常为 0) +- out_obj:输出对象变量 + 返回:是否获取成功(1/0)。 + +###### CreateComObject + +用途:创建新的 OLE/COM 对象实例(仅 Windows)。 +参数: + +- prog_id:COM ProgID(如 "Word.Application") + 返回:COM 对象实例;失败返回 nil。 + +说明:COM 对象仅在 Windows 可用,Linux 不支持。 + +###### CreateMatrix + +用途:创建 Matrix 类型数据,可指定列索引与初始值。 +参数: + +- rows:行数 +- cols:列数 +- cols_value:列序列(可选) +- values:初始化值序列(可选,按行列顺序) + 返回:Matrix 对象。 + +范例 + +对比范例一与范例二,即Matrix与矩阵类型的比较 + +范例一:Matrix + +```tsl +// 当没有ColsValue参数,返回的MATRIX的行和列的下标为从0开始的序列 +return CreateMatrix(2, 3); +``` + +范例二:矩阵 + +```tsl +return nils(3, 2); +``` + +范例三: + +```tsl +// 有ColsValue参数并初始化该Matrix时,返回的MATRIX的列序列为ColsValue数组中//的字符串或整数 +return CreateMatrix(3, 4, array('s', 'd', 'f'), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); +``` + +###### MatrixToArray + +用途:将 Matrix 转换为数组。 +参数: + +- matrix:Matrix 数据 + 返回:数组。 + +范例 + +```tsl +// 使用CreateMatrix创建一个Matrix,把这个Matrix转换为一个数组后返回该数组。 +a := CreateMatrix(3, 4, array('s', 'd', 'f'), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); +return MatrixToArray(a); + +// 把TS的矩阵转化成Matrix类型数据 +a := ones(5, 5); +return mselect * from a end; +``` + +###### GetMatrixFields + +用途:获取 Matrix 的字段(列名)列表。 +参数: + +- matrix:Matrix 数据 + 返回:字段名数组。 + +###### CreateBinary + +用途:创建 Binary 缓冲区。 +参数: + +- size:字节长度 + 返回:Binary 数据。 + +###### ConvertDataToBuf + +用途:按指定类型将数据编码为内存 Buffer。 +参数: + +- value:输入数据 +- type_name:类型名称 + 返回:Binary Buffer。 + +范例 + +```tsl +// 将一个数据转换成内存存贮的BUFFER并返回 +return ConvertDataToBuf(1.5343, 'Currency'); +``` + +###### ConvertBufToData + +用途:按指定类型将 Buffer 解码为数据。 +参数: + +- buffer:Binary Buffer +- type_name:类型名称 + 返回:解析后的数据。 + +###### None类型 + +None类型是一种极为特殊的特性,不参与运算,仅在特殊场景传递。None类型本身可以包含一个整数。 + +目前用于对象算符重载[]的数组设置算符时候,重载函数送入的第一个参数是索引值,第二个参数在非最后一级时设置为None类型,用于描述级别信息(最后一级送入的是要设置的值)。 + +####### 内容 + +- ifNone +- GetNone + +####### ifNone + +用途:判断是否为 None 类型。 +参数: + +- value:输入数据 + 返回:布尔值。 + +具体应用可参考:FAQ:对象算符重载数组set算符时none类型的应用实例 + +####### GetNone + +用途:获取 None 类型值(可携带整数标记)。 +参数: + +- tag:整数标记(可选) + 返回:None 值。 + +具体应用可参考:FAQ:对象算符重载数组set算符时none类型的应用实例 + +##### 数据类型转换函数 + +###### 内容 + +- Integer +- Int64 +- Real +- String +- WideString +- Binary +- SetPrecision +- ToSTM +- ToSTN +- ToXML +- STM +- STN +- XML +- ExportCsv +- ImportCsv + +###### Integer + +用途:将数值转换为整数。 +参数: + +- value:输入数值 + +返回:整数。 + +范例 + +```tsl +return Integer(123.456); // 返回值为整型数据:123。 +``` + +###### Int64 + +用途:将数值转换为 64 位整数。 +参数: + +- value:输入数值 + +返回:64 位整数。 + +范例 + +```tsl +return Int64(123); // 返回值为64位整型数据:123。 +``` + +###### Real + +用途:将数值转换为实数。 +参数: + +- value:输入数值 + +返回:实数。 + +范例 + +```tsl +return Real(123); // 返回值为实数数据:123.00 +``` + +###### String + +用途:将数据转换为字符串。 +参数: + +- value:输入数据 + +返回:字符串。 + +范例 + +```tsl +return String(L'abcd'); +// 返回值为字符串:abcd。 +``` + +###### WideString + +用途:将数据转换为 Unicode 字符串。 +参数: + +- value:输入数据 + +返回:Unicode 字符串。 + +范例 + +```tsl +return WideString('abcd'); +// 返回值为Unicode字符串:L’abcd’。 +``` + +###### Binary + +用途:将数据转换为二进制流。 +参数: + +- value:输入数据 + +返回:Binary 数据。 + +范例 + +```tsl +return Binary('111111'); // 返回值为二进制流。 +``` + +###### SetPrecision + +用途:设置数值的小数精度。 +参数: + +- value:输入数值 +- digits:小数位数 + +返回:按精度处理后的数值。 + +范例 + +```tsl +return SetPrecision(123.4567, 3); // 返回值为保留3位小数点后的实数:123.457。 +``` + +###### ToSTM + +用途:将数据序列化为 STM 二进制流。 +参数: + +- value:输入数据 +- mode:序列化模式(可选) +- precision:小数位数(可选) + +返回:STM 二进制流。 + +范例 + +```tsl +return ToSTM(array(1, 23, 4, 5, 6, 7, )); // 返回以.stm为后缀名的二进制文件。 +``` + +可选参数的应用 + +```tsl +t := rand(4, 5); +s := ToSTM(t, 0, 1, 2); // 用新流模式,且保留两位小数 +return stm(s); +``` + +返回如下: + +###### ToSTN + +用途:将数值格式化为 STN 字符串。 +参数: + +- value:输入数值 +- digits:小数位数(可选) + +返回:字符串。 + +范例 + +范例一: + +```tsl +return ToSTN(12345); // 返回值为字符串:’12345’。 +``` + +范例二: + +```tsl +return ToSTN(1.2345, 2); // 返回值为字符串:’1.23’。 +``` + +###### ToXML + +用途:将数据转换为 XML 字符串表示。 +参数: + +- value:待转换的数据 + +返回:XML 字符串。 + +范例 + +```tsl +return ToXML("this is XML document"); +// 返回值示例: +// +// +``` + +差异说明仅windows中支持,Linux中暂不支持。 + +###### STM + +###### STN + +###### XML + +用途:解析 TSXML 字符串并返回内容。 +参数: + +- xml_text:TSXML 字符串 + +返回:解析结果值。 + +范例 + +```tsl +return XML('' + + ' '); +// 返回值示例:"this is a document"。 +``` + +差异说明仅windows中支持,Linux中暂不支持。 + +###### ExportCsv + +用途:将数组导出为 CSV 格式字符串。 +参数: + +- data:数组数据 +- out_text:输出字符串(引用返回) +- include_index:是否包含下标(可选,1/0) +- include_header:是否包含表头(可选,1/0) + +返回:是否成功(1/0)。 + +范例 + +范例01:一维数组转换成csv格式字符串 + +```tsl +data := array(1, 2, "3", "A", 9, 8); +ret := ExportCsv(data, s); +if ret then return s; +else return ret; +``` + +范例02:二维数组转换成csv格式字符串 + +```tsl +data := array((2, 5, 0), (3, 2, 1), (4, 7, 2)); +ret := ExportCsv(data, s); +if ret then return s; +else return ret; +``` + +范例03:转换成csv格式字符串,结果包含数组下标信息 + +```tsl +data := array("A":(2, 5, 0), "B":(3, 2, 1), "C":(4, 7, 2)); +ret := ExportCsv(data, s, 1); +if ret then return s; +else return ret; +``` + +范例04:转换成csv格式字符串,结果不包含字段头部信息 + +```tsl +data := array((2, 5, 0), (3, 2, 1), (4, 7, 2)); +ret := ExportCsv(data, s, 0, 0); +if ret then return s; +else return ret; +``` + +###### ImportCsv + +用途:将 CSV 字符串解析为数组。 +参数: + +- csv_text:CSV 字符串 +- out_data:输出数组(引用返回) +- has_header:是否包含表头(可选,1/0) + +返回:是否成功(1/0)。 + +范例 + +范例01:将指定csv格式字符串转换成二维数组 + +```tsl +s := "0,1,2\r\n2,5,0\r\n3,2,1\r\n4,7,2\r\n"; +ret := ImportCsv(s, data); +if ret then return data; +else return ret; +``` + +范例02:读取本地csv文件,并将其转换成数组 + +本地csv文件内容如下: + +```tsl +filepath := "D:\\test\\csv\\data.csv"; +rdo2 ReadFile(rwRaw(), "", filepath, 0, 1000, s); +ret := ImportCsv(s, data, 1); +if ret then return data; +else return ret; +``` + +##### 复制函数 + +###### 内容 + +- dupValue + +###### dupValue + +用途:复制值,避免被调用函数修改原变量。 +参数: + +- value:输入值 + +返回:复制后的值。 + +范例 + +```tsl +// 主函数 +function test1(); +begin + a := 1; + b := 2; + c := 3; + d := test2(dupValue(a), b, c); + return array(a, b, c, d); +end; +// 返回array(1,20,3,33) +// 被调用函数 +function test2(a, b, c); +begin + a := 10; + b := 20; + return a + b + c; +end; +``` + +由test1执行出来的结果可以知道,a变量,由于使用了dupValue复制值,虽然在子函数test2中改变了其值,但在主函数中的a变量仍然没变。而b变量则发生了改变。 + +##### 随机函数 + +###### 内容 + +- randomize +- random +- RandomFrom + +###### randomize + +参考random RandomFrom + +###### random + +用途:生成随机数。 +参数:value 为上限(可选);不传则生成 0~1 之间随机实数。 +返回:随机实数或随机整数。 + +定义1:random():Real; + +说明:返回一个0到1之间的随机数 + +返回:实数。 + +定义2:random(value:Integer):Integer; + +说明:如果无参数,则返回0->1之间的随机实数,如果参数为整数,则返回0->value之间的随机整数(不包括value),即左闭右开,如random(1)只会返回0。 + +参数: + +- max_value:上限(可选;不传返回 0~1 之间随机实数;传整数返回 [0, max_value) 随机整数) + +范例: + +```tsl +// 表达式无参数 +return random(); // 返回值为0到1随机实数:0.124562。 + +// 表达式有参数 +return random(100); // 返回值为随机的0到100的整型数据:94。 +``` + +参考:RandomFrom + +###### RandomFrom + +用途:从数组中随机取一个元素。 +参数: + +- items:候选数组 + +返回:随机元素。 + +范例 + +```tsl +items := array('a', 'b', 'c', 'd', 'e', 'f'); +return RandomFrom(items); +// 返回值为随机返回 items 中一个字符:'b'。 +``` + +参考random + +##### 条件选择函数 + +###### 内容 + +- IfThen +- IfThen3 + +###### IfThen + +用途:条件成立返回 true_value,否则返回 false_value。 +参数: + +- condition:判断条件 +- true_value:条件成立时返回值 +- false_value:条件不成立时返回值 + +返回:true_value 或 false_value。 + +范例 + +```tsl +left_value := 1; +right_value := 2; +return IfThen(left_value > right_value, left_value, right_value); +// 返回:2。 +``` + +###### IfThen3 + +用途:比较两个值,返回大/等/小对应结果。 +参数: + +- left:左值 +- right:右值 +- greater_value:left > right 时返回 +- equal_value:left = right 时返回 +- less_value:left < right 时返回 + +返回:对应比较结果的值。 + +范例 + +```tsl +return IfThen3(1, 2, '左大', '相等', '右大'); +// 返回:’右大’ +``` + +##### 表达式相关函数 + +###### 内容 + +- Eval +- Call +- CallInArray +- Invoke +- Invokeinarray +- SafeEval +- DoubleVariableExecute +- MultipleExecute +- SingleVariableExecute +- SafeSetSysParam + +###### Eval + +用途:计算表达式或表达式字符串并返回结果。 +参数: + +- expr:表达式(@)或表达式字符串(&) + +返回:表达式计算结果。 + +范例 + +范例01: + +```tsl +// 表达式是字符串表达式。&转换字符串为表达式。 +A := '1'; +B := '2'; +return Eval(&('A+B')); // 返回值为表达式的结果:'12'。 +``` + +范例02: + +```tsl +// 表达式是语句表达式 +A := 1; +B := 2; // A,B均为整型数据 +return Eval(@(A + B)); +// 返回值为整型数据:3,@(A+B)可以是一个执行语句块,调用该函数会得到执行语句块后的结果。 +``` + +范例03://字符串表达式中进行return返回。 + +```tsl +s := 'a := 1;b := 2;return a+b;'; +return Eval(&s); +``` + +结果:3 + +范例4:跨函数中传导引用参数和变量 + +```tsl +setsysparam(pn_stock(), "SH600507"); +return eval_test("StockZf4(t)", 20250723t); +function eval_test(e, endt); +begin + t := specdate(ref(sp_time(), 1), endt); + return array(datetostr(t), Eval(&e)); +end; +``` + +参考Call CallInArray + +###### Call + +用途:按函数名字符串或函数指针调用函数。 +参数: + +- func:函数名字符串或函数指针 +- args:调用参数列表 + +返回:函数返回值。 + +范例 + +```tsl +// 采用字符串方式来调用函数 +return Call("IntTodate", 20140101); +// 返回41640 + +// 采用函数指针来调用函数 +F := ThisFunction(IntToDate); +return Call(F, 20140101); +// 返回41640 +``` + +参考Eval THISFUNCTION CallInArray + +###### CallInArray + +用途:以参数数组调用指定函数(含函数名或函数变量)。 +参数: + +- func:函数名字符串或函数指针 +- args:参数数组 + +返回:函数调用结果。 + +范例 + +范例1:根据函数名称调用,第一个参数为函数名称 + +```tsl +return CallInArray("StrToIntDef", array('1234', 999)); +// 返回1234 +``` + +范例2:调用匿名函数,第一个参数是指向匿名函数的变量 + +```tsl +{func1是一个变量,我们将一个函数体赋值给这个变量,变量型函数我们称为匿名函数,匿名函数的语句段放在某个函数体内,调用的时候,需使用call或callinarray函数进行调用。 +// 这个例子中,a是一个变量,当a在func1匿名函数中,并在匿名函数体重修改a,使a := a + 10; ,但执行完匿名函数后,a参数的值是不变的,即不支持变参,所以最后返回a为10,b为20。 +callinarray在这里执行匿名函数func1时,其参数不需要跟在func1之后。} +a := 10; +func1 := function(a) begin + a := a + 10; + return a; +end; +b := CallInArray(func1, array(a)); +return array(a, b); +// array(10,20) +``` + +范例3:根据函数指针调用,第一个参数为函数指针 + +```tsl +{thisfunction()函数可获得函数指针;由于调用的是stockzf3,该函数没有参数,因此,callinarray的第二个参数给空数组} +setsysparam(pn_stock(), 'SH000001'); +return CallInArray(thisfunction(stockzf3), array()); +``` + +范例04:调用时指定参数传参 + +```tsl +function CCC(a, b, c, d); // 展示各参数的值 +begin + echo "A:", a, " B:", b, " C:", c, " D:", d; + return b; +end; +// 调用 +return CallInArray("CCC", array("b":1, "d":4)); +``` + +返回:1 + +打印结果:A: B:1 C: D:40 + +解析:callINArray在通过数组传参数时,可以通过指定下标的方式给指定参数进行传参,下标对应函数定义中的变量名。 + +上面示例中,只对参数b与d进行了传参,其它两参数没有进行传值,所以是nil。 + +参考Eval THISFUNCTION Call + +###### Invoke + +用途:调用对象成员方法或设置成员属性。 +参数: + +- obj:目标对象 +- name:成员名 +- mode:0 调用方法;1 设置成员 +- args:方法参数或设置值 + +返回:调用结果或设置结果。 + +范例 + +范例01:设置成员变量后调用成员方法并返回结果 + +```tsl +obj := new classTest(); +// 设置成员变量name的值为"张三" +Invoke(obj, "name", 1, "张三"); +// 设置成员变量age的值为18 +Invoke(obj, "age", 1, 18); +// 设置成员变量sid的值为"ts001" +Invoke(obj, "sid", 1, "ts001"); +// 执行单参数重载成员方法fun +a := Invoke(obj, "fun", 0, "name"); +// 执行双参数重载成员方法fun +b := Invoke(obj, "fun", 0, "name", "age"); +// 执行三参数重载成员方法fun +c := Invoke(obj, "fun", 0, "name", "age", "studentID"); +return array(a, b, c); +type classTest = class +name; +age; +sID; +function fun(a);overload; +begin + s := "\r\n" + a + ":" + name; + echo s; + return s; +end; +function fun(a, b);overload; +begin + s := "\r\n" + a + ":" + name + " " + b + ":" + floattostr(age); + echo s; + return s; +end; +function fun(a, b, c);overload; +begin + s := "\r\n" + a + ":" + name + " " + b + ":" + floattostr(age) + " " + c + ":" + sID; + echo s; + return s; +end; +end; +``` + +打印: + +返回:参考Invokeinarray + +###### Invokeinarray + +用途:以参数数组调用对象成员方法或设置成员属性。 +参数: + +- obj:目标对象 +- name:成员名 +- mode:0 调用方法;1 设置成员 +- args:参数数组 + +返回:调用结果或设置结果。 + +范例 + +范例01:设置成员变量后调用成员方法并返回结果 + +```tsl +obj := new classTest(); +// 设置成员变量name的值为"张三" +Invokeinarray(obj, "name", 1, array("张三")); +// 设置成员变量age的值为18 +Invokeinarray(obj, "age", 1, array(18)); +// 设置成员变量sid的值为"ts001" +Invokeinarray(obj, "sid", 1, array("ts001")); +// 执行单参数重载成员方法fun +a := Invokeinarray(obj, "fun", 0, array("name")); +// 执行双参数重载成员方法fun +b := Invokeinarray(obj, "fun", 0, array("name", "age")); +// 执行三参数重载成员方法fun +c := Invokeinarray(obj, "fun", 0, array("name", "age", "studentID")); +return array(a, b, c); +type classTest = class +name; +age; +sID; +function fun(a);overload; +begin + s := "\r\n" + a + ":" + name; + echo s; + return s; +end; +function fun(a, b);overload; +begin + s := "\r\n" + a + ":" + name + " " + b + ":" + floattostr(age); + echo s; + return s; +end; +function fun(a, b, c);overload; +begin + s := "\r\n" + a + ":" + name + " " + b + ":" + floattostr(age) + " " + c + ":" + sID; + echo s; + return s; +end; +end; +``` + +打印: + +name:张三 + +name:张三 age:18 + +name:张三 age:18 studentID:ts001返回: + +范例02:命名参数调用的方式 + +```tsl +// 调用 +obj := new classTestB(); +return Invokeinarray(obj, "fun", 0, array("c":3, "b":2, "a":1)); // 命名参数的调用 +// 类实现 +type classTestB = class +function fun(a, b, c);overload; +begin + return array(a, b, c); +end; +end; +``` + +返回:array(1,2,3)参考Invoke + +###### SafeEval + +用途:安全执行表达式或表达式字符串,执行失败返回 nil。 +参数: + +- expr:表达式(@)或表达式字符串(&) + 返回:表达式结果或 nil。 + +###### DoubleVariableExecute + +用途:设置两个系统参数数组并计算表达式。 +参数: + +- arr1:第一个参数值数组 +- param1:系统参数函数(如 pn_Stock()) +- arr2:第二个参数值数组 +- expr:表达式 + +返回:结果数组。 + +算法 + +根据参数Arr和TimeArr的长度设置不同的系统参数,求表达式的值范例 + +```tsl +stocks := array(getbk('上证50')); +time_arr := MarketTradeDayQk(20220101T, 20221211T); +return DoubleVariableExecute(stocks, pn_Stock(), time_arr, @close()); +``` + +返回:(部分结果截图) + +###### MultipleExecute + +用途:基于系统参数 STOCKS/BKS/TIMES 批量计算表达式。 +参数: + +- expr:表达式 + 返回:结果数组。 + +算法 + +(1)获得'STOCKS','BKS','TIMES'对应的系统参数; + +(2)根据以上系统参数是否是数组型,设置不同的系统参数,求表达式的值 + +###### SingleVariableExecute + +用途:设置一个系统参数数组并计算表达式。 +参数: + +- arr:参数值数组 +- param:系统参数函数(如 pn_Stock()) +- expr:表达式 + +返回:结果数组。 + +范例 + +```tsl +// Arr中存储的是代码,获取2019年3月1日,Arr中所有代码的收盘价 +arr := array('SZ000001', 'SZ000002'); +return SingleVariableExecute(arr, pn_stock(), @close()); +``` + +###### SafeSetSysParam + +用途:安全设置系统参数(与 SetSysParam 类似,失败不抛异常)。 +参数: + +- param_name:参数名或系统参数函数 +- value:参数值 + 返回:设置结果(成功为 1,失败为 0)。 + +##### 性能优化相关函数 + +###### 内容 + +- SetProfiler +- GetProfilerInfo + +###### SetProfiler + +用途:设置性能分析开关与统计范围。 +参数: + +- flags:统计选项位掩码 + +返回:无。 + +范例 + +范例01:1+2+4的优化信息返回 + +```tsl +SetProfiler(7); +a := array(); +SetSysParam(PN_Stock(), 'SH000001'); +for i := 20000101t to 20200721T do +begin + if not spec(istradeday(i), 'SH000001') then continue; + echo specdate(close(), i); +end; +return 1; +``` + +结果:times为函数运行的次数,seconds为运行时间,op为指令的优化信息,type为函数类型。 + +范例02:内置对象的优化信息返回 + +```tsl +SetProfiler(8); +o := new TStringList(); +o.text := "Tinysoft"; // 给对象的属性赋值 +o.DelimitedText := 'A=abc,B=123,C=abc,F=996,E=abd'; +o.Add("G=666"); +return 1; +``` + +优化信息如: + +###### GetProfilerInfo + +用途:获取性能分析信息。 +参数: + +- mode:可选;传 1 仅返回信息不弹窗 + +返回:性能分析信息。 + +范例 + +范例01:不弹出profiler窗口 + +```tsl +setprofiler(7); // 记录TSL源代码函数调用+二进制函数的调用+指令调用的优化信息 +a := 99; +b := inttostr(a); // inttostr是函数 +a := rand(1000, 1); // rand是指令 +a := select * from a where [0] > 0.5 end; // select是指令 +setsysparam(pn_stock(), "SZ000002"); +b := nday3(100, close()); // nday3也算是指令,不是函数 ,close是函数 +return GetProfilerInfo(1); +``` + +范例02:弹出profiler窗口 + +```tsl +setprofiler(7); // 记录TSL源代码函数调用+二进制函数的调用+指令调用的优化信息 +a := 99; +b := inttostr(a); // inttostr是函数 +a := rand(1000, 1); // rand是指令 +a := select * from a where [0] > 0.5 end; // select是指令 +setsysparam(pn_stock(), "SZ000002"); +b := nday3(100, close()); // nday3也算是指令,不是函数 ,close是函数 +t := GetProfilerInfo(); +return b; +``` + +返回结果:返回程序结果的同时,另外弹出profiler窗口 + +##### 函数库路径 + +###### 内容 + +- sysgettsllibpath +- syssettsllibpath + +###### sysgettsllibpath + +用途:获取当前函数库查找路径。 +参数:无。 +返回:当前查找路径字符串。 + +范例 + +```tsl +echo "当前查找路径:", sysgettsllibpath(), '\r\n'; +``` + +###### syssettsllibpath + +用途:设置函数库查找路径(支持分号分隔的多个目录)。 +参数: + +- path_list:路径列表字符串(分号分隔) + +返回:设置前的查找路径字符串。 + +范例 + +```tsl +a := 198.86; +b := -22.34; +echo "当前查找路径:", sysgettsllibpath(), '\r\n'; +syssettsllibpath("C:\\DoTSL\\otherTest\\;"); +echo "当前查找路径:", sysgettsllibpath(), '\r\n'; +try + v := TestTsfsum(a, b); + echo "TestTsfsum执行成功:", v, '\r\n'; +except + echo ExceptObject.ErrInfo, '\r\n'; +end; +return "执行完毕"; +``` + +##### 调用堆栈 diff --git a/data/tsl_reference_catalog_source/third_party.md b/data/tsl_reference_catalog_source/third_party.md new file mode 100644 index 00000000..a160532e --- /dev/null +++ b/data/tsl_reference_catalog_source/third_party.md @@ -0,0 +1,569 @@ +#### 第三方交互函数 + +##### 内容 + +- Python支持函数 +- R支持函数 +- MatLab支持函数 +- 彭博终端支撑函数 +- Html +- do方式对外部语言的调用 +- COM接口 +- JAVA方法的调用 + +##### Python支持函数 + +###### 内容 + +- Python支持函数简介 +- PyPutVar +- PyGetVar +- PyRun +- PyCall +- PyRelease +- PyEnsure +- 调用Python范例 +- PyError + +###### Python支持函数简介 + +要使用Python的引擎,首先需要将对应于客户端(如在脚本调用则为TSL.EXE)的相应位数的版本(32位对应32位,64位对应于64位)的python相应支持DLL所在位置加入系统或者PATH中,并在天软存贮目录的plugin\FileMgr.ini中加入 + +[Python Config] + +Enabled=1 + +version=3 + +如果是版本2.7的就用version=2 + +###### PyPutVar + +###### PyGetVar + +###### PyRun + +用途:Python支持函数相关函数。 +参数:arg1(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +s := "a=1 +b := 1 +if a == 1: +b := 2 +"; +PyRun(s); +return array("a":pygetvar("a"), "b":pygetvar("b")); +``` + +本地执行返回结果: + +###### PyCall + +用途:Python支持函数相关函数。 +参数:arg1,arg2,arg3,arg4(按示例顺序传入)。 +返回:处理后的结果值。 + +范例 + +```tsl +rdo2 PyRun("import numpy"); +// 不给状态值,默认方式下调用python的randint函数 +return rdo2 PyCall('numpy.random', 'randint', 6, 9); +// 参数通过数组方式传入 +return PyCall(2, 'numpy.random', 'randint', array('high':9, 'low':6)); +// 一个个指定参数方式传入 +return PyCall('numpy.random', 'randint', high:9, low:6); +``` + +###### PyRelease + +###### PyEnsure + +###### 调用Python范例 + +例1: + +```tsl +a := 2; +pyputvar("a", a); // 送入变量 +pyrun("a = a+1"); // 计算 +b := pygetvar("a"); // 获取变量返回结果为 3 +// 例2: +PyRun("import math"); // 执行python语句 :导入python的math模块 +a := PyCall("math", "sqrt", 2); // a = 1.4142135623731 +// 调用math模块下的sqrt(开方)函数,参数为2; +b := PyCall("math", "pow", 2, 3); // b = 8; +// 调用math模块下的pow函数,参数为2,3; +return C := a * b; +``` + +###### PyError + +用途:获取最近一次 Python 调用错误信息。 +参数:无。 +返回:错误信息字符串。 + +范例 + +本地执行以下脚本 + +```tsl +pyrun("a=math.pi"); // 此处会报错因为没有 import math +return PyError(); +``` + +返回: name 'math' is not defined + +##### R支持函数 + +###### 内容 + +- R支持函数简介 +- REVal +- RGetVar +- RPutVar +- REnsure +- RRelease +- R支持函数范例 + +###### R支持函数简介 + +要使用R的引擎,首先需要将对应于客户端(如在脚本调用则为TSL.EXE)的相应位数的版本(32位对应32位,64位对应于64位)的R.DLL所在位置加入系统或者PATH中,并在天软存贮目录的plugin\FileMgr.ini中加入 + +[R Config] + +Enabled=1 + +天软平台尝试对R进行了多线程支持,但由于R语言本身的缺陷,多线程调用R会存在内存泄露等问题。因此,尽管TSL语言支持R语言的多线程调用并经过了测试,天软依旧不建议多线程下调用R语言。 + +###### REVal + +###### RGetVar + +###### RPutVar + +###### REnsure + +###### RRelease + +- R支持函数简介 +- REVal +- RGetVar +- RPutVar +- REnsure +- RRelease +- R支持函数范例 + +###### R支持函数范例 + +Rdo2 RPutVar("a",array(1,2,3,4)); + +Ret:=Rdo2 REval("b=mean(laply(a,unlist))",Code); //Code=0则正确 + +VarValue:=Rdo2 RGetVar("b"); + +return varvalue; + +说明: + +RputVar传递给R一个array(1,2,3,4),,并且命名为a,R那边接受的是一个list,通过laply(a,unlist)转化成R里面的数组类型,进而求均值。最后通过RgetVar得到计算的值。通过这种形式,可以很容易的实现在在天软平台调用R的函数。注意这里由于安全原因R的支持服务器不授权不能被调用,因此需要使用RDO2来测试。 + +##### MatLab支持函数 + +###### 内容 + +- MatLab支持函数简介 +- MATLAB编译的DLL支持函数 + +###### MatLab支持函数简介 + +TSL有两种模式调用MATLAB,一种是调用编译后的MATLAB函数,另外一种是调用MATLAB引擎的函数。 + +无论哪种调用,均依赖系统提供的matlab.dll动态库来支持,该动态库和安装到的MATLAB的版本有关系,每一个安装的版本的MATLAB,我们均提供一个对应的DLL来进行支持,一般的,系统提供了多个版本的支持库,例如matlab.dll.2008a,matlab.2009a等,用户把自己相应安装的版本的该文件复制成为matlab.dll即可。如果找不到匹配版本的动态库,可能是您的版本过老或者太新,请联系客户服务人员进行该支持库的定制。 + +###### MATLAB编译的DLL支持函数 + +TSL语言支持通过配置的方法来支持MATLAB编译出来的函数提供调用。 + +TSL提供支持编译MATLAB的函数的方法: + +无论是用户自己编写的,函数现有的TOOLBOX函数,在MATLAB中都是以.m文件存在的,这些m文件matlab提供了编译成DLL的方法: + +假定当前目录为toolbox\garch\garch下: + +用C:\Program Files\MATLAB\R2008a\toolbox\garch\garch>mcc -W lib:garch -T +link:lib + +garchset garchfit garchpred ..\..\stats\norminv + +可以将garchset garchfit garchpred +norminv等函数编译成DLL,假如要编译更多的TOOLBOX函数或者自己编写的M函数,只要在命令行内添加就可以了。 + +编译完成后会得到garch.dll(由lib:garch指定的),在TSL的相关配置文件里进行配置就可以使得mdo和mdo2函数可以对其中编译的函数进行调用。 + +####### 内容 + +- Mdo +- Mdo2 +- 天软金融平台调用MATLAB的M方法的图解步骤 +- MATLAB引擎支持函数 + +####### Mdo + +####### Mdo2 + +####### 天软金融平台调用MATLAB的M方法的图解步骤 + +######## 内容 + +- 第一步,在MATLAB中建立C Shared Library工程 +- 第二步,在工程中加入需要的M文件 +- 第三步,设置好工程的相关的属性 +- 第四步,编译,生成动态库 +- 第五步,在金融工程平台中配置。 +- 第六步,可以在金融工程平台中建模使用 +- 第七步,运行的结果窗口 + +######## 第一步,在MATLAB中建立C Shared Library工程 + +######## 第二步,在工程中加入需要的M文件 + +以下范例为加入garchfit,garchpred,garchset,norminv等MATLAB方法 + +######## 第三步,设置好工程的相关的属性 + +######## 第四步,编译,生成动态库 + +######## 第五步,在金融工程平台中配置。 + +######## 第六步,可以在金融工程平台中建模使用 + +######## 第七步,运行的结果窗口 + +####### MATLAB引擎支持函数 + +要使用MATLAB的引擎,首先需要在天软的平台或者解释器以及客户端所在的目录找到当前使用的MATLAB版本难得相关支撑文件,一般来说其支撑文件的命名是matlab.dll.版本,例如matlab.dll.2013b就代表了R2013B的版本支持文件。 + +用户把相应的支撑文件的名字更名为matlab.dll。 + +对于绝大多数的MATLAB版本而言,这样就已经完成了配置,接下来的事情就是重新启动服务或者客户端,但是对于某些版本的MATLAB而言,这还不够,因为某些版本的MATLAB的路径设置有问题,用户需要手动将包含MATLAB引擎支撑库的路径加入到系统或者用户的PATH。一般来说该添加到PATH中的路径应包括安装到的目录的bin以及bin\win32或者bin\win64以及runtime\win32,runtime\win64。 + +######## 内容 + +- MEVal +- MPutVar +- MGetVar +- MGetBuf +- MClose +- MSetVisible +- MGetVisible +- MATLAB引擎调用范例 +- Menablefmarray + +######## MEVal + +######## MPutVar + +######## MGetVar + +######## MGetBuf + +######## MClose + +######## MSetVisible + +######## MGetVisible + +######## MATLAB引擎调用范例 + +例如,用matlab做矩阵求逆的例子: + +a:=rand(10,10); + +MPutVar("MatlabA",a); + +MEval("MatlabB=inv(a)"); + +b:=MGetVar("MatlabB"); + +由于大多数情况下MATLAB安装在客户机器上,因此,需要利用天软平台的RDO2来调用: + +于是代码就变成了: + +a:=rand(10,10); + +RDO2 MPutVar("MatlabA",a); + +RDO2 MEval(“MatlabB=inv(a)”); + +b:=RDO2 MGetVar("MatlabB"); + +######## Menablefmarray + +范例 + +范例代码: + +```tsl +t := CreateMatrix(3, 4, array('s', 'd', 'f'), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); +rdo2 mPutVar("A", t); +rdo2 mPutVar("B", 2); +rdo2 mEval("C=A+B"); +return rdo2 mGetVar("C"); +``` + +场景一:不设置Menablefmarray + +不修改上述范例代码,结果如下: + +场景二:设置Menablefmarray值为0 + +上述范例代码前加上"rdo2 Menablefmarray(0);",结果如下: + +场景三:设置Menablefmarray值为1 + +上述范例代码前加上"rdo2 Menablefmarray(1);",结果如下: + +##### 彭博终端支撑函数 + +###### 内容 + +- 彭博终端支撑函数简介 +- blpcall +- BLP测试范例 + +###### 彭博终端支撑函数简介 + +为了更好地和其他信息源进行交互,根据BLP的API,TSL封装了一个函数,用来从彭博的终端或者SERVER获得数据。 + +###### blpcall + +###### BLP测试范例 + +下属例子为订阅两支指数的最新价格,价格到达则回调hello函数。 + +```tsl +a := array(); +a[0] := array("FSSTI Index", "LAST_PRICE"); +a[1] := array("DAX Index", "LAST_PRICE"); +blpcall(array("maxEvent":300), "//blp/mktdata", "subscription", a, "hello"); +function hello(b); +begin + echo "-----------------------------------\r\n"; + if b["type"] = 8 and b["msgs"][0, "id"] = "FSSTI Index"then c[0, 1] := b["msgs"][0, "value"]["LAST_PRICE"]; + else if b["type"] = 8 and b["msgs"][0, "id"] = "DAX Index"then c[1, 1] := b["msgs"][0, "value"]["LAST_PRICE"]; + echo tostn(c), "\r\n"; + return 1; // return + false退出, 如果一直返回真,就等到接收到系统结束的事件或者事件数达到maxEvent的规定。 +end; +``` + +##### Html + +###### 内容 + +- TextToHtml +- TextToURL +- HtmlToText +- URLToText + +###### TextToHtml + +用途:Html相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Src := "The First LETTER won\'t be replaced by \'one\', but the Second letter will."; +return TextToHtml(Src); +// 结果: +The First LETTER won't be replaced by 'one', but the Second letter will. +``` + +###### TextToURL + +用途:Html相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +ASrc := "#abcd 10"; +return TextToURL(ASrc); +// 结果:%23abcd%20%2010 +``` + +###### HtmlToText + +用途:Html相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +Src := "The First LETTER won't be replaced by 'one', but the Second letter will."; +return HtmlToText(Src); +// 结果:The First LETTER won't be replaced by 'one', but the Second letter will. +``` + +###### URLToText + +用途:Html相关函数。 +参数: + +返回:处理后的结果值。 + +范例 + +```tsl +aSrc := "%23abcd%20%2010"; +return URLToText(aSrc); +// 结果:#abcd 10 +``` + +##### do方式对外部语言的调用 + +语法:do extlanguage [paramlist] [by config] + +说明: + +1、对外部语言的调用,in表示只送入,out表示只送出,var表示送入送出。 + +2、如果使用变量名,天软会默认将同名变量名送入到外部语言中。假如目标语言大小写相关,则必须用name关键字明确指定变量名。 + +3、对于不同的语言而言,可能有的语言存在返回值,有的语言是无返回值的。例如PYTHON没有返回值,而r有返回值。 + +4、如果只执行代码,参数等都可以省略。 + +5、对于某些语言,可能会存在其他配置的,可以通过by语法来送入。 + +6、目前extlanguage已经支持python,r,matlab,今后可能更多的语言会被扩展支持,底层用户也可以通过接口规范来扩展支持其他语言。 + +7、配合新的%%非转义字符串语法,对于调用其他语言会更方便。 + +下面是一个调python语言的示例: + +```tsl +a := 3; +c := 2; +do python in a name"A", out b, var c +%% +c := A * c +b := c * c +%%; +``` + +结果c为6,b为36 + +##### COM接口 + +TSL内置了COM对象支持,支持通过创建外部com对象来调用外部组件的功能。 + +天软客户端也提供了COM服务,服务名为TSExpert.CoExec。利用COM访问天软平台,可以支撑包括MATLAB,SAS,EXCEL +VBA,SPLUS,R等软件。 + +###### 内容 + +- 外部COM对象的创建 +- 天软客户端COM接口 + +###### 外部COM对象的创建 + +TSL内置了COM对象支持,支持通过创建外部com对象来调用外部组件的功能。 + +TSL中提供一个简单的方法GetOleObject来创建COM对象。 + +COM的调用和TSL的对象的调用是没有差异的,也非常类似于PASCAL以及VB等对COM对象的调用。每个COM对象方法或者属性的调用要么返回一个TSL基本类型,如数组,数字,字符串,NIL等,要么返回一个COM对象。 + +例如: + +```tsl +GetOleObject(“Excel.Application”, 0, Obj); +Obj.WorkBooks.Open(“C:\\1.xls”); +``` + +上边的代码Obj.WorkBooks隐含着返回了一个WorkBooks对象 + +###### 天软客户端COM接口 + +##### JAVA方法的调用 + +JAVA类型在TSL语言中是一个内置的对象。 + +利用TJObject可以创建Java的对象,利用TJClass可以获得Java的类。 + +使用Java对象或者Java的类和Java并无大的差异 + +==========tjclass的使用范例============= + +```tsl +systemClass := new TJClass("java/lang/System"); +properties := systemClass.getProperties(); +systemClass.out.println(properties.getProperty("java.class.path")); +``` + +==========tjobject使用范例============== + +```tsl +// 构造StringBuffer对象 +sbObj := new TJObject("java/lang/StringBuffer", "hello world"); +// 调用对象的insert方法 +ret := sbObj.insert(6, "天软"); +// 调用toString方法 +str := sbObj.toString(); +// 显示: hello 天软 world +echo str, "\r\n"; +``` + +###### 内容 + +- Java参数类型的转换 + +###### Java参数类型的转换 + +绝大多数的数据类型, TSL与Java之间会做隐式类型转换, TSL支持显式的数据类型转换这是由JavaEncode以及 + +JavaDecode来实现的 + +==============JavaEncode JavaDecode范例================== + +```tsl +// char[]构造, Unicode字符集, JavaEncode负责生成Unicode编码的char数组 +charArr := JavaEncode("chararray", "Tinysoft天软"); +strObj := new TJObject("java/lang/String", charArr); +SystemClass.out.println(strObj.toString()); +// 构造字符串 +strObj := new TJObject("java/lang/String", "天软科技"); +// 得到byte数组,系统默认字符集 +byteArray := strObj.getBytes(); +// byte数组转换为字符串 +str := JavaDecode("String", byteArray); +echo str, "\r\n"; +``` + +======================================================== + +JavaEncode支持的显式转换的类型有: + +"CharArray", "ByteArray", "CurrentClass" + +JavaDecode支持的显式类型有 + +"String","WString" + +由于绝大多数数据类型已经在隐式转换里自动支持,例如array(1.0,2.0)会映射到float[] + +如存在有需要显式转换的其他类型今后将会根据具体需求进行升级 + +========================================================= diff --git a/docs/tsl/code_style.md b/docs/tsl/code_style.md index 10b416f4..a0cc9d9e 100644 --- a/docs/tsl/code_style.md +++ b/docs/tsl/code_style.md @@ -1,7 +1,17 @@ # TSL 代码风格(Code Style) +文档类型:规范页 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[naming.md](naming.md)、[syntax/index.md](syntax/index.md)、[toolchain.md](toolchain.md) + 本章节规定 TSL 代码的结构与格式约定。 +以下出现的 ``、`<...>`、模板占位和单独标成 `反例 / 不可照写` 的块,只用于说明风格或反例,不等于可直接复制的源码字面量。 + +本页里的 `反例 / 不可照写` 仅表示风格上的不推荐写法,不等于语法主线里“已验证会编译失败/运行失败”的反向边界;因此页头里的 `是否含已验证反例` 仍保持为 `否`。 + 相关文档: - 命名规范:`docs/tsl/naming.md` @@ -65,6 +75,8 @@ - 代码块使用统一的块结构(示例按常见 TSL 写法;若项目语法/约定有差异,以项目现有代码为准): +代码块身份:配置片段 / 概念骨架 + ```tsl if cond then begin @@ -81,6 +93,8 @@ end - `else/elseif` 等分支关键字另起一行,与上一块的 `end` 对齐。 - 单语句分支可省略 `begin/end`(保持清晰优先;一旦分支变复杂就回退到块结构): +代码块身份:配置片段 / 概念骨架 + ```tsl if cond then DoSomething() else DoOther() @@ -100,8 +114,10 @@ else DoOther() - 复杂条件拆分为具名布尔变量或小函数。 - 早返回优于深层嵌套: +代码块身份:配置片段 / 概念骨架 + ```tsl -if !ok then return err +if !ok then return err; // main path ``` @@ -136,6 +152,8 @@ if !ok then return err - 注释使用完整句子,末尾带标点。 - 推荐模板(按需裁剪;语言可中英混写): +代码块身份:配置片段 / 概念骨架 + ```tsl // Summary: 一句话说明做什么(以及关键约束/边界)。 // Args: @@ -151,8 +169,21 @@ if !ok then return err - 避免“显而易见注释”: - 尾随注释(写在代码行末)只用于非常短的补充;超过一行时改为写在语句上方,或重构代码提醒意图。 +不推荐这样写: + +代码块身份:反例 / 不可照写 +代码块说明:风格反例,不是已验证语法反例。 + ```tsl -count = count + 1 // bad: obvious +count := count + 1; // obvious +``` + +推荐直接删掉这类显而易见注释: + +代码块身份:配置片段 / 概念骨架 + +```tsl +count := count + 1; ``` ### 3.4 TODO/FIXME @@ -164,8 +195,7 @@ count = count + 1 // bad: obvious ## 4. 代码实践(Best Practices) > 本节偏“实践建议”(should),用于提升可读性/可测试性;若目标项目有更严格的约束与检查命令,以项目落地的工具链为准(参考 -> `docs/tsl/toolchain.md`)。如需给自动化/AI 代理配置强约束,可参考 -> `.agents/tsl/code_quality.md` 与 `.agents/tsl/testing.md`。 +> `docs/tsl/toolchain.md`)。如果项目对自动化或 AI 代理有额外要求,应把约束直接写进仓库内可见的检查脚本、CI 配置或项目文档,而不是依赖隐藏规范。 ### 4.1 变量与常量 @@ -174,6 +204,8 @@ count = count + 1 // bad: obvious - 对外 API 优先只读:对外暴露用只读 property(只有 `read`,不写 `write`),内部用私有成员保存。 +代码块身份:配置片段 / 概念骨架 + ```tsl type User = class public @@ -196,6 +228,8 @@ end; `Style`(建议紧贴类型名书写)。 - 示例(`{Unit.}` 前缀仅用于阅读,不改变类型名): +代码块身份:配置片段 / 概念骨架 + ```tsl type DocxContext = class public @@ -210,6 +244,8 @@ function RenderParagraph(para_: {DocxML.}Paragraph): void; - 无返回值函数显式标注返回类型为 `void`;`create`/`destroy` 作为构造/析构函数不写返回类型。 +代码块身份:配置片段 / 概念骨架 + ```tsl function Func(a: string; b: ClassName): void; ``` @@ -222,21 +258,29 @@ function Func(a: string; b: ClassName): void; - 输入参数在前;可选配置/选项(如 `*Options`/`*Config`)居中;输出/回调在后。 - 避免堆叠多个布尔开关参数;优先收敛到 `*Options`/`*Config`(按需在 `class` 或 `unit` 中定义)。 -- 示例:避免多个布尔开关参数(调用点难以理解 `true/false` 的含义),改为 +- 示例:避免多个开关参数直接堆在签名里(调用点难以理解各参数含义),改为 `*Options`/`*Config`: +不推荐这样写: + +代码块身份:反例 / 不可照写 +代码块说明:风格反例,不是已验证语法反例。 + ```tsl -// 注:参数类型名按项目实际替换(此处 bool/Any 仅为示例占位)。 -// bad: 多个 bool 参数在调用点难读、易传错 function ExportReport( path: string; - data: Any; - include_header: bool; - compress: bool; - dry_run: bool + rows: array; + include_header; + compress; + dry_run ): void; +``` -// good: 将可选开关收敛到 Options(调用点更自解释、后续扩展更稳定) +推荐把可选开关收敛到 `Options` / `Config`: + +代码块身份:配置片段 / 概念骨架 + +```tsl type ExportOptions = class public property IncludeHeader read include_header_ write include_header_; @@ -248,7 +292,7 @@ private dry_run_; end; -function ExportReport(path: string; data: Any; options: ExportOptions): void; +function ExportReport(path: string; rows: array; options: ExportOptions): void; ``` - 尽量避免超过 5 个参数;必要时封装为对象(`class`/`unit`)。 @@ -267,22 +311,22 @@ function ExportReport(path: string; data: Any; options: ExportOptions): void; - 错误信息与日志(允许在库里打日志,但要克制): - 错误/日志至少包含:**做什么失败** + **关键上下文(脱敏)**,便于定位;避免只有“failed”。 - - 禁止把 Token/密码/个人数据等敏感信息写入日志、注释或错误信息(参考 - `.agents/tsl/auth.md`)。 + - 禁止把 Token、密码、个人数据等敏感信息写入日志、注释或错误信息;如需记录标识,优先记录脱敏后的业务 ID 或可复现的上下文键。 - 避免重复记录:同一个错误链路尽量只在**边界层**记录一次(库里记录后,上层通常不再重复打一遍同等级日志)。 - 示例:`try/except/end` + 降级(best-effort): - - 注:示例中的 `Any`/`nil`/`LogWarn`/`ReadCacheFromFile` - 为占位,按项目实际类型与函数替换。 + - `LoadCacheValue` / `RecordCacheWarning` 代表项目自有函数,重点在结构而不是函数名本身。 + +代码块身份:配置片段 / 概念骨架 ```tsl // 读取可选缓存:失败允许降级为 cache miss(必须可观测,并说明原因)。 -function ReadOptionalCache(path: string): Any; +function ReadOptionalCache(path: string); begin try - return ReadCacheFromFile(path) + return LoadCacheValue(path) except // best-effort: cache 仅用于提速,失败不应影响主流程 - LogWarn("ReadOptionalCache failed; fallback to miss. path=" + path) + RecordCacheWarning(path) return nil end end; @@ -290,22 +334,22 @@ end; ### 4.4 性能与可测试性 -- 避免过早优化:先写清晰正确的代码,再用数据(profile/trace/log/基准)定位瓶颈并做最小化改动(参考 - `.agents/tsl/performance.md`)。 -- 复杂逻辑要可测试:把“纯计算/解析/规则”与“I/O/环境依赖(文件/网络/DB/全局状态)”分离;I/O 层做薄封装,核心逻辑保持可单测(参考 - `.agents/tsl/testing.md`)。 +- 避免过早优化:先写清晰正确的代码,再用项目实际可用的 profile、trace、日志或基准数据定位瓶颈,并做最小化改动。 +- 复杂逻辑要可测试:把“纯计算/解析/规则”与“I/O/环境依赖(文件/网络/DB/全局状态)”分离;I/O 层做薄封装,核心逻辑保持可单测。 - 避免在热路径里做隐式昂贵操作:循环内重复 I/O、重复解析/格式化、无界缓存、隐式复制等;缓存如必须引入,明确生命周期与上限(大小/TTL/清理点)。 - 示例:薄 I/O + 厚纯逻辑(便于测试与复用): - - 注:示例中的 `Any`/`ReadAllText` 为占位,按项目实际类型与函数替换。 + - `LoadConfigText` 代表项目自己的 I/O 边界函数;`ParseConfig` 只负责解析与校验。 + +代码块身份:配置片段 / 概念骨架 ```tsl // pure: 只做解析/校验,不做 I/O,便于单元测试 -function ParseConfig(text: string): Any; +function ParseConfig(text: string): array; // I/O: 只负责读文件与兜底处理,把逻辑交给 ParseConfig -function LoadConfig(path: string): Any; +function LoadConfig(path: string): array; begin - text = ReadAllText(path) + text := LoadConfigText(path); return ParseConfig(text) end; ``` diff --git a/docs/tsl/finance/backtest_and_trade_flow.md b/docs/tsl/finance/backtest_and_trade_flow.md new file mode 100644 index 00000000..b7cc0bae --- /dev/null +++ b/docs/tsl/finance/backtest_and_trade_flow.md @@ -0,0 +1,59 @@ +# Backtest And Trade Flow + +文档类型:业务骨架 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:项目实际接口定义、[../modules/tsbacktesting.md](../modules/tsbacktesting.md)、[selection_and_signal_patterns.md](selection_and_signal_patterns.md)、[../syntax/index.md](../syntax/index.md) + +这一篇收拢回测、组合、交易与结果读取流程。 + +## 这一篇解决什么问题 + +回答“回测对象如何组织、交易流程如何设置、结果怎样取出和解释”。 + +## 必须记住的规则 + +- 回测流程属于业务框架使用,不属于语言层语法。 +- 在回测场景里,先分清“框架对象怎么配置”和“语法怎么写”是两件不同的事。 +- 本层只给业务流程骨架,不给回测对象 API 真值。 +- 本层优先解释流程、对象职责和结果读取入口。 +- 如果问题已经落到回测对象创建方式、交易数据入口名、结果接口真值或项目封装差异,停止在 finance / modules 层继续推断,直接回项目实际接口定义。 + +## 最小任务骨架 + +1. 先确认回测对象类型、周期、资金和组合类型。 +2. 再确认项目侧是否已经封装好最小可用对象模型、交易输入入口和结果读取链路。 +3. 然后配置交易约束、价格口径、费用和基准。 +4. 再准备交易输入:目标权重、成交明细或其他框架要求的输入数据。 +5. 再执行回测。 +6. 最后按任务读取净值、成交、持仓和绩效结果。 + +## 进入前先回答的问题 + +- 你做的是比例类组合,还是数量类组合。 +- 你需要哪些交易约束、费用模型和基准口径。 +- 结果要给人看,还是要交给后续分析 / 执行链路。 + +## 结果读取骨架 + +- 这里说的是结果类型,不是保证存在的接口名;任何读取方法都先以项目实际接口定义为准。 +- 读净值 / 收益率时间序列。 +- 读成交 / 调仓结果。 +- 读持仓、资产和绩效指标。 +- 读基准或扩展结果时,先确认对应接口是否已经在项目里封装好。 + +## 常见误判 + +- 把回测框架的字段和方法误当成 TSL 语言内建语法。 +- 在没确认组合类型、资金约束和结果接口前,就直接复制零散片段。 +- 只看到 `BackTest()`,就跳过交易输入准备和结果读取设计。 +- 把“概念流程”误写成“独立可编译模板”。 + +## 跳转指引 + +- finance 总入口:见 [entry_decision.md](entry_decision.md) +- 参考现有回测资料:见 [../modules/tsbacktesting.md](../modules/tsbacktesting.md) +- 具体字段、交易数据入口、结果接口真值或项目封装差异:回项目实际接口定义 +- 选股与信号:见 [selection_and_signal_patterns.md](selection_and_signal_patterns.md) +- 回到语言层:见 [../syntax/index.md](../syntax/index.md) diff --git a/docs/tsl/finance/entry_decision.md b/docs/tsl/finance/entry_decision.md new file mode 100644 index 00000000..3e8e43a1 --- /dev/null +++ b/docs/tsl/finance/entry_decision.md @@ -0,0 +1,58 @@ +# Finance Entry Decision + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[market_data_context.md](market_data_context.md)、[../syntax/index.md](../syntax/index.md)、[../reference/index.md](../reference/index.md) + +这里是金融层的入口决策页,不是代码页。它只解决“业务任务该往哪一层跳”,不重新定义语言基础语法。 + +## 这一篇解决什么问题 + +回答“什么时候应该进入 finance 层、进入后先去哪个业务主题页,以及什么时候该回到 syntax / reference 层”。 + +## 必须记住的规则 + +- finance 只解释业务任务怎样组织,不解释语言规则本身。 +- finance 可以给出“语法 + 金融函数结合示例”,但不拥有语言规则的解释权。 +- 不需要先通读完整 syntax;先进入最相关的业务主题页,需要时再回补语法或函数查阅。 + +## 适用场景 + +- 你在问市场数据语境、序列/指标组织、选股/信号任务、回测/交易流程。 +- 你已经知道自己在做金融任务,但还没决定应该先读哪一篇业务页。 +- 你需要业务层的“任务骨架”,而不是单条语法结论。 + +## 进入 finance 前至少要掌握什么 + +- 知道 TSL 的最短骨架怎么写:见 [../syntax/02_quickstart.md](../syntax/02_quickstart.md) +- 知道当前文件属于哪种顶层模型:见 [../syntax/03_core_model.md](../syntax/03_core_model.md) +- 知道高频误写不要怎么踩:见 [../syntax/12_pitfalls.md](../syntax/12_pitfalls.md) + +## 进入后先去哪里 + +- 如果你要先理解市场数据从哪里来、脚本运行在什么语境里:去 [market_data_context.md](market_data_context.md) +- 如果你要先理清序列、指标、逐 bar 计算和窗口依赖:去 [series_and_indicator_model.md](series_and_indicator_model.md) +- 如果你要组织选股条件、筛选条件、信号输出:去 [selection_and_signal_patterns.md](selection_and_signal_patterns.md) +- 如果你要配置回测对象、交易流程和结果读取:去 [backtest_and_trade_flow.md](backtest_and_trade_flow.md) + +## 什么时候回到别的层 + +- 如果问题变成“这句语法怎么写”:回 [../syntax/index.md](../syntax/index.md) +- 如果问题变成“这个函数在哪个目录、怎么查签名”:回 [../reference/index.md](../reference/index.md) +- 如果问题变成“现成模块或互操作能力怎么接”:回 [../modules/index.md](../modules/index.md) + +## 常见误判 + +- 把金融数据上下文误当成语言通用规则。 +- 还没澄清业务任务类型,就先去补读整套 syntax。 +- 把 finance 页里的任务骨架误当成独立可编译模板。 + +## 跳转指引 + +- 市场数据语境:见 [market_data_context.md](market_data_context.md) +- 序列与指标模型:见 [series_and_indicator_model.md](series_and_indicator_model.md) +- 选股与信号:见 [selection_and_signal_patterns.md](selection_and_signal_patterns.md) +- 回测与交易:见 [backtest_and_trade_flow.md](backtest_and_trade_flow.md) +- 回到语法层:见 [../syntax/index.md](../syntax/index.md) diff --git a/docs/tsl/finance/index.md b/docs/tsl/finance/index.md new file mode 100644 index 00000000..e1566a8d --- /dev/null +++ b/docs/tsl/finance/index.md @@ -0,0 +1,32 @@ +# Finance Index + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[../syntax/index.md](../syntax/index.md)(优先)、[market_data_context.md](market_data_context.md)、[../reference/index.md](../reference/index.md) + +这里是业务层入口。只讨论金融任务如何使用 TSL,不重讲基础语法。 + +## 先看这 5 条 + +- 如果你的问题是“语言怎么写”,不要留在 finance,回到 [../syntax/index.md](../syntax/index.md)。 +- 如果你的问题是“某个金融任务怎么组织”,从下面最接近的业务主题开始。 +- [entry_decision.md](entry_decision.md) 是入口决策页,不是代码页。 +- 先进入 finance 的业务主题页;只有业务页需要补语法或函数细节时,再回到语法手册或函数查阅层。 +- 只进入一个最相关的主题文件,需要时再跳到相邻主题。 + +## 按任务跳转 + +| 当前任务 | 先读哪里 | +| --- | --- | +| 先判断是否该进入业务层 | [entry_decision.md](entry_decision.md)(决策页,不是代码页) | +| 理解市场数据上下文与运行场景 | [market_data_context.md](market_data_context.md) | +| 理解序列、指标、时序计算模型 | [series_and_indicator_model.md](series_and_indicator_model.md) | +| 写选股、信号、筛选表达模式 | [selection_and_signal_patterns.md](selection_and_signal_patterns.md) | +| 写回测对象、交易流程、结果读取 | [backtest_and_trade_flow.md](backtest_and_trade_flow.md) | + +## 切换到别的层 + +- 回到语法层:见 [../syntax/index.md](../syntax/index.md) +- 回到函数库查找层:见 [../reference/index.md](../reference/index.md) diff --git a/docs/tsl/finance/market_data_context.md b/docs/tsl/finance/market_data_context.md new file mode 100644 index 00000000..440e348c --- /dev/null +++ b/docs/tsl/finance/market_data_context.md @@ -0,0 +1,40 @@ +# Market Data Context + +文档类型:业务骨架 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[series_and_indicator_model.md](series_and_indicator_model.md)、[../syntax/index.md](../syntax/index.md)、[../modules/tsbacktesting.md](../modules/tsbacktesting.md) + +本页用于判断金融脚本运行时的数据语境,不提供独立语法模板。 + +这一篇整理金融场景中的市场数据语境与执行环境。 + +## 这一篇解决什么问题 + +回答“金融脚本运行时的数据上下文是什么、哪些概念属于业务层而不是语言层”。 + +## 必须记住的规则 + +- 这里讨论的是市场数据语境,不是语言语法。 +- 当问题变成“`if` / `function` / `array` 怎么写”时,应回到 syntax 层。 +- 当问题变成“当前 bar、序列窗口、市场字段从哪里来”时,才留在 finance 层。 + +## 适用边界 + +- 本文不新增语法规则,语法仍以 `docs/tsl/syntax/` 为准。 + +## 为什么这里不放独立示例 + +- 本文不放单独的语法示例,避免把业务上下文误写成语言规则。 + +## 常见误写 + +- 把市场数据上下文误当成所有 TSL 文件默认自带的语言能力。 +- 在还没确认数据语境前,先去排查语法。 + +## 跳转指引 + +- 回到语法层:见 [../syntax/03_core_model.md](../syntax/03_core_model.md) +- 看指标与序列:见 [series_and_indicator_model.md](series_and_indicator_model.md) +- 参考现有业务资料:见 [../modules/tsbacktesting.md](../modules/tsbacktesting.md) diff --git a/docs/tsl/finance/selection_and_signal_patterns.md b/docs/tsl/finance/selection_and_signal_patterns.md new file mode 100644 index 00000000..c509170a --- /dev/null +++ b/docs/tsl/finance/selection_and_signal_patterns.md @@ -0,0 +1,51 @@ +# Selection And Signal Patterns + +文档类型:业务骨架 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[series_and_indicator_model.md](series_and_indicator_model.md)、[backtest_and_trade_flow.md](backtest_and_trade_flow.md)、[../syntax/index.md](../syntax/index.md) + +这一篇收拢选股、筛选和信号生成的业务模式。 + +## 这一篇解决什么问题 + +回答“如何把条件表达和金融筛选任务组织成稳定的选股/信号脚本”。 + +## 必须记住的规则 + +- 选股和信号属于业务层模式,不是通用语言规则。 +- 语言层只回答“条件怎么写”;finance 层回答“这些条件怎样组成选股/信号任务”。 +- 如果问题开始变成某个基础运算符怎么写,应回到 syntax 层。 + +## 任务骨架 + +1. 先写条件表达:澄清你在筛什么、比较什么、窗口是多少。 +2. 再生成信号:决定输出是布尔筛选、买卖信号,还是评分 / 排序结果。 +3. 最后整理结果输出:决定是输出标的列表、信号列、分数字段,还是交给下游回测。 + +## 常见任务形态 + +- 单次筛选:给定条件,输出满足条件的标的集合。 +- 连续信号:按时间推进,逐 bar 产生买入 / 卖出 / 持有信号。 +- 评分排序:先算分,再做阈值过滤、排名或分组。 + +## 写之前先决定 + +- 条件是在“当前 bar 是否成立”,还是“最近 N 个 bar 的模式是否成立”。 +- 信号是即时使用,还是要保存成后续回测 / 执行的输入。 +- 输出面向人看,还是面向下游框架消费。 + +## 常见误判 + +- 把一个业务筛选范式误写成“所有 TSL 都应这样写”的基础语法结论。 +- 不区分“条件表达成立”与“选股任务组织合理”这两件事。 +- 还没确认输出形式,就先把条件堆成很长的单条表达式。 +- 把筛选条件、信号生成和结果输出混写在一个不可拆分的大块里。 + +## 跳转指引 + +- 指标与序列:见 [series_and_indicator_model.md](series_and_indicator_model.md) +- 市场上下文:见 [market_data_context.md](market_data_context.md) +- 回测与交易:见 [backtest_and_trade_flow.md](backtest_and_trade_flow.md) +- 基础语法:见 [../syntax/index.md](../syntax/index.md) diff --git a/docs/tsl/finance/series_and_indicator_model.md b/docs/tsl/finance/series_and_indicator_model.md new file mode 100644 index 00000000..492aa142 --- /dev/null +++ b/docs/tsl/finance/series_and_indicator_model.md @@ -0,0 +1,53 @@ +# Series And Indicator Model + +文档类型:业务骨架 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[market_data_context.md](market_data_context.md)、[selection_and_signal_patterns.md](selection_and_signal_patterns.md)、[../syntax/index.md](../syntax/index.md) + +这一篇处理金融序列与指标计算模式。 + +## 这一篇解决什么问题 + +回答“指标、序列、逐 bar 计算和相关金融表达方式如何组织,以及 AI 应该先建立什么样的业务心智模型”。 + +## 必须记住的规则 + +- 序列与指标属于业务模型,不属于通用语法。 +- 当你需要解释循环、表达式、数组和字符串时,应回到 syntax 层。 +- 当你需要解释“指标如何依赖历史序列”时,才留在这里。 + +## 输入上下文 + +- 先确认标的、周期、起止区间和复权口径。 +- 先确认你在处理“单值输入”还是“逐 bar 序列输入”。 +- 先确认指标依赖多少历史窗口,以及窗口未满时如何处理。 + +## 逐 bar 心智模型 + +- 每个 bar 只应使用当前 bar 及其之前已经可见的信息。 +- 先准备输入序列,再计算当前 bar 的指标值,最后再决定当前 bar 的输出。 +- 不要把后面的 bar 结果回填到前面的 bar。 +- 不要把“能写成一个表达式”误解成“就不需要业务上下文”。 + +## 窗口依赖 + +- 任何均线、滚动统计、历史比较,先写清窗口长度。 +- 窗口未满前,先决定是跳过、返回空值,还是走 warm-up 逻辑。 +- 多条序列一起参与计算时,先确认时间轴是否对齐。 +- 当结果依赖前值时,先确认你是在做“当前 bar 计算”还是“状态延续”。 + +## 常见误判 + +- 把指标写法误当成“TSL 基础表达式”的定义来源。 +- 在没有澄清数据频率、窗口和上下文前,就直接抽象成通用语法规则。 +- 把未来数据混进当前 bar 的计算里。 +- 先写公式,再补上下文,导致窗口长度和序列来源都不明确。 + +## 跳转指引 + +- 市场数据上下文:见 [market_data_context.md](market_data_context.md) +- 选股与信号:见 [selection_and_signal_patterns.md](selection_and_signal_patterns.md) +- 回测与交易:见 [backtest_and_trade_flow.md](backtest_and_trade_flow.md) +- 表达式与控制流语法:见 [../syntax/07_expressions_and_operators.md](../syntax/07_expressions_and_operators.md) 与 [../syntax/08_control_flow.md](../syntax/08_control_flow.md) diff --git a/docs/tsl/index.md b/docs/tsl/index.md new file mode 100644 index 00000000..8f0f4096 --- /dev/null +++ b/docs/tsl/index.md @@ -0,0 +1,111 @@ +# TSL Index + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[syntax/index.md](syntax/index.md)、[finance/index.md](finance/index.md)、[reference/index.md](reference/index.md)、[modules/index.md](modules/index.md)、项目自身文档、`scripts/*` 入口脚本、CI 配置 + +这个入口文件只负责一件事:让新 session 先判断主问题属于哪一层,再进入最相关的单个入口页。 + +## 先记住这些规则 + +- 先读本文件,不要默认通读全部 TSL 文档。 +- 语言怎么写的问题,先从 `docs/tsl/syntax/` 开始。 +- 指标、选股、回测和策略流程的问题,先从 `docs/tsl/finance/` 开始;不要先把业务问题拆成纯语法问题。 +- 某个函数怎么用、属于哪个函数库分类或目录,先从 `docs/tsl/reference/` 开始。 +- 现成模块、外部集成和互操作问题,先从 [modules/index.md](modules/index.md) 开始。 +- 账户体系、真实接口名、部署方式、脚本入口、权限模型、环境变量、CI、验证命令这类问题,先按“项目依赖 / 项目执行”处理;优先回项目自身文档、`scripts/*` 入口脚本、CI 配置。 +- [toolchain.md](toolchain.md) 不是 TSL 语法子类,而是项目执行类辅证页;只有当前项目已经补齐工具链与验证信息时才使用;如果这页仍是模板,不把它当主入口。 +- 顶层主体优先按四类理解:松散语句、`function / procedure`、`type Name = class`、`unit`。 +- 不要把顶层 `function / procedure` 定义和松散语句混在同一个文件模型里。 +- 任何语法判断都先看正式语法页结论。 +- 如果涉及较新写法、资料冲突或解释器差异,先回到 `docs/tsl/syntax/index.md`,再按主题跳到对应语法页;只有对应主题页仍然没有结论时,才本地用 `tsl` 验证。 +- 如果涉及高频误写、反例或负向边界,优先回到 `docs/tsl/syntax/12_pitfalls.md`;只有结论缺失时,才本地用 `tsl` 验证。 +- 模板、错误示例和输出片段不算可独立编译代码。 + +## 元数据与证据标签 + +- 页头里的 `是否可直接用于生成代码` 只做页面级粗判断;如果页内已经给出 `代码块身份`,一律以块级标签为准。 +- `是否可直接用于生成代码` 有三种值:`是`、`否`、`仅部分`;其中 `仅部分` 表示页内既有可直接参考的块,也有依赖多文件、查找路径或运行时环境的块,必须继续看块级标签。 +- `是否含已验证可执行示例` 只统计已经跑通、可以直接参考外形的正向代码示例。 +- `是否含已验证反例` 只统计已经确认不能照写的负向例子。 +- `代码块身份` 只使用固定词表:`已验证可执行示例`、`已验证输出片段`、`反例 / 不可照写`、`配置片段 / 概念骨架`。 +- 如果还需要补充用途、限制或复用建议,单独写 `代码块说明`,不要把说明文字继续拼进 `代码块身份`。 +- 如果页头里的 `遇到不确定时跳转到` 列出多个目标,默认第一项是优先入口,后面的目标只用于分流或补证。 + +## 新 session 起手规则 + +### If / Then 路由 + +- If 问题在问“语言怎么写”,then 先从 [syntax/index.md](syntax/index.md) 开始。 +- If 问题在问“指标 / 选股 / 回测怎么组织”,then 先从 [finance/index.md](finance/index.md) 开始。 +- If 问题在问“某个函数怎么用”或“函数属于哪个函数库分类 / 目录”,then 先从 [reference/index.md](reference/index.md) 开始。 +- If 问题在问“现成模块 / 集成 / 互操作”,then 先从 [modules/index.md](modules/index.md) 开始。 +- If 问题依赖项目实际接口、账户体系、部署方式、脚本入口、权限模型、环境变量、CI 或验证命令,then 不把它当通用 TSL 事实;优先回项目自身文档、`scripts/*` 入口脚本、CI 配置;只有当前项目已补齐时,才把 [toolchain.md](toolchain.md) 当辅证页。 +- If 问题在问“这句语法能不能写”,then 先从 [syntax/index.md](syntax/index.md) 开始。 +- If 问题在问“较新写法 / 新能力并入 / 资料冲突 / 解释器版本边界”,then 先看 [syntax/index.md](syntax/index.md),再按主题跳到对应语法页。 +- If 问题在问“高频误写 / 反例核对 / 负向边界”,then 先看 [syntax/12_pitfalls.md](syntax/12_pitfalls.md)。 + +### Tie-Break + +- If 一个问题同时涉及业务和语法,then 先按主问题分层。 +- If 主问题是业务实现,then 先走 `finance/` 或 `modules/`,语法只作辅证,不反过来吞掉业务入口。 +- If 主问题是语言写法,then 先走 `syntax/`,金融或模块页只作为示例和上下文。 +- If 主问题已经落到真实接入参数、账号来源、部署依赖、执行入口或权限模型,then 直接转“项目依赖 / 项目执行”确认,不继续在 `modules/`、`syntax/` 或模板型 `toolchain.md` 里兜圈子。 + +### 语言事实 + +- 可以先把 TSL 当成 Pascal 风格语言去理解:`function`、`begin`、`end`、`unit`、`uses` 都很接近;但这里只借外形,不默认继承 Pascal 的全部语义、库习惯和文件模型。 +- 涉及赋值、`function / procedure` 外形、`unit` 骨架、命名参数、`type Name = class`、数组 / 字符串下标这类高频硬规则,统一以 [syntax/02_quickstart.md](syntax/02_quickstart.md) 的“语言核心事实速查”为准;当前页只保留跨层路由所需的最小提醒。 + +#### 写代码前先记住 + +- 写代码前先把高频硬规则收口到 [syntax/02_quickstart.md](syntax/02_quickstart.md),不要分别从入口页、介绍页和文件模型页拼接结论。 +- 顶层主体仍优先按四类理解:松散语句、`function / procedure`、`type Name = class`、`unit`。 +- 模板、错误示例和输出片段不算可独立编译代码;真正落代码时优先看块级 `代码块身份`。 + +### 手册建模规则 + +- 更可靠的识别方式是看顶层内容,而不是只看文件扩展名。 +- 顶层允许出现 `uses`,但这里只把它当辅助语句,不把它当主体声明。 +- 下游大量 `program test; begin ... end.` 形式,只作为自包含验证样例外壳,不作为这里归纳的正式顶层模型。 + +## 如果你马上要写 TSL + +- 先看 [syntax/02_quickstart.md](syntax/02_quickstart.md) +- 再看 [syntax/index.md](syntax/index.md) +- 然后看 [syntax/12_pitfalls.md](syntax/12_pitfalls.md) +- 最后按需补看相应专题页 + +## 最短跳转 + +| 当前任务 | 先读哪里 | +| --- | --- | +| 我要系统入门 TSL | [syntax/index.md](syntax/index.md) | +| 我要先核对语言核心事实 | [syntax/02_quickstart.md](syntax/02_quickstart.md) | +| 我要写最短可运行骨架 | [syntax/02_quickstart.md](syntax/02_quickstart.md) | +| 我要判断“这句语法能不能写” | [syntax/index.md](syntax/index.md) | +| 我要核对较新写法 / 新能力并入 / 资料冲突 / 解释器版本边界 | [syntax/index.md](syntax/index.md),再按主题跳到对应语法页 | +| 我要核对高频误写 / 反例 / 负向边界 | [syntax/12_pitfalls.md](syntax/12_pitfalls.md) | +| 我要知道正式语法手册现在还差什么 | [syntax/coverage_map.md](syntax/coverage_map.md) | +| 我要写金融指标 / 选股 / 回测 | [finance/index.md](finance/index.md) | +| 我要看模块 / 集成 / 互操作入口 | [modules/index.md](modules/index.md) | +| 我要确认账户体系 / 真实接口 / 部署方式 / 脚本入口 / 环境变量 / CI / 验证命令 | 项目自身文档、`scripts/*` 入口脚本、CI 配置;当前项目已补齐时再看 [toolchain.md](toolchain.md) | +| 我要看回测框架模块 | [modules/tsbacktesting.md](modules/tsbacktesting.md) | +| 我要看 Python 互操作 | [modules/tsl_python_interop.md](modules/tsl_python_interop.md) | +| 我要看微信消息推送 | [modules/wechat_message.md](modules/wechat_message.md) | +| 我要看 Python API | [modules/pytsl_api.md](modules/pytsl_api.md) | +| 我要查函数库 | [reference/index.md](reference/index.md) | +| 当前项目已补齐工具链时,看工具链 / 项目执行辅证 | [toolchain.md](toolchain.md) | +| 我要避开高频误写 | [syntax/12_pitfalls.md](syntax/12_pitfalls.md) | + +## 进入之后怎么读 + +1. 先判断主问题属于语法、业务、函数库、模块/集成,还是项目依赖 / 项目执行。 +2. 如果主问题是项目依赖 / 项目执行,直接回项目自身文档、`scripts/*` 入口脚本或 CI 配置;只有当前项目已经补齐时,才把 [toolchain.md](toolchain.md) 当辅证。 +3. 否则先进入一个最相关的入口页,不要同时展开多个层。 +4. 当前页如果已经给出结论,先采用;准备编写时优先找已验证正例,再落代码;只有需要补充时再跳到相邻页。 +5. 遇到“资料写法不一致”且偏较新写法、资料冲突或解释器差异时,先回 [syntax/index.md](syntax/index.md) 按主题跳到对应语法页。 +6. 遇到“资料写法不一致”且偏高频误写、反例或负向边界时,先看 [syntax/12_pitfalls.md](syntax/12_pitfalls.md)。 +7. 只有当前手册没有给出结论时,才写最小 `.tsl` / `.tsf` 例子并用 `tsl` 实测。 diff --git a/docs/tsl/modules/index.md b/docs/tsl/modules/index.md new file mode 100644 index 00000000..dd2b9561 --- /dev/null +++ b/docs/tsl/modules/index.md @@ -0,0 +1,40 @@ +# Modules Index + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[tsbacktesting.md](tsbacktesting.md)、[tsl_python_interop.md](tsl_python_interop.md)、[../finance/index.md](../finance/index.md)、项目自身文档、`scripts/*` 入口脚本、CI 配置 + +这里处理“现成模块、外部集成和互操作”,不处理基础语法教学,也不替代金融业务主线。 + +模块摘要页只负责确认能力边界和选路,不负责给出项目账户体系、真实接口名、部署方式、权限模型或脚本入口的真值。 + +## If / Then 路由 + +- If 问题在问“策略回测框架怎么组织、怎么取结果”,then 先读 [tsbacktesting.md](tsbacktesting.md)。 +- If 问题在问“TSL 和 Python 怎样双向调用或嵌入”,then 先读 [tsl_python_interop.md](tsl_python_interop.md)。 +- If 问题在问“微信消息怎样发送、查询状态”,then 先读 [wechat_message.md](wechat_message.md)。 +- If 问题在问“官方 Python SDK / pyTSL 客户端怎么用”,then 先读 [pytsl_api.md](pytsl_api.md)。 +- If 问题在问模块的真实接入参数、账号来源、部署依赖、权限模型或脚本入口,then 这已经不是模块能力识别;优先回项目自身文档、`scripts/*` 入口脚本、CI 配置,必要时再把对应模块页当边界说明。 + +## Tie-Break + +- If 主问题是业务流程、选股逻辑或回测指标组织,then 先回 [../finance/index.md](../finance/index.md)。 +- If 主问题是现成模块或集成能力,then 先留在 `modules/`;语法只作辅证。 +- If 主问题已经落到 TSL 通用函数库签名或通用语法参数细节,then 再回 [../reference/index.md](../reference/index.md) 或对应语法页。 +- If 主问题已经落到模块专属 API / SDK 参数细节,then 先回对应模块页,并以该页指向的官方文档、项目文档或调用侧文档为准。 +- If 主问题已经落到真实接入参数、账号来源、部署依赖、权限模型或执行入口,then 退出模块摘要层,直接转项目依赖确认。 + +## 最短跳转 + +| 当前任务 | 先读哪里 | +| --- | --- | +| 我要看回测框架 | [tsbacktesting.md](tsbacktesting.md) | +| 我要看 Python 互操作 | [tsl_python_interop.md](tsl_python_interop.md) | +| 我要看微信消息推送 | [wechat_message.md](wechat_message.md) | +| 我要看 Python API | [pytsl_api.md](pytsl_api.md) | +| 我要确认模块的真实接入参数 / 账号来源 / 部署依赖 / 脚本入口 | 项目自身文档、`scripts/*` 入口脚本、CI 配置;当前项目已补齐时再看 [../toolchain.md](../toolchain.md) | +| 我要回到业务主线 | [../finance/index.md](../finance/index.md) | +| 我要回到语法主线 | [../syntax/index.md](../syntax/index.md) | +| 我要查函数库 | [../reference/index.md](../reference/index.md) | diff --git a/docs/tsl/modules/pytsl_api.md b/docs/tsl/modules/pytsl_api.md index 0de31714..d43fb788 100644 --- a/docs/tsl/modules/pytsl_api.md +++ b/docs/tsl/modules/pytsl_api.md @@ -1,5 +1,15 @@ # 天软 pyTSL 接口使用说明 +文档类型:模块摘要 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:项目级部署文档、官方 pyTSL 详细接口文档、[tsl_python_interop.md](tsl_python_interop.md)、[index.md](index.md) + +本页用于确认 pyTSL 的接入方向和最小链路,不替代项目级部署文档或完整接口手册。 + +- 如果登录方式、凭证来源、环境变量、部署入口、连接上下文或返回结构没有确认,不继续生成接入代码,直接回项目级部署文档或官方 pyTSL 详细接口文档。 + ## 定位 - 官方 Python SDK,面向取数/执行/批量/异步与数据转换。 @@ -17,6 +27,12 @@ - `pip install tspytsl`(在线安装) - 离线安装与手动部署 +## 同步 / 异步怎么选 + +- 同步:任务短、交互简单、立即取结果时优先用 `pyTSL.Client`。 +- 异步:任务长、需要并发或批量调度时再看 `pyTSL.AsyncClient` 与 `async_util`。 +- 如果只是先打通最小链路,先用同步客户端,不要一开始就上异步。 + ## 核心类与模块 - `pyTSL.Client`:同步客户端 @@ -35,8 +51,31 @@ - `EncodeStream` / `DecodeStream` - `DataFrameToTSArray` +## 最小成功路径 + +1. 先回项目级部署文档确认登录方式、凭证来源、环境变量和部署入口。 +2. 安装 `tspytsl`。 +3. 创建 `pyTSL.Client(...)`。 +4. 调 `login()` 登录。 +5. 用 `query(...)`、`exec(...)` 或 `call(...)` 执行任务。 +6. 从返回结果里读取你真正需要的内容;常见起手是 `result.dataframe()`。 +7. 完成后显式 `logout()`。 + +## 返回结果与失败处理 + +- 常见返回会落在 `TSResultValue` 这一层;真正用之前,先确认你要的是表格、标量还是其他结构。 +- 最小起手路径可以先看 `result.dataframe()` 是否符合预期,再扩展到别的读取方式。 +- 登录、查询和退出应当成对出现;不要把长期未退出的连接当默认用法。 +- 如果失败,先检查安装、登录上下文、查询语句和返回结构,再决定是否切到异步客户端。 +- 如果还不能确认登录方式、凭证来源或返回结构,不继续扩展接入代码,先回项目级部署文档和官方接口文档。 + ## 示例(Python) +示例里的 `"user"` / `"password"` 只表示调用外形,不代表项目里的真实登录方式或凭证来源。 + +代码块身份:配置片段 / 概念骨架 +代码块说明:可参考最小链路,不是已验证可执行示例。 + ```python import pyTSL diff --git a/docs/tsl/modules/tsbacktesting.md b/docs/tsl/modules/tsbacktesting.md index 7c1991c0..05d9d123 100644 --- a/docs/tsl/modules/tsbacktesting.md +++ b/docs/tsl/modules/tsbacktesting.md @@ -1,66 +1,53 @@ # 策略回测框架 TSBackTesting -## 定位 +文档类型:模块摘要 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:项目实际接口定义、[../finance/backtest_and_trade_flow.md](../finance/backtest_and_trade_flow.md)、[index.md](index.md) -- 提供统一的策略回测框架(股票/期货/期权/组合等),覆盖资金、交易约束、清算与绩效输出。 +本页不足以直接生成回测代码,只用于确认回测任务的组织顺序,以及哪些地方必须回到项目实际接口定义继续核对。 -## 结构索引 +- 只要任务已经进入对象创建、交易输入入口、结果读取方法或项目封装差异,就先停止生成,直接回项目实际接口定义,不要先拼调用链。 -- 策略回测流程 -- 成员变量 -- 成员方法 -- 查询用接口 -- 回测范例 -- 债券品种回测说明 -- 期权组合策略回测说明 -- 常见问题 +## 适用场景 -## 回测流程概览 +- 任务已经进入“回测框架怎么配置、怎么执行、怎么读结果”。 +- 你处理的是组合型任务,而不是单纯的表达式或单次筛选。 +- 你已经知道自己要做比例类组合还是数量类组合,或者正在先判断这件事。 -- 组合类型选择 → 交易数据准备 → 回测执行 → 结果查询与分析。 +## 当前只确认的范围 -## 组合类型 +- 当前页已经确认的范围是:对象名 `TSBackTesting`、典型任务顺序、组合类型差异、常见字段组和常见结果接口类别。 +- 下面出现的字段名和结果接口名,只用于检索候选和理解类别,不是可以直接假定存在的项目接口真值。 +- 任务顺序可以先按这条主线理解:组合类型选择 → 交易数据准备 → 回测执行 → 结果查询与分析。 +- 组合类型先按两类理解:比例类组合提供目标权重,数量类组合提供成交量或成交价等交易明细。 +- 常见字段组可以先按以下几类检索: + - 时间与周期:`FBegT`、`FEndT`、`FCycle` + - 组合类型:`FGroupType` + - 资金与价格:`FIniCash`、`FPriceType`、`FPriceType1..4` + - 交易约束:`FNoZT`、`FNoDT`、`FMinVol`、`FMinAmount`、`FMaxVolPercent`、`FMaxAmountPercent` + - 费用与分红:`FFeeType`、`FlowestFeeType`、`FDividendType` + - 基准与输出:`FBMType`、`FBMDetail`、`FBMOption`、`FHFDataOutPut` +- 常见结果接口可以先按以下类别检索:`GetTimeSeries`、`GetTradeOrder`、`GetNetAssetValue` / `GetAssetData` / `GetHoldData`、`GetPercent`、`GetIRRReturn`、`ReturnBenchmark`。 -- 比例类组合:提供目标权重。 -- 数量类组合:提供成交量/成交价等交易明细。 +## 任务骨架(非代码模板) -## 关键成员变量(分组摘要) +1. 先判断任务属于比例类组合还是数量类组合。 +2. 然后先回到项目实际接口定义,确认最小可用对象模型、对象创建方式、最小必填项和交易数据输入入口。 +3. 再确认起止时间、组合类型和初始资金是不是项目里的最小必填项。 +4. 执行回测。 +5. 最后先按项目实际接口定义确认结果读取链路,再读取净值时间序列、成交结果或持仓结果,再补看绩效指标。 -- **时间与周期**:`FBegT`、`FEndT`、`FCycle` -- **组合类型**:`FGroupType`(比例类/数量类) -- **资金与价格**:`FIniCash`、`FPriceType`、`FPriceType1..4` -- **交易约束**:`FNoZT`、`FNoDT`、`FMinVol`、`FMinAmount`、`FMaxVolPercent`、`FMaxAmountPercent` -- **费用与分红**:`FFeeType`、`FlowestFeeType`、`FDividendType` -- **期权与期货特性**:`FOptionRs`、`FMainFutureMap` -- **基准与输出**:`FBMType`、`FBMDetail`、`FBMOption`、`FHFDataOutPut` +## 不要猜的部分 -> 详细取值及说明以实际接口定义为准。 +- 当前页没有确认的范围是:对象创建方式、最小必填字段的强制集合、交易数据入口名、最小输入结构、结果读取完整链路。 +- 如果没有项目实际接口定义,不要根据本页直接写 `new TSBackTesting()`、`SetTradeData(...)` 或其他具体调用链。 +- 各字段可选值和更细接口,以实际接口定义为准;当前页只负责告诉你要核对哪些位置,不负责补全细节。 -## 关键成员方法(常用) +## 跳转指引 -- `BackTest`:执行回测 -- `GetTimeSeries`:返回净值/收益率时间序列 -- `GetTradeOrder`:返回调仓/成交数据 -- `GetNetAssetValue` / `GetAssetData` / `GetHoldData`:资产与持仓 -- `GetPercent`、`GetIRRReturn`、`ReturnBenchmark`:绩效指标 -- `GetClearancePrice` / `GetIntVol` / `GetOtherData`:扩展查询 - -## 最小流程示例(概念化) - -```tsl -// 1) 初始化参数 -backtest := new TSBackTesting(); -backtest.FBegT := 20240101T; -backtest.FEndT := 20241231T; -backtest.FGroupType := 1; // 比例类 -backtest.FIniCash := 1000000; - -// 2) 设置交易数据(比例类:目标持仓) -// backtest.SetTradeData(trade_data); - -// 3) 执行回测 -backtest.BackTest(); - -// 4) 获取结果 -return backtest.GetTimeSeries(); -``` +- 业务组织问题:见 [../finance/backtest_and_trade_flow.md](../finance/backtest_and_trade_flow.md) +- 具体字段、交易数据入口、对象创建方式和结果接口真值:回项目实际接口定义 +- 回到模块入口:见 [index.md](index.md) +- 只在需要查 TSL 通用函数归类时,才回 [../reference/index.md](../reference/index.md) diff --git a/docs/tsl/modules/tsl_python_interop.md b/docs/tsl/modules/tsl_python_interop.md index f8325279..470b8897 100644 --- a/docs/tsl/modules/tsl_python_interop.md +++ b/docs/tsl/modules/tsl_python_interop.md @@ -1,10 +1,28 @@ # 天软平台和 Python 的交互 +文档类型:模块摘要 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:项目级部署文档、对应官方文档、[pytsl_api.md](pytsl_api.md)、[index.md](index.md) + +本页用于接入决策和最小链路确认,不替代项目级部署文档。 + +- 如果登录方式、凭证来源、位数、环境变量、连接通道或部署入口没有确认,不继续生成接入代码,直接回项目级部署文档或对应官方文档。 + ## 摘要 - 覆盖三类交互:Python 调用 TSL、TSL 调用 Python、落地服务器开启 Python 服务。 - 提供 COM/远程登录两种路径,以及 `PyRun`/`PyCall` 体系。 +## 怎么选路 + +| 场景 | 先选哪条路 | 最小前置条件 | 常见失败点 | +| --- | --- | --- | --- | +| Python 作为主控,远程执行或调用 TSL | Python 调 TSL | Python 环境、TSLPy 模块、可用连接方式(COM / 远程登录) | 位数不一致、环境变量没配好、服务器未登录 | +| TSL 脚本里需要调用现有 Python 代码 | TSL 调 Python | TSL 与 Python 位数一致、`PYTHONHOME` 等环境正确 | Python 环境未就绪、模块找不到、网格场景不支持 | +| 落地服务器侧长期提供 Python 能力 | 落地服务器开启 Python 服务 | 服务端环境、部署权限、可维护的脚本入口 | 服务端环境和本地环境不一致、依赖未部署、运行权限不足 | + ## 结构索引 - 支持版本 @@ -17,9 +35,12 @@ ## Python 调用 TSL(核心步骤) -1. 配置环境变量(天软目录、Python 目录)。 -2. 加载 TSLPy 模块(直接加载或修改包名)。 -3. 选择连接方式(COM / 远程登录)。 +1. 先确认项目级部署文档里的天软目录、Python 目录、位数、连接通道和登录方式。 +2. 配置环境变量(天软目录、Python 目录)。 +3. 加载 TSLPy 模块(直接加载或修改包名)。 +4. 选择连接方式(COM / 远程登录)。 +5. 登录服务器后,再执行 `RemoteExecute` / `RemoteCallFunc`。 +6. 完成后显式断开连接。 ## 主要接口(Python 侧) @@ -35,12 +56,38 @@ - `PyCall`(调用 Python 函数,支持命名参数) - `PyError` / `PyRelease` / `PyEnsure` +## TSL 调用 Python(核心步骤) + +1. 先回项目级部署文档确认位数、`PYTHONHOME`、解释器路径和可用模块。 +2. 用 `PyEnsure` 确认 Python 运行时已经就绪。 +3. 需要把输入传给 Python 时,先用 `PyPutVar` 放入变量。 +4. 选择执行方式:执行整段脚本用 `PyRun`,直接调函数用 `PyCall`。 +5. 需要取回结果时,再用 `PyGetVar` 读取输出变量。 +6. 失败时先看 `PyError`,结束后显式 `PyRelease`。 + +## 最小前置条件 + +- Python 与 TSL 位数必须一致。 +- 多版本 Python 需同步设置 `PYTHONHOME`。 +- 落地前先决定是谁主控:Python 主控还是 TSL 主控。 + ## do Python 方式 - 适合快速执行 Python 脚本,省去显式接口调用。 +## 落地服务器开启 Python 服务(核心步骤) + +1. 先回项目级部署文档确认服务入口、部署权限、依赖目录和守护方式。 +2. 在服务器上准备与项目要求一致的 Python 运行时和依赖包。 +3. 放置一个稳定的 Python 脚本或服务入口,先只承载一条最小调用链。 +4. 按项目约定把这个入口接到天软侧的调用路径或调度入口。 +5. 用最小请求先验证“能启动、能调用、能返回”,再扩展业务逻辑。 +6. 再补日志、重启方式和运维监控;如果这些入口还没确认,不继续生成部署代码。 + ## 注意事项(精简) - Python 与 TSL 位数必须一致。 - 多版本 Python 需同步设置 `PYTHONHOME`。 - TSL 调 Python 不支持网格调用。 +- 出现调用失败时,优先先检查环境、位数和登录状态,再排查业务逻辑。 +- 如果登录方式、凭证来源、位数、环境变量、连接通道或部署入口任一没有确认,不继续生成接入代码。 diff --git a/docs/tsl/modules/wechat_message.md b/docs/tsl/modules/wechat_message.md index 2e3e4260..84c68f02 100644 --- a/docs/tsl/modules/wechat_message.md +++ b/docs/tsl/modules/wechat_message.md @@ -1,6 +1,14 @@ # 发送微信消息使用说明 -## 摘要 +文档类型:模块摘要 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:调用侧账户体系文档、项目实际接口说明、[index.md](index.md) + +本页用于确认接口名称、参数含义和风险边界,不替代项目级接入文档。 + +## 适用场景 - 通过“天软科技服务号”向微信客户端发送模板消息。 - 支持同步/异步发送,异步可用消息 ID 查询状态。 @@ -22,6 +30,7 @@ ## 参数说明(模板消息) - `userid`:绑定账户后获取的用户标识(必需)。 +- `username`:查询异步发送状态时使用的用户名 / 账户标识;当前页只确认查询接口需要它,具体来源以项目实际账户体系或调用侧约定为准。如果调用侧拿不到该值,当前页不支持生成状态查询代码。 - `url`:详情地址(必需,可为空字符串)。 - `title`:模板消息标题(必需)。 - `first`:副标题(一般需要)。 @@ -35,8 +44,23 @@ - 同步:阻塞等待结果,适合紧急通知。 - 异步:立即返回,适合非紧急通知;用 `get_wechat_message_status` 查询。 +- 如果你无法确认 `username` 的来源,不要自行猜测;先回调用侧或账户体系文档确认。 -## 示例(TSL) +## 当前只确认的范围 + +- 当前页已经确认的范围是:发送接口名、异步发送会返回消息 ID、状态查询接口需要 `userid` + `username` + `wechat_message_id`。 +- 当前页没有确认的范围是:`username` 的正式来源、不同模板关键字的完整映射、项目侧的统一封装方式。 + +## 不要猜的部分 + +- 不要把 `"username"` 当成可用实参,也不要凭空拼接账户名。 +- 如果调用侧没有提供 `username`,当前页只支持生成发送代码,不支持生成状态查询代码。 +- `k1..k6` 的含义随模板类型变化;需要和具体模板一起核对。 + +## 发送示例(配置片段,可参考参数组织) + +代码块身份:配置片段 / 概念骨架 +代码块说明:可参考参数组织,不是已验证可执行示例。 ```tsl // 定义参数 @@ -55,6 +79,9 @@ echo send_wechat_message(user_id, url, title, first, remark, keyword_1, keyword_ // 异步发送 wechat_message_id := send_wechat_message_async(user_id, url, title, first, remark, keyword_1, keyword_2); -// 获取结果 -echo get_wechat_message_status(user_id, "username", wechat_message_id); ``` + +## 状态查询示例 + +- 当前页不提供状态查询代码块。 +- 只有在调用侧已经明确提供 `username` 来源时,才继续生成 `get_wechat_message_status(...)` 调用。 diff --git a/docs/tsl/naming.md b/docs/tsl/naming.md index 4d3dfb68..b2ea29e7 100644 --- a/docs/tsl/naming.md +++ b/docs/tsl/naming.md @@ -1,8 +1,16 @@ # TSL 命名规范(Naming) +文档类型:规范页 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[code_style.md](code_style.md)、[syntax/index.md](syntax/index.md)、[syntax/03_core_model.md](syntax/03_core_model.md) + 本仓库命名规则与 Google C++ Style Guide 对齐:通过名字的“形状”快速判断实体类型(类型/函数/变量/常量等),减少阅读成本。 +以下出现的 `<...>` 形式只表示命名或注释模板占位,不是源码字面量。 + ## 1. 选名原则 - **可读一致**:名字清晰可读,并随可见范围调整具体程度。 @@ -42,42 +50,47 @@ Guide 对齐:通过名字的“形状”快速判断实体类型(类型/函 ## 3. 类型命名(Type Names) -TSL 的顶层声明只有三种:`class`、`unit`、`function`(仅适用于 `.tsf`)。因此 -`.tsf` 文件基名必须与顶层声明同名(见“4. 文件命名与顶层声明”)。 +AI 先按四类顶层外形判断文件模型:顶层松散语句、顶层 `function / procedure`、 +顶层 `type Name = class`、顶层 `unit`。本页只覆盖“需要命名的顶层实体”,不覆盖松散语句本身;文件模型判断本身以 +`docs/tsl/syntax/03_core_model.md` 为准。 -- **类(class)与单元(unit)**使用 +- **类与单元**使用 `PascalCase`,不带下划线;名称应为名词/名词短语(通常单数),避免动词开头。 +- 顶层类的正式写法统一按 `type Name = class ... end;` 理解;不要把裸 `class` + 当成正式顶层类模型的简称。 - 不推荐 `*Unit` 作为 `unit` 的后缀(`unit` 本身已表达语义);需要表达用途时,可使用 `*Shared`/`*Common`/`*Enums` 等更具体后缀(按团队约定)。 -- **顶层函数(function)**使用 `PascalCase`;名称优先动词/动词短语(例如 +- **顶层函数 / 过程**使用 `PascalCase`;名称优先动词/动词短语(例如 `Load`/`Parse`/`Build`),详见函数命名章节。 -- 示例:`UserAccount`、`OrderShared`、`LoadMarketData()`。 +- 示例:`UserAccount`、`OrderShared`、`LoadMarketData()`、`FlushCache()`。 ## 4. 文件命名与顶层声明(File Names) TSL 的语法要求(仅 `.tsf`):每个 `.tsf` 文件只能有一个顶层声明,且**文件基名必须与该顶层声明名字一致**。 -- 顶层声明可能是 `class`、`unit` 或 `function`(见类型命名)。 -- `.tsf` 代码文件:用于库/模块等“顶层声明”的承载文件;顶层声明可为 - `class`/`unit`/`function`,文件基名需与之同名。 +- 更可靠的判断方式仍然是先看顶层内容,而不是只看扩展名;命名规范只是补充“命名后的实体如何取名”,不替代文件模型判断。 +- 需要命名的顶层实体可以是 `function / procedure`、`type Name = class`、`unit`。 +- `.tsf` 代码文件:用于库/模块等“顶层声明”的首选承载文件;顶层声明可为 + `function / procedure`、`type Name = class`、`unit`,文件基名需与之同名。 - `.tsl` 脚本文件:用于入口/编排层;允许直接写语句(如 - `a := 1; echo a;`),不要求顶层声明,也不强制文件基名与函数名一致;可复用逻辑应下沉到 + `a := 1; echo a;`),也可能出现顶层 `function / procedure` 骨架或 `program test;` + 这类验证样例外壳;但风格上不把 `.tsl` 当成可复用顶层声明的默认落点,也不要求文件基名与函数名一致;可复用逻辑优先下沉到 `.tsf`(见 `docs/tsl/code_style.md`)。 - 注:`.tsf` 也是 TSL 源文件,命名/风格与 `.tsl` 遵循同一套规则。 - **硬规则(仅 - `.tsf`)**:重命名顶层声明时必须同步重命名文件基名,否则语法/加载规则无法识别;批量重命名可参考 - `$bulk-refactor-workflow`。 + `.tsf`)**:重命名顶层声明时必须同步重命名文件基名,否则语法/加载规则无法识别;批量重命名时也必须把这两处一起改掉。 命名建议: - 基名统一使用 `PascalCase`,与顶层声明的推荐写法一致。 - 示例: - - `LoadMarketData.tsl` 中定义 `function LoadMarketData(...)`. + - `DailyEntry.tsl` 作为入口 / 编排脚本,主体是松散语句或验证样例外壳。 - `UserAccount.tsf` 中定义 `type UserAccount = class ... end;`. - `DocxEnumerations.tsf` 中定义 `unit DocxEnumerations; ... end.` - `ParseConfig.tsf` 中定义 `function ParseConfig(...)`. + - `FlushCache.tsf` 中定义 `procedure FlushCache(...);`. 注:TSL 大小写无关,实际编译时按大小写比较不会出错,但仍应保持文件名与声明名的推荐写法一致以便检索与协作。 @@ -108,11 +121,13 @@ TSL 的语法要求(仅 `.tsf`):每个 `.tsf` `IsReady`),对应私有成员可用 `is_ready_` 等。 - 示例: +代码块身份:配置片段 / 概念骨架 + ```tsl type User = class public property UserId read user_id_ write user_id_; - property IsReady read is_ready_; // bool property example + property IsReady read is_ready_; private user_id_; is_ready_; @@ -131,8 +146,11 @@ end; - 命名仍使用 `snake_case`(不使用 `g_` 前缀)。 - 必须在声明处写注释说明:它是什么、用于什么、以及(如不明显)为什么需要是全局/静态。 - 建议补充写入点与生命周期:谁会写、何时写、何时清理/重置;如涉及并发,写明并发假设/保护方式。 - - 不要在注释/日志中写入任何敏感信息(参考 `.agents/tsl/auth.md`)。 + - 不要在注释/日志中写入任何敏感信息;如需标识调用上下文,优先使用脱敏后的业务 ID、任务 ID 或路径键。 - 示例(注释模板,按需裁剪): + - 以下为注释模板占位,不是源码字面量。 + +代码块身份:配置片段 / 概念骨架 ```tsl // : @@ -193,6 +211,8 @@ TSL 没有内置 `enum`,推荐使用 `unit` + `const` 在 `interface` 区域 示例: +代码块身份:配置片段 / 概念骨架 + ```tsl unit AlertEnumerations; interface @@ -202,6 +222,8 @@ interface end. ``` +代码块身份:配置片段 / 概念骨架 + ```tsl unit DocxEnumerations; interface diff --git a/docs/tsl/reference/catalog/base.md b/docs/tsl/reference/catalog/base.md new file mode 100644 index 00000000..8f82b7fc --- /dev/null +++ b/docs/tsl/reference/catalog/base.md @@ -0,0 +1,714 @@ +# 基础函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:字符串、数组、日期时间、类型转换与常用基础能力 +- 主题数:41 +- 函数数:574 + +## 主题目录 + +### 数字 + +- `FloatN` +- `FloatToStrEx` +- `FormatFloatExt` +- `WebZero` +- `RoundTo5` +- `SimpleRoundTo2` +- `DivValue` +- `Dataisequal` + +### 日期时间 + +- `ISO8601` + +### 日期时间 / 常用日期时间函数 + +- `Time` +- `DecodeTime` +- `DayOfWeek` +- `EncodeTime` +- `Now` +- `DecodeDate` +- `Date` +- `TryEncodeDate` +- `TryEncodeTime` +- `DecodeDateFully` +- `EncodeDate` +- `TryStrToDate` +- `StrToDateTimeDef` +- `DateTimeToInternetStr` +- `IncAMonth` +- `StrToTime` +- `CurrentYear` +- `TryStrToTime` +- `StrToDate` +- `DateTimeGMTToHttpStr` +- `DateToStr` +- `StrToTimeDef` +- `DateTimeToStr` +- `DateTimeToString` +- `Strtodatetime2` +- `FormatDateTime` +- `DateTimeGMTToCookieStr` +- `StrToDateTime` +- `IsLeapYear` +- `GMTToLocalDateTime` +- `TimeToStr` +- `StrToDateDef` +- `TryStrToDateTime` + +### 日期时间 / 简单转换函数 + +- `DateToInt` +- `IntToDate` +- `StrToDateExt` +- `ExcelIntToDate` +- `ExcelDateToInt` +- `FormatStrToDateTime2` + +### 日期时间 / 普通日期函数 + +- `IsInLeapYear` +- `IsPM` +- `IsValidDate` +- `IsValidTime` +- `IsValidDateTime` +- `IsValidDateDay` +- `IsValidDateWeek` +- `IsValidDateMonthWeek` +- `WeeksInYear` +- `WeeksInAYear` +- `DaysInYear` +- `DaysInAYear` +- `DaysInMonth` +- `DaysInAMonth` +- `Today` +- `Yesterday` +- `Tomorrow` +- `IsToday` +- `IsSameDay` + +### 日期时间 / 分解函数 + +- `DateOf` +- `TimeOf` +- `YearOf` +- `MonthOf` +- `DayOf` +- `HourOf` +- `MinuteOf` +- `SecondOf` +- `MilliSecondOf` + +### 日期时间 / 起始结束函数 + +- `StartOfTheYear` +- `EndOfTheYear` +- `StartOfAYear` +- `EndOfAYear` +- `StartOfTheMonth` +- `EndOfTheMonth` +- `StartOfAMonth` +- `EndOfAMonth` +- `StartOfTheWeek` +- `EndOfTheWeek` +- `StartOfAWeek` +- `EndOfAWeek` +- `StartOfTheDay` +- `EndOfTheDay` +- `StartOfADay` +- `EndOfADay` +- `StartOfTheHalfYear` +- `StartOfTheQuarter` +- `EndOfTheQuarter` +- `EndOfTheHalfYear` + +### 日期时间 / 关系函数 + +- `HourOfTheYear` +- `HourOfTheMonth` +- `MonthOfTheYear` +- `MilliSecondOfTheYear` +- `WeekOfTheYear` +- `WeekOfTheMonth` +- `MinuteOfTheYear` +- `SecondOfTheYear` +- `DayOfTheYear` +- `DayOfTheMonth` +- `SecondOfTheMinute` +- `HourOfTheWeek` +- `SecondOfTheMonth` +- `DayOfTheWeek` +- `MinuteOfTheDay` +- `MilliSecondOfTheSecond` +- `SecondOfTheWeek` +- `MinuteOfTheMonth` +- `MinuteOfTheHour` +- `MinuteOfTheWeek` +- `MilliSecondOfTheDay` +- `MilliSecondOfTheMonth` +- `HourOfTheDay` +- `MilliSecondOfTheHour` +- `SecondOfTheHour` +- `MilliSecondofTheMinute` +- `SecondOfTheDay` +- `MilliSecondOfTheWeek` + +### 日期时间 / 范围判定函数 + +- `WithinPastYears` +- `WithinPastMonths` +- `WithinPastWeeks` +- `WithinPastDays` +- `WithinPastHours` +- `WithinPastMinutes` +- `WithinPastSeconds` +- `WithinPastMilliSeconds` + +### 日期时间 / 范围获得函数 + +- `YearsBetween` +- `MonthsBetween` +- `WeeksBetween` +- `DaysBetween` +- `HoursBetween` +- `MinutesBetween` +- `SecondsBetween` +- `MilliSecondsBetween` + +### 日期时间 / 范围生成函数 + +- `YearSpan` +- `MonthSpan` +- `WeekSpan` +- `DaySpan` +- `HourSpan` +- `MinuteSpan` +- `SecondSpan` +- `MilliSecondSpan` + +### 日期时间 / 时间推移函数 + +- `IncYear` +- `IncHalfYear` +- `IncQuarter` +- `IncMonth` +- `IncWeek` +- `IncDay` +- `IncHour` +- `IncMinute` +- `IncSecond` +- `IncMilliSecond` + +### 日期时间 / 组合、分解日期函数 + +- `EncodeDateTime` +- `DecodeDateTime` +- `EncodeDateWeek` +- `DecodeDateWeek` +- `DecodeDateDay` +- `EncodeDateMonthWeek` +- `DecodeDateMonthWeek` +- `TryEncodeDateTime` +- `TryEncodeDateWeek` +- `TryEncodeDateDay` +- `TryEncodeDateMonthWeek` + +### 日期时间 / 日期重组函数 + +- `RecodeYear` +- `RecodeMonth` +- `RecodeDay` +- `RecodeHour` +- `RecodeMinute` +- `RecodeSecond` +- `RecodeMilliSecond` +- `RecodeDate` +- `RecodeTime` +- `RecodeDateTime` +- `TryRecodeDateTime` +- `CompareDateTime` +- `SameDateTime` +- `CompareDate` +- `SameDate` +- `CompareTime` +- `SameTime` +- `NthDayOfWeek` +- `DecodeDayOfWeekInMonth` +- `EncodeDayOfWeekInMonth` +- `TryEncodeDayOfWeekInMonth` + +### 日期时间 / 日期格式的转换 + +- `DateTimeToJulianDate` +- `JulianDateToDateTime` +- `TryJulianDateToDateTime` +- `DateTimeToModifiedJulianDate` +- `ModifiedJulianDateToDateTime` +- `TryModifiedJulianDateToDateTime` +- `DateTimeToUnix` +- `UnixToDateTime` +- `FileDateToDateTime` +- `DateTimeToFileDate` +- `ExcelRDate` + +### 日期时间 / 宽字节日期格式转换函数 + +- `DateTimeGMTToCookieStrw` +- `DateTimeGMTToHttpStrw` +- `DateTimeToInternetStrw` +- `Datetimetostrw` +- `TimetoStrw` +- `DateToStrw` + +### 字符串 / 常用字符串函数 + +- `StrCmp` +- `Chr` +- `WideChr` +- `Str2Array` +- `Concat` +- `Array2Str` +- `Format` +- `Ord` +- `SetLength` +- `CompareText` +- `Copy` +- `UpperCase` +- `LeftBStr` +- `RightBStr` +- `MidBStr` +- `GetFormatLocalCode` +- `Str` +- `RightStr` +- `CompareStr` +- `LeftStr` +- `Trim` +- `SameText` +- `SetChar` +- `AppendStr` +- `GetChar` +- `LowerCase` +- `SetFormatLocalCode` +- `Val` +- `Pos` +- `TrimRight` +- `AnsiFormat` +- `TrimLeft` +- `StrToIntDef` +- `FormatFloat` +- `StrToCurrDef` +- `Booltostr2` +- `StrToFloatDef` +- `IntToHex` +- `TryStrToInt` +- `FloatToStr` +- `TryStrToFloat` +- `FormatCurr` +- `TryStrToCurr` +- `StrToInt` +- `BoolToStr` +- `CurrToStr` +- `TryStrToBool` +- `SpaceByNumber` +- `IsValidIdent` +- `StrToBool` +- `StrToFloat` +- `StrToBoolDef` +- `IntToStr` +- `StrToCurr` +- `AnsiStr2Array` +- `TryUppercase` +- `TryLowercase` +- `SysEncodecryptStr` +- `Letters` +- `DecToInt64` +- `DecToInt64def` +- `TryDecToInt64` +- `DecToInt32` +- `DecToInt32def` +- `TryDecToInt32` +- `StrToInt64` +- `StrToInt64Def` +- `TryStrToInt64` +- `StrToInt32` +- `StrToInt32Def` +- `TryStrToInt32` +- `DecToInt` +- `DecToIntDef` +- `TryDecToInt` + +### 字符串 / 判定函数 + +- `AnsiContainsText` +- `AnsiStartsText` +- `AnsiEndsText` +- `AnsiMatchText` +- `AnsiContainsStr` +- `AnsiStartsStr` +- `AnsiEndsStr` +- `AnsiMatchStr` +- `FormatStrExt` + +### 字符串 / 替换以及处理函数 + +- `StuffString` +- `AnsiReplaceText` +- `AnsiReplaceStr` +- `ReplaceText` +- `ReplaceStr` +- `WrapText` +- `AdjustLineBreaks` +- `ReverseString` +- `SeprateStrToTotal` +- `TotalStrToSeprate` +- `DateStrToArr` +- `RdateStrToArr` + +### 字符串 / 字符串数组相关函数 + +- `AnsiIndexText` +- `AnsiIndexStr` + +### 字符串 / 重复函数 + +- `DupeString` + +### 字符串 / 多字节语言支持函数 + +- `LengthW` +- `MidStr` + +### 字符串 / 字节函数 + +- `ContainsText` +- `StartsText` +- `EndsText` +- `ContainsStr` +- `StartsStr` +- `EndsStr` +- `StuffbString` +- `ReversebString` + +### 字符串 / 发音相关函数 + +- `SoundEx` +- `SoundexInt` +- `DecodeSoundexInt` +- `SoundexWord` +- `DecodeSoundexWord` +- `SoundexSimilar` +- `SoundexCompare` +- `SoundexProc` +- `AnsiResemblesText` + +### 字符串 / 正则表达式函数 + +- `ParseRegExpr` +- `GetLikeFlag` +- `SetLikeFlag` +- `ReplaceStrByReg` +- `ReplaceTextByReg` +- `ParseRegExpr3` + +### 字符串 / 多语言支持函数 + +- `NextCharIndex` +- `AnsiToUTF8` +- `UTF8ToAnsi` +- `CharToByteIndex` +- `ByteToCharLen` +- `AnsiQuotedStr` +- `AnsiPos` +- `AnsiDequotedStr` +- `CharToByteLen` +- `CharLength` +- `ByteToCharIndex` +- `ByteType` +- `Booltostrw` +- `UnicodeESC` +- `unUnicodeESC2` +- `FloattoStrw` +- `UnicodeESC2` +- `unUnicodeESCw` +- `UnicodetoUTF8` +- `CurrtoStrw` +- `Inttostrw` +- `Booltostrw2` +- `Strw` +- `Inttohexw` +- `LCMapString` +- `MultibytetoUnicodew` +- `UTF8toUnicode` +- `Exportjsonstring` +- `unUnicodeESC2w` +- `unUnicodeESC` +- `Ifwstring` +- `Importjsonstring` +- `ExportJsonStringUTF8` +- `ExportJSONStringMBCS` + +### 字符串 / 文件名以及目录名相关处理函数 + +- `ChangeFileExt` +- `ExtractFilePath` +- `ExtractFileDir` +- `ExtractFileDrive` +- `ExtractFileName` +- `ExtractFileExt` +- `ExtractRelativePath` +- `IsPathDelimiter` +- `IsDelimiter` +- `IncludeTrailingPathDelimiter` +- `IncludeTrailingBackslash` +- `ExcludeTrailingPathDelimiter` +- `ExcludeTrailingBackslash` +- `LastDelimiter` +- `AnsiCompareFileName` +- `SameFileName` +- `AnsiLowerCaseFileName` +- `AnsiUpperCaseFileName` + +### 字符串 / 其它 + +- `GetPYStringList` +- `HztoPY` +- `DataUnitConversion` + +### 数组 / 基本 + +- `FieldCount` +- `FieldExist` +- `FieldNames` +- `FieldName` +- `IsTable` +- `MagicSetArray` +- `NoRecordTable` +- `MagicGetArray` +- `RecordExist` +- `RecordExist2` +- `RecordExist3` +- `FieldNamesOfStrSubscript` +- `StrSubscriptTableToNormal` +- `FieldCountOfStrSubscript` +- `argmax` +- `Argmin` +- `PasswordGen` + +### 数组 / 数组下标以及长度相关函数 + +- `GetStrIndexNum` +- `GetStrIndexs` +- `GetIntIndexs` +- `GetAllIndexs` +- `DeleteIndex` +- `DeleteField` +- `Length` + +### 数组 / 排序函数 + +- `RankIt` +- `RankIt2` +- `RPSIt` +- `SortTableByFieldExt` +- `RankValue` +- `SortArray` +- `SortTableByField` +- `argsort` + +### 数组 / 增删改查 + +- `AppendArray` +- `SeekPosInArray` +- `StockAmount` +- `DeleteNILValueByField` +- `FilterIn` +- `FilterNotIn` +- `IN1` +- `searchsorted` +- `argconfirst` +- `DeleteColumnByField` +- `Inserttablebyrno` +- `GetValuesByFieldValue` +- `Arrayextend` +- `Arrayinsert` +- `Frameinsert` + +### 数组 / 数组操作 + +- `OutPutTableToCanBeUnderstood` +- `SeperateTable` +- `Unitary` +- `Reverse` +- `DescartesJoin` +- `TableVectorizeArray` +- `DataProcess_MF` +- `AbnormalData` +- `QKsplit_Trailing` +- `QKsplit_Resampling` +- `WebFormatToRung` +- `RPSValue` +- `ZValue` +- `QKsplit_ToDate` +- `GroupByFieldValue` +- `FilterOneDimEx2` +- `GroupRankIt` +- `ElementWhere` +- `Histogram` +- `FrameGetSubByReg` +- `Factorize` +- `GroupPercentrankIt` +- `SparseMatFill` +- `ArrayAddGap` +- `dumies_decode` +- `GroupTransformByFunc` +- `Framedrop_duplicates` +- `Field_ReSortCols` +- `Framedrop_na` +- `Framemerge` +- `Frameqcut` +- `Frameupdate` +- `GroupZscoreIt` +- `get_dummies` +- `get_dummies2` +- `framePivot_table` +- `framecut` +- `frameMelt` +- `GroupDemeanIt` +- `ArrDropDuplicate` + +### 数组 / 数组取值 + +- `ColumnValue` +- `GetSubTableByField` +- `GetTopN` +- `FilterTableEx` +- `ColumnValue2` +- `GetBottomN` +- `FilterOneDimEx` +- `GetDistinctValue` +- `GetMiddleN` +- `FilterTable` +- `GetSubField` +- `GetSubTable` +- `Arraygetdefault` +- `Arraysetdefault` +- `Arraysetdefault2` +- `Randomchoice` + +### 数组 / 集合运算 + +- `MergeArray` +- `FilterIntersectionPart` +- `FilterIntersectionPart2` +- `DistinctStr` +- `IntersectionPart` +- `QuickIntersectionPart` +- `Frameconcat` + +### 数组 / 统计函数 + +- `GeoMeanByColumn` +- `SumValueByColumn` +- `AverageValueByColumn` +- `PercentValueByField` +- `MedianByColumn` +- `VarByColumn` +- `SumValueByColumn2` +- `SkewByColumn` +- `AveDevByColumn` +- `SumValueByRow2` +- `MaxValueByColumn` +- `DevsqByColumn` +- `KurtByColumn` +- `SumValueByRow` +- `HarMeanByColumn` +- `StatByColumn` +- `AverageByColumn` +- `StdevByColumn` +- `MinValueByColumn` +- `Describe` +- `Framecorrel` +- `Framecov` +- `Framehhi` +- `Framelag_zf` +- `Framepct_change` +- `Framevaluecounts` +- `Simpledescribe` + +### 数组 / 重构函数 + +- `NormalTabletoStrSubscript` +- `RenameField` +- `Field_AddSuffix` +- `RenameFieldByFormat` +- `Field_AddPrefix` +- `ReIndex` +- `ReIndexCopy` +- `Reshape` +- `Frame_addprefix` +- `Frame_addsuffix` + +### 数组 / 稀疏矩阵 + +- `Sparse1` +- `Sparse2` +- `Speye` +- `Sprand1` +- `Sprand2` +- `Sprandn1` +- `Sprandn2` +- `Sprandsym1` +- `Sprandsym2` +- `Sparsefull` +- `Spones` +- `Spnnz` +- `Spnonzeros` +- `Ifsparse` +- `Spdiags1` +- `Spdiags2` +- `Spdiags3` +- `Spdiags4` + +### 数组 / 数据比较 + +- `TwoRDateCompare_M1` +- `CompareDataOfDifferentDataProvider` + +### 数组 / 表格显示 + +- `Pivot` +- `Pivot_table` +- `Show3DTable` +- `Show2DTable` +- `ShowTableByField` +- `ShowTableByUnit` +- `ShowTableByInverse` +- `QuickRecordExist` +- `RotateTable` +- `NonIntersectionPart` +- `FooterValue` +- `FooterAverage` +- `FooterSum` +- `SetRowDefaultValue` +- `InverseTable` +- `GetSubTableByKey` +- `TableSelect` +- `TableType` +- `GetSubTableFreeParam` +- `ExpandTable` + +### 数组 / 数组下标 + +- `frameIndex_filter` +- `frameIndex_getilocDZ` diff --git a/docs/tsl/reference/catalog/client.md b/docs/tsl/reference/catalog/client.md new file mode 100644 index 00000000..5cbfab16 --- /dev/null +++ b/docs/tsl/reference/catalog/client.md @@ -0,0 +1,60 @@ +# 客户端函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:客户端交互、界面控制与前端协作能力 +- 主题数:8 +- 函数数:19 + +## 主题目录 + +### 结果处理 / CallBack + +- `DelPrecodeCallBack` +- `IncPrecodeCallBack` + +### 结果处理 / 层次表格的展开 + +- `ExtractData` +- `ExtractDataEx` +- `ExtractDataEx2` +- `ExtractDataLocalRun2` + +### 结果处理 / 简单统计 + +- `SimpleStat` + +### 结果处理 / 品种管理 + +- `GetTypeOfStock` + +### 错误处理 + +- `RaiseError` +- `ASSERT` + +### 客户端行为控制函数 + +- `TSExpert_ClientConfig` + +### 客户端行为控制函数 / 客户端行为控制函数简介 + +- `ChartColor` +- `ChartColorArray` +- `DisabledFuncTypeList` +- `DisabledSystemFuncList` +- `DisabledSysFuncList` +- `FuncTypeList` +- `AutoRun` + +### 直接函数 + +- `SendRunningData` diff --git a/docs/tsl/reference/catalog/compression.md b/docs/tsl/reference/catalog/compression.md new file mode 100644 index 00000000..87370bdf --- /dev/null +++ b/docs/tsl/reference/catalog/compression.md @@ -0,0 +1,25 @@ +# 压缩和解压函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:压缩、解压与归档能力 +- 主题数: +- 函数数:5 + +## 主题目录 + +### 直接函数 + +- `ZipCompress` +- `ZipExtract` +- `RarExtract` +- `unicompress` +- `uniuncompress` diff --git a/docs/tsl/reference/catalog/digest_encoding.md b/docs/tsl/reference/catalog/digest_encoding.md new file mode 100644 index 00000000..f8337dc0 --- /dev/null +++ b/docs/tsl/reference/catalog/digest_encoding.md @@ -0,0 +1,33 @@ +# 信息摘要及编码 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:哈希、摘要、编码与转换能力 +- 主题数:3 +- 函数数:7 + +## 主题目录 + +### 信息摘要函数 + +- `GetMsgDigest` + +### BASE64编码 + +- `StrToBase64` +- `Base64ToStr` + +### 进制编码函数 + +- `EncodeRadixstr` +- `DecodeRadixstr` +- `Decoderadixwstr` +- `Encoderadixwstr` diff --git a/docs/tsl/reference/catalog/graphics.md b/docs/tsl/reference/catalog/graphics.md new file mode 100644 index 00000000..9526f7b2 --- /dev/null +++ b/docs/tsl/reference/catalog/graphics.md @@ -0,0 +1,53 @@ +# 图形函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:图表、绘图与可视化相关函数 +- 主题数:3 +- 函数数:27 + +## 主题目录 + +### 作图函数 + +- `Graph` +- `GraphGroup` +- `MergeGraph` +- `EncodeGraphGroup` +- `DecodeGraphGroup` +- `DecodeGraph` +- `EncodeGraph` +- `FastLine_Web` +- `GetColorByIndex` + +### 图形字段函数 + +- `gfColor` +- `gfFill` +- `gfFlag` +- `gfZero` +- `gfMaxValue` +- `gfMinValue` +- `gfLTP` +- `gfTitleCaption` +- `gfLeftTitleCaption` +- `gfCoordinate` + +### 图形填充设置函数 + +- `flSolid` +- `flClear` +- `flHorizontal` +- `flVertical` +- `flFDiagonal` +- `flBDiagonal` +- `flCross` +- `flDiagCross` diff --git a/docs/tsl/reference/catalog/index.md b/docs/tsl/reference/catalog/index.md new file mode 100644 index 00000000..d9682c58 --- /dev/null +++ b/docs/tsl/reference/catalog/index.md @@ -0,0 +1,30 @@ +# Function Catalog + +这里是 canonical 函数目录。它只回答“函数在哪个模块里”,不承担基础语法教学。 + +## 使用顺序 + +1. 不知道函数在哪个模块,先看下面的模块目录。 +2. 进入模块页后,在页内搜索具体函数名。 +3. 如果问题是语法怎么写,回到 [../../syntax/index.md](../../syntax/index.md)。 +4. 如果问题是金融场景如何组织,回到 [../../finance/index.md](../../finance/index.md)。 + +## 模块目录 + +| 模块 | 分类页 | 范围 | 函数数 | +| --- | --- | --- | --- | +| 基础函数 | [base.md](base.md) | 字符串、数组、日期时间、类型转换与常用基础能力 | 574 | +| 数学函数 | [math.md](math.md) | 数值计算、统计分析、矩阵处理与数学算法 | 518 | +| 系统相关函数 | [system.md](system.md) | 数据类型、表达式调用、性能与运行时能力 | 57 | +| 资源访问函数 | [resource.md](resource.md) | 文件、数据库、网络与外部资源访问 | 136 | +| 平台函数 | [platform.md](platform.md) | 平台相关功能与系统接口 | 19 | +| 客户端函数 | [client.md](client.md) | 客户端交互、界面控制与前端协作能力 | 19 | +| 图形函数 | [graphics.md](graphics.md) | 图表、绘图与可视化相关函数 | 27 | +| 压缩和解压函数 | [compression.md](compression.md) | 压缩、解压与归档能力 | 5 | +| 信息摘要及编码 | [digest_encoding.md](digest_encoding.md) | 哈希、摘要、编码与转换能力 | 7 | +| 第三方交互函数 | [third_party.md](third_party.md) | 第三方库与外部程序交互能力 | 8 | + +## 说明 + +- 这套目录页由仓库内的函数语料自动整理生成。 +- 当前目标是先提供稳定检索层,再逐步补全更细的 canonical 说明。 diff --git a/docs/tsl/reference/catalog/math.md b/docs/tsl/reference/catalog/math.md new file mode 100644 index 00000000..468738c7 --- /dev/null +++ b/docs/tsl/reference/catalog/math.md @@ -0,0 +1,655 @@ +# 数学函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:数值计算、统计分析、矩阵处理与数学算法 +- 主题数:40 +- 函数数:518 + +## 主题目录 + +### 数值计算 / 数值微积分 + +- `ig_Romberg` +- `integral` +- `ig_Trapezoid_1` +- `ig_Trapezoid_2` +- `ig_Simpson_1` +- `ig_Gauss` +- `ig_Chebyshev` +- `ig_Simpson_2` +- `sf_SinX` +- `sf_CosX` +- `sf_eX` +- `sf_EllipseX_1` +- `sf_EllipseX_2` +- `Conv` +- `Hessian` + +### 数值计算 / 线性方程组的求解 + +- `se_Gauss` +- `se_Gauss_Jordan` +- `se_Ldl` +- `se_Cholesky` +- `se_Gauss_Seidel` + +### 数值计算 / 插值 + +- `interp` +- `interp_unit` +- `ip_Lagrangian_A` +- `ip_Lagrangian_B` +- `ip_Parabola_A` +- `ip_Parabola_B` +- `ip_Hermite_A` +- `ip_Hermite_B` +- `ip_Aitken_A` +- `ip_Aitken_B` +- `ip_Spline_A` +- `ip_Spline_B` +- `ip_Spline_C` +- `ip_SLQ` +- `ip_SLG` + +### 数值计算 / 矩阵运算及分解 + +- `mt_Transposition` +- `mt_Multiplication` +- `mt_Addition` +- `mt_iv_Gauss_Jordan` +- `mt_iv_Ldl` +- `mt_Subtraction` +- `Mt_decompose_lu` +- `mt_decompose_qr` +- `mt_decompose_chol` +- `chol` +- `mt_va_Gauss_Jordan` +- `mt_decompose_svd` +- `mt_decompose_ldl` +- `mt_decompose_eig` +- `Standarize_II` +- `ReIndex2` +- `Det` +- `isSymmetry` +- `Orth` +- `roots` +- `Eigen` +- `pinv` +- `norm2` +- `Cond` +- `diag` +- `isDefinite` + +### 数值计算 / 数组扩展 + +- `Any` +- `ALL` + +### 数值计算 / 其他 + +- `perms` +- `nchoosek` +- `MaxDrawDown` +- `MinRecoveryTime` +- `Betainc` +- `PercentileOfScore` +- `GenerateCombinations` +- `Percentage` + +### 常用数学函数 + +- `Pi` +- `Odd` +- `Abs` +- `Sqr` +- `Sqrt` +- `DivMod` +- `Frexp` +- `Ldexp` +- `Poly` + +### 三角函数 + +- `Sin` +- `Cos` +- `SinCos` +- `Tan` +- `Cot` +- `CoTan` +- `Sec` +- `Csc` +- `Secant` +- `Cosecant` +- `ArcSin` +- `ArcCos` +- `ArcTan` +- `ArcTan2` +- `ArcCot` +- `ArcSec` +- `ArcCsc` +- `Hypot` + +### 角度量转换 + +- `RadToDeg` +- `RadToGrad` +- `RadToCycle` +- `DegToRad` +- `DegToGrad` +- `DegToCycle` +- `GradToRad` +- `GradToDeg` +- `GradToCycle` +- `CycleToRad` +- `CycleToDeg` +- `CycleToGrad` + +### 双曲线函数 + +- `Sinh` +- `Cosh` +- `Tanh` +- `CotH` +- `SecH` +- `CscH` +- `ArcCosh` +- `ArcSinh` +- `ArcTanh` +- `ArcCotH` +- `ArcSecH` +- `ArcCscH` + +### 指数对数函数 + +- `Ln` +- `LnXP1` +- `Log10` +- `Log2` +- `LogN` +- `Exp` +- `IntPower` +- `Power` + +### 精度设置及取整运算 + +- `Int` +- `Ceil` +- `Ceil32` +- `Ceil64` +- `Floor` +- `Floor32` +- `Floor64` +- `Trunc` +- `Trunc32` +- `Trunc64` +- `Frac` +- `Round` +- `Round32` +- `Round64` +- `SimpleRound` +- `SimpleRound32` +- `SimpleRound64` +- `RoundTo` +- `SimpleRoundTo` + +### 比较判断函数 + +- `IsNan` +- `IsInfinite` +- `Sign` +- `IsZero` +- `Min` +- `Max` +- `CompareValue` +- `SameValue` +- `RandomRange` +- `InRange` +- `EnsureRange` + +### 一般统计量 + +- `MinIntValue` +- `SumOfSquares` +- `StdDev` +- `Mean` +- `Sum` +- `MaxValue` +- `MinValue` +- `Norm` +- `SumsAndSquares` +- `MaxIntValue` +- `SumInt` +- `Harmean` +- `Variance` +- `MeanAndStdDev` +- `AveDev` +- `Skewness` +- `TotalVariance` +- `Product` +- `PopnStdDev` +- `kurtosis2` +- `Median` +- `skewness2` +- `Kurtosis` +- `Mode` +- `RandG` +- `Geomean` +- `PopnVariance` +- `MomentSkewKurtosis` +- `DevSq` +- `randomfrom` + +### 次序统计量 + +- `Large` +- `Small` +- `Percentile` +- `Percentrank` +- `Quartile` +- `Rank` +- `Trimmean` +- `Frequency` + +### 统计函数 + +- `Cov` +- `Correl` +- `Slope` +- `Intercept` +- `Rsq` +- `Steyx` +- `Slopeandintercept` +- `VariationCoefficient` +- `Skew` +- `SelfStddev` +- `RegressionChannel` +- `Kurt` +- `MeanAndPopnStdDevWithRate` +- `BetaAndAlpha` +- `correlpaired` +- `correlpaired_side` + +### 统计函数 / 扩充统计 + +- `Expanding_Unit` + +### 统计函数 / 含NAN统计 + +- `NanMean` +- `NanSum` +- `NanStd` +- `NanVariance` +- `NanPopnStd` +- `NanPopnVariance` +- `NanRankArr` +- `NanPercentRankArr` + +### 统计分布 + +- `Gammaln` +- `Hist` +- `sf_Error` +- `erfc` +- `sf_Gamma` +- `erf` +- `erfcinv` +- `sf_Beta` +- `sf_IntegerBessel_1` +- `sf_IncompleteGamma` +- `Gamma` +- `erfinv` +- `Randnorm` +- `sf_F` +- `sf_geopdf` +- `sf_RealBessel_1` +- `sf_unidcdf` +- `sf_normpdf` +- `sf_geoinv` +- `sf_unidpdf` +- `sf_IncompleteBeta` +- `sf_normalinv2` +- `sf_norminv` +- `Randunid` +- `sf_Normal` +- `sf_unidinv` +- `sf_X2` +- `sf_IntegerBessel_2` +- `sf_normcdf` +- `sf_t` +- `sf_geocdf` +- `Randgeo` +- `sf_normalinv` +- `Normfit` +- `sf_RealBessel_2` +- `sf_hygeinv` +- `poissfit` +- `sf_binocdf` +- `Randhyge` +- `sf_poissinv` +- `sf_poisscdf` +- `sf_nbininv` +- `binofit` +- `sf_hygepdf` +- `sf_unifcdf` +- `sf_exppdf` +- `sf_binoinv` +- `uniffit` +- `sf_nbinpdf` +- `Randnbin` +- `Randpoiss` +- `sf_hygecdf` +- `sf_poisspdf` +- `Randbino` +- `Randunif` +- `sf_unifinv` +- `sf_binopdf` +- `sf_nbincdf` +- `sf_unifpdf` +- `sf_tcdf` +- `sf_fpdf` +- `sf_tinv` +- `expfit` +- `Randgam` +- `sf_ch2inv` +- `sf_ch2cdf` +- `sf_finv1` +- `Randt` +- `sf_expcdf` +- `sf_finv` +- `sf_gamcdf` +- `sf_tpdf` +- `sf_x2inv` +- `sf_gampdf` +- `sf_gammainv` +- `sf_fcdf` +- `sf_ch2pdf` +- `Randf` +- `Randexp` +- `Randch2` +- `sf_gaminv` +- `sf_expinv` +- `sf_betapdf` +- `sf_tinv1` +- `RandCauchy` +- `sf_Laplacecdf` +- `Randbeta` +- `sf_Cauchypdf` +- `sf_logninv` +- `sf_Laplaceinv` +- `sf_betacdf` +- `sf_raylinv` +- `sf_wblcdf` +- `sf_lognpdf` +- `sf_Cauchycdf` +- `Randlogn` +- `Randrayl` +- `sf_Laplacepdf` +- `sf_raylpdf` +- `sf_wblinv` +- `sf_logncdf` +- `sf_Cauchyinv` +- `sf_raylcdf` +- `Randwbl` +- `sf_betainv` +- `RandLaplace` +- `sf_wblpdf` +- `sf_betainv1` +- `sf_mvtcdf` +- `Mvtcdfqmc` +- `sf_mvncdf` +- `sf_copulacdf` +- `sf_copulafit` +- `RandCopula` +- `sf_exp` +- `Norminv` + +### 统计推断 + +- `Estimate_SNU` +- `Estimate_TNU` +- `Estimate_TND` +- `Estimate_SP` +- `Estimate_TP` +- `Hypoth_TailRes` +- `NormPlot` +- `Hypoth_Kstest` +- `Hypoth_lillietest` +- `Hypoth_IndepTest` +- `Hypoth_KruskalWallis` +- `Hypoth_SNUTest` +- `Hypoth_TNUTest` +- `Hypoth_SNDTest` +- `Hypoth_TNDTest` +- `Hypoth_LSUTest` +- `Anova_Single` +- `Anova_Twice` +- `Anova_Bartlett` +- `Anova_Levene` + +### 统计推断 / 假设检验 + +- `Hypoth_SignTest` +- `Hypoth_WilcoxonTest` +- `Hypoth_McNemarTest` + +### 统计推断 / 配对检验 + +- `Hypoth_PNUTest` + +### 多元统计分析 + +- `Corr` +- `CorrelationMatrix` +- `Covariance` +- `Corrcoef` +- `Corr_partial` +- `Distance` +- `Cluster_Kmeans` +- `Cluster_System` +- `Cluster_ward` +- `Discrim` +- `princomp` +- `Factor` +- `corr_canonical` +- `corr_Spearman` +- `Cov2CorrMatrix` +- `CorrMatrixAdjust` +- `corr_Kendall` +- `HISTC` + +### 多元统计分析 / 相对重要性 + +- `Regress_domin_formula` +- `Regress_domin_marginal` + +### 回归 / 回归检验 + +- `Regress_Ridge` +- `Regress_AdjustedR2` +- `Regress_Logistic` +- `Regression` +- `Regress_DWTest` +- `Regress_Stepwise` +- `Regress_Constraint` +- `Regress_White` +- `Regress_MLS` +- `Regress_CMLS` +- `Regress_JBTest` +- `Regress_pri` +- `Regress_FTest` +- `Regression_WLS` +- `Regress_Binary` +- `Regress_TTest` +- `Regress_NLM` +- `Regress_WLS` +- `Regress_AicAndSbic` +- `Regress_RSquare` +- `Regress_QRlsq` +- `boxcox` +- `Regress_HettestSpearman` +- `Regress_VIF` +- `Regress_TTest_RWLS` +- `Regress_TTest_White` +- `Regress_TTest_NW` +- `Regression_OLS_White` +- `Regression_OLS_NW` +- `NW_Adjustment_Simplification` +- `Robustfit_M` +- `Regress_GRStest` + +### 回归 / 回归公用函数 + +- `LeastSquares_CurveFitting` + +### 灰色系统 + +- `GM_Initial` +- `GM_Corr` +- `GM_AGO` +- `GM_Icorr` +- `GM_Scorr` + +### 主成分分析 + +- `PrincaipalComponentAnalysis` + +### 主成分分析 / 中间函数 + +- `Mbbub` +- `ComponentScoreMatrix` +- `FactorScoreMatrix` +- `ComponentMatrix` +- `RotatedComponentMatrix` +- `Eigen_Jacobi` +- `GetEigenValue` +- `FScoreResult` + +### 时间序列分析 + +- `Time_Diff` +- `Time_AutoCov` +- `Time_ACF` +- `Time_PACF` +- `Time_RandomTest` +- `Time_DanielTest` +- `AR` +- `ARMA` +- `Time_ARCH` +- `Time_GARCH` +- `Times_ADFTest` +- `Times_Cointergration_test` +- `Times_ECM` +- `Times_Granger` +- `Time_ARp` +- `Time_MAq` +- `Time_ARMA` +- `Time_GreenFun` +- `Time_InvFun` +- `Time_Analyse` +- `Time_ChoseP` +- `Times_Cointergration` +- `GM_Estimate` +- `Time_ARCHTest` +- `GarchFit` +- `Times_johansen` +- `Times_GrangerCausality` + +### 时间序列分析 / 因果推断 + +- `Time_VolatilitySpillover` + +### 优化 + +- `NonLP_Hooke_Jeeves` +- `Prog_L` +- `NonLP_minPS` +- `NonLP_Fibonacci` +- `NonLP_Range` +- `Fmin` +- `NonLP_BSearch` +- `Prog_M` +- `NonLP_minFactor` +- `NonLP_GP` +- `NonLP_Fminsearch` +- `NonLP_Fmincon` +- `NonLP_minSUMT` +- `Prog_Q` +- `Prog_N` +- `NonLP_Nelder` +- `NonLP_Fminbnd` +- `NonLP_Golden` +- `TSOptimizer` +- `Quadprog` +- `LinearProgramming` +- `NonLP_Rosenbrock` +- `QuadLagR` +- `OZProg` +- `QuadTrackRoute` +- `IntLinProg` + +### 优化 / 有约束优化算法 + +- `SUMT_Method` + +### 优化 / 无约束优化算法 + +- `Hooke_Jeeves_Method` + +### 优化 / 测试 + +- `H_J_Method_Pgm` +- `Sumt_Method_CallBack` + +### 小波分析 + +- `Wavedec` +- `wrcoef` +- `wavelet` + +### 财务函数 + +- `DoubleDecliningBalance` +- `FutureValue` +- `InterestPayment` +- `InterestRate` +- `InternalRateOfReturn` +- `NumberOfPeriods` +- `NetPresentValue` +- `Payment` +- `PeriodPayment` +- `PresentValue` +- `SLNDepreciation` +- `SYDDepreciation` + +### 增长率与比率 + +- `AccumulativeYTMtoYTM` +- `YTMToAccumulativeYTM` +- `RatioValue` +- `OutPutValueByUnit` +- `OutPutLnGrowRatio` +- `OutPutGrowValue` +- `OutPutGrowValue2` +- `OutPutGrowRatio` +- `OutPutGrowRatio2` +- `MultyValue` +- `OutPutGrowValue3` +- `OutPutGrowRatio3` +- `RatioValue_Math` + +### 概率分布 / 线性变换 + +- `Norm_LinearTransform` + +### 信号处理 + +- `filter_hp` diff --git a/docs/tsl/reference/catalog/platform.md b/docs/tsl/reference/catalog/platform.md new file mode 100644 index 00000000..be3e8566 --- /dev/null +++ b/docs/tsl/reference/catalog/platform.md @@ -0,0 +1,48 @@ +# 平台函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:平台相关功能与系统接口 +- 主题数:4 +- 函数数:19 + +## 主题目录 + +### 自有数据维护函数 + +- `LoadTableEx` +- `LoadTable` +- `SaveTable` +- `TestTable` +- `SaveBk` +- `DeleteBk` +- `ListTable` +- `DeleteTable` + +### 自有数据维护函数 / UserDB + +- `UserDataUpLoad` +- `HexToString` +- `TransFileName` + +### 平台执行信息 + +- `tsAppServer` +- `TsAppServerName` +- `SendToClient` +- `TS_ModuleInfo` + +### 用户和函数相关函数 + +- `User` +- `FunctionType` +- `FunctionName` +- `FunctionVer` diff --git a/docs/tsl/reference/catalog/resource.md b/docs/tsl/reference/catalog/resource.md new file mode 100644 index 00000000..3f5d5338 --- /dev/null +++ b/docs/tsl/reference/catalog/resource.md @@ -0,0 +1,183 @@ +# 资源访问函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:文件、数据库、网络与外部资源访问 +- 主题数:10 +- 函数数:136 + +## 主题目录 + +### 数据库访问函数 + +- `ExecSQL` + +### 文件访问函数 + +- `FileList` +- `FileAge` +- `RemoveDir` +- `FileSize` +- `SetFileAttr` +- `FileDelete` +- `Sysdbfwrite` +- `FileTime` +- `SetFileAge` +- `WriteFile` +- `WriteToLog` +- `FileExists` +- `FileCopy` +- `SetFileTime` +- `ReadExcelSheets` +- `CreateDir` +- `FileAttr` +- `ReadFile` +- `Sysdbfread` +- `FileRename` +- `ImportFile` +- `ExportFile` +- `ExportFile2` +- `ImportFile2` +- `FileMode` +- `SetFileMode` +- `FileAttrToStr` +- `FileModeToStr` +- `StrToFileAttr` +- `StrToFileMode` +- `Filemove` + +### 文件访问函数 / 导入导出类型函数 + +- `ftCSV` +- `ftXLS` +- `ftXls2` +- `ftXls3` +- `ftStream` +- `ftString` +- `ftXML` +- `ftdbf` + +### 文件访问函数 / 文件读写类型函数 + +- `rwByte` +- `rwInt` +- `rwReal` +- `rwStr` +- `rwObj` +- `rwRaw` +- `rwBinary` + +### 网络访问以及相关函数 + +- `GetHttp` +- `PostHttp` +- `GetURL` +- `CreateHttpSession` +- `SetHttpMode` +- `SetHttpCallBack` +- `GetHttpContent` +- `GetHttpResponseHeader` +- `SysSendMail` + +### INI文件处理函数 + +- `IniReadBool` +- `IniReadDate` +- `IniReadDateTime` +- `IniReadFloat` +- `IniReadInteger` +- `IniReadTime` +- `IniReadString` +- `IniReadBinaryStream` +- `IniReadSection` +- `IniReadSections` +- `IniReadSectionValues` +- `IniSectionExists` +- `IniValueExists` +- `IniWriteBool` +- `IniWriteDate` +- `IniWriteDateTime` +- `IniWriteFloat` +- `IniWriteInteger` +- `IniWriteTime` +- `IniWriteString` +- `IniWriteBinaryStream` +- `IniDeleteKey` +- `IniEraseSection` + +### INI文件处理函数 / 宽字节处理函数 + +- `IniReadSectionsw` + +### 进程相关函数 + +- `SysPutenv` +- `SysExec` +- `SysParamStr` +- `SysErrorMessage` +- `Sysgetenv` +- `SysWaitForMultipleObjects` +- `SysTerminate` +- `SysCreateMutex` +- `SysCloseHandle` +- `SysReleaseMutex` +- `SysProcessID` +- `SysParamcount` +- `SysThreadID` +- `Sleep` +- `SysWaitForSingleObject` +- `SysGetenvs` +- `SysexecReadpipe` +- `SysexecGetenvs` +- `SysexecDeletepipe` +- `SysexecSetenvs` +- `SysexecNewpipe` +- `SysExecWritepipe` +- `dbglocalrunning` +- `dbglocalcancel` +- `SysThreadSelf` +- `syslinuxkrnlclosemutex` +- `SysSetThreadPriority` +- `SysGetThreadPriority` +- `SysSetProcessPriority` +- `SysGetProcessPriority` +- `SysGetProcessList` +- `SysGetProcessListw` +- `SysGetProcessNamePath` +- `SysGetProcessNamePathw` +- `SysGetProcessCmdLine` +- `SysGetProcessCmdLinew` +- `SysSetThreadName` +- `SysGetThreadName` +- `SysGetThreads` +- `SysPPid` +- `SysGetSubProcesses` +- `SysKill` +- `SysPidOfTid` +- `SysPidOfHandle` +- `SysHandleOfPid` + +### 进程相关函数 / 获取COM进程 + +- `SysGetPidOfCom` +- `SysGetWndOfCaption` +- `SysGetPidtidOfWnd` + +### 本地资源相关函数 + +- `SysExecName` +- `PluginPath` +- `FileInfo` +- `Getlogicdrive` +- `GetDeviceFree` +- `Getdeviceinfo` +- `Createlink` +- `Realpath` diff --git a/docs/tsl/reference/catalog/system.md b/docs/tsl/reference/catalog/system.md new file mode 100644 index 00000000..a56b0f79 --- /dev/null +++ b/docs/tsl/reference/catalog/system.md @@ -0,0 +1,101 @@ +# 系统相关函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:数据类型、表达式调用、性能与运行时能力 +- 主题数:9 +- 函数数:57 + +## 主题目录 + +### 数据类型函数 + +- `DataType` +- `ifInt` +- `ifInt64` +- `ifReal` +- `ifNumber` +- `ifString` +- `ifArray` +- `ifNil` +- `ifExp` +- `ifGraph` +- `ifGraphGroup` +- `ifBinary` +- `ifMatrix` +- `ifObj` +- `GetOleObject` +- `CreateComObject` +- `CreateMatrix` +- `MatrixToArray` +- `GetMatrixFields` +- `CreateBinary` +- `ConvertDataToBuf` +- `ConvertBufToData` + +### 数据类型函数 / None类型 + +- `ifNone` +- `GetNone` + +### 数据类型转换函数 + +- `Integer` +- `Int64` +- `Real` +- `String` +- `WideString` +- `Binary` +- `SetPrecision` +- `ToSTM` +- `ToSTN` +- `ToXML` +- `XML` +- `ExportCsv` +- `ImportCsv` + +### 复制函数 + +- `dupValue` + +### 随机函数 + +- `randomize` +- `random` +- `RandomFrom` + +### 条件选择函数 + +- `IfThen` +- `IfThen3` + +### 表达式相关函数 + +- `Eval` +- `Call` +- `CallInArray` +- `Invoke` +- `Invokeinarray` +- `SafeEval` +- `DoubleVariableExecute` +- `MultipleExecute` +- `SingleVariableExecute` +- `SafeSetSysParam` + +### 性能优化相关函数 + +- `SetProfiler` +- `GetProfilerInfo` + +### 函数库路径 + +- `sysgettsllibpath` +- `syssettsllibpath` diff --git a/docs/tsl/reference/catalog/third_party.md b/docs/tsl/reference/catalog/third_party.md new file mode 100644 index 00000000..90db5b35 --- /dev/null +++ b/docs/tsl/reference/catalog/third_party.md @@ -0,0 +1,34 @@ +# 第三方交互函数 + +这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。 + +## 使用方式 + +- 返回总目录:[catalog/index.md](index.md) +- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md) +- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md) + +## 模块范围 + +- 说明:第三方库与外部程序交互能力 +- 主题数:3 +- 函数数:8 + +## 主题目录 + +### Python支持函数 + +- `PyRun` +- `PyCall` +- `PyError` + +### R支持函数 + +- `RRelease` + +### Html + +- `TextToHtml` +- `TextToURL` +- `HtmlToText` +- `URLToText` diff --git a/docs/tsl/reference/index.md b/docs/tsl/reference/index.md new file mode 100644 index 00000000..ee7afbab --- /dev/null +++ b/docs/tsl/reference/index.md @@ -0,0 +1,34 @@ +# Reference Index + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[catalog/index.md](catalog/index.md)、[../syntax/index.md](../syntax/index.md)、[../finance/index.md](../finance/index.md) + +这里是函数查阅层,不是默认通读入口。现在这一页本身就是函数总入口,不再要求先跳到额外的中转页。 + +## 先看这 5 条 + +- 这里用于函数查找,不用于建立基础语法模型。 +- 不要把 reference 当成默认通读入口;如果任务就是查函数,可以直接从这里开始。 +- 函数库规模很大,应先走索引,再做定向检索。 +- 如果目录和定向检索都找不到函数,不要默认它是 TSL 内建函数;先回语法层、业务层、模块页或项目文档确认来源。 +- 如果你还在问“语言怎么写”,先回 [../syntax/index.md](../syntax/index.md)。 + +## 检索策略 + +1. 先看 [catalog/index.md](catalog/index.md) 的模块目录,确定大类。 +2. 进入对应模块页,在页内搜索具体函数名。 +3. 仍然不确定时,再用 `rg` 对 `docs/tsl/reference/catalog/` 做定向搜索。 +4. 如果目录和定向检索都找不到函数,不要发明函数名,也不要默认它是 TSL 内建函数;回 [../syntax/index.md](../syntax/index.md)、[../finance/index.md](../finance/index.md)、[../modules/index.md](../modules/index.md) 或项目文档确认来源。 + +## 按任务跳转 + +| 当前任务 | 先读哪里 | +| --- | --- | +| 查函数库入口 | [catalog/index.md](catalog/index.md) | +| 直接按模块查函数 | [catalog/index.md](catalog/index.md) | +| 回到语法层 | [../syntax/index.md](../syntax/index.md) | +| 回到金融层 | [../finance/index.md](../finance/index.md) | +| 回到模块层 | [../modules/index.md](../modules/index.md) | diff --git a/docs/tsl/syntax/01_introduction.md b/docs/tsl/syntax/01_introduction.md new file mode 100644 index 00000000..a9fcd529 --- /dev/null +++ b/docs/tsl/syntax/01_introduction.md @@ -0,0 +1,98 @@ +# Introduction + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[02_quickstart.md](02_quickstart.md)、[03_core_model.md](03_core_model.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 1 篇,共 32 篇。上一篇:手册入口 [index.md](index.md)。下一篇:[02_quickstart.md](02_quickstart.md)。 + +这一篇只做一件事:让新 session 在看到 TSL 时,先用正确的读法建立心智模型。 + +## 这一篇解决什么问题 + +回答“第一次读 TSL 时,应该先把它当成什么来理解,以及最容易和别的语言混淆的差异是什么”。 + +涉及赋值、命名参数、类外形、`unit` 骨架、数组 / 字符串下标这类高频硬规则时,统一以 [02_quickstart.md](02_quickstart.md) 的“语言核心事实速查”为准;这一页只负责建立第一印象。 + +## 先用什么方式读 TSL + +- 可以先按 Pascal 风格语言去读它:常见外形是 `function ... begin ... end;`、`unit ... interface ... implementation ... end.`、`type Name = class ... end;`;但这里只借外形,不默认继承 Pascal 的全部语义、库习惯和文件模型。 +- 先看顶层主体,再看细节;不要先被文件扩展名带偏。 +- 当前手册把顶层主体优先收敛成四类:松散语句、顶层 `function / procedure`、顶层 `type Name = class`、顶层 `unit`。 +- 顶层 `uses` 可以出现,但这里只把它当成辅助组织语句,不把它当成主体声明。 +- 日常赋值先记 `:=`,不要把 `=` 当成普通赋值。 + +## 第一次写时最容易混淆的差异 + +- `array(...)` 既可以当顺序数组,也可以当字符串键表。 +- 数组下标从 `0` 开始,字符串下标从 `1` 开始。 +- 顶层类定义按 `type Name = class ... end;` 去写,不使用裸 `class Name`。 +- 调用函数时,命名参数写成 `name: value`,例如 `Demo(a: 1, b: 2)`。 + +## 已验证的第一印象 + +最常见的 `function / procedure` 外形: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(); +begin + return 1; +end; + +procedure LogDemo(msg); +begin + WriteLn(msg); +end; +``` + +赋值、数组、字符串下标的第一印象: + +代码块身份:已验证可执行示例 + +```tsl +items := array(10, 20, 30); +table_data := array("Code": "000001", "Name": "Demo"); +first_item := items[0]; +first_char := "ABC"[1]; +``` + +类的第一印象: + +代码块身份:已验证可执行示例 + +```tsl +type DemoType = class +end; +``` + +`unit` 的第一印象: + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface + +function Demo(); + +implementation + +function Demo(); +begin + return 1; +end; + +end. +``` + +## 下一步怎么读 + +- 需要立刻开始写代码:看 [02_quickstart.md](02_quickstart.md) +- 需要判断当前文件属于哪一种顶层模型:看 [03_core_model.md](03_core_model.md) +- 需要先写值、数组、字符串:看 [04_values_and_literals.md](04_values_and_literals.md) +- 需要先写变量、常量:看 [05_variables_and_constants.md](05_variables_and_constants.md) +- 需要先写函数和调用:看 [06_functions_and_calls.md](06_functions_and_calls.md) diff --git a/docs/tsl/syntax/02_quickstart.md b/docs/tsl/syntax/02_quickstart.md new file mode 100644 index 00000000..39a415eb --- /dev/null +++ b/docs/tsl/syntax/02_quickstart.md @@ -0,0 +1,132 @@ +# Syntax Quickstart + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[03_core_model.md](03_core_model.md)、[06_functions_and_calls.md](06_functions_and_calls.md)、[10_units_and_scope.md](10_units_and_scope.md) + +手册位置:第 2 篇,共 32 篇。上一篇:[01_introduction.md](01_introduction.md)。下一篇:[03_core_model.md](03_core_model.md)。 + +这一篇集中回答两个紧邻问题:现在要写 TSL 时,应该从哪一种最短骨架起手;以及落代码前必须先核对哪些语言硬规则。 + +## 这一篇解决什么问题 + +快速回答“当前任务应该从松散语句、函数、类还是 unit 开始”,并提供一份单点的语言核心事实速查。 + +## 语言核心事实速查 + +这一节是当前语法手册默认的语言硬规则收口点。涉及赋值、顶层外形、命名参数、类写法、`unit` 骨架和下标规则时,统一先看这里。 + +- 普通赋值用 `:=`,不要把 `=` 当成普通赋值。 +- 顶层主体先按四类理解:松散语句、`function / procedure`、`type Name = class`、`unit`。 +- 如果当前文件采用顶层 `function / procedure` 模型,就不要再混入松散语句。 +- 无返回值时用 `procedure Name(...); begin ... end;`,不要勉强用 `function`。 +- 顶层类定义统一写成 `type Name = class ... end;`,不要写裸 `class Name`。 +- 多文件组织默认先按 `unit Name; interface ... implementation ... end.` 理解。 +- 命名参数写法是 `Func(a:1, b:2)`。 +- `array(...)` 既可以写顺序数组,也可以写字符串键表;数组下标从 `0` 开始,字符串下标从 `1` 开始。 + +## 术语对照 + +- 文档里出现的“顶层 `function / procedure`”“顶层函数骨架”“顶层函数定义体”,指的是同一类顶层模型:文件以顶层 `function` / `procedure` 为主体。 +- 文档里出现的 ``class function`` 和“类方法”,指的是同一件事:前者是代码关键字写法,后者是中文描述。 + +## 先选哪一种骨架 + +| 当前任务 | 起手骨架 | +| --- | --- | +| 只写一段一次性脚本逻辑 | 顶层松散语句 | +| 先沉淀一个可复用逻辑块 | 顶层 `function` | +| 需要对象状态、字段、方法 | `type Name = class` | +| 需要把接口和实现组织进一个模块 | `unit` | + +默认建议: + +- 如果你只是要让新 session 先写出一段最稳、最容易续写的基础语法,优先从顶层 `function` 开始。 +- `uses` 往往天然进入多文件查找路径问题,所以不放进这篇的最小起手骨架里。 + +## 已验证最小骨架 + +顶层松散语句骨架: + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +``` + +顶层函数骨架: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(); +begin + return 1; +end; +``` + +顶层类骨架: + +代码块身份:已验证可执行示例 + +```tsl +type DemoType = class +end; +``` + +顶层 `unit` 骨架: + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface + function Ping(); + +implementation + function Ping(); + begin + return 1; + end; +end. +``` + +## 最常用起手版本 + +如果你现在没有明确的多文件或对象建模需求,直接从函数版本开始: + +代码块身份:已验证可执行示例 + +```tsl +function Hello(); +begin + return 1; +end; +``` + +## 最容易写错的一件事 + +- 不要把“顶层函数定义”和“顶层松散语句”混写在同一个最小文件里。 + +代码块身份:反例 / 不可照写 + +```text +function Add(a, b); +begin + return a + b; +end; + +value := Add(1, 2); +``` + +上面这种“先定义顶层函数,再接松散语句”的混合写法会编译失败。 + +## 跳转指引 + +- 先建立整体读法:见 [01_introduction.md](01_introduction.md) +- 继续判断顶层模型:见 [03_core_model.md](03_core_model.md) +- 继续写函数:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- 继续写 `unit` / `uses`:见 [10_units_and_scope.md](10_units_and_scope.md) +- 继续写类:见 [09_objects_and_classes.md](09_objects_and_classes.md) diff --git a/docs/tsl/syntax/03_core_model.md b/docs/tsl/syntax/03_core_model.md new file mode 100644 index 00000000..5b3db036 --- /dev/null +++ b/docs/tsl/syntax/03_core_model.md @@ -0,0 +1,108 @@ +# Core Model + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[06_functions_and_calls.md](06_functions_and_calls.md)、[10_units_and_scope.md](10_units_and_scope.md)、[09_objects_and_classes.md](09_objects_and_classes.md) + +手册位置:第 3 篇,共 32 篇。上一篇:[02_quickstart.md](02_quickstart.md)。下一篇:[04_values_and_literals.md](04_values_and_literals.md)。 + +这一篇说明 TSL 的文件模型判断规则:顶层主体是什么、辅助语句是什么、为什么很多错误其实是“文件模型选错了”。 + +## 这一篇解决什么问题 + +回答“当前文件到底属于哪一种顶层写法,以及哪些语句只是辅助组织,不应该被误当成主体声明”。 + +如果问题已经变成赋值、命名参数、类外形、`unit` 骨架或下标规则这类通用硬规则,统一回 [02_quickstart.md](02_quickstart.md) 的“语言核心事实速查”;这一页只处理文件模型判断。 + +## 必须记住的规则 + +- 比起扩展名,更可靠的判断方式是看顶层内容。 +- 顶层主体在当前手册里优先按四种外形理解:顶层松散语句、`function / procedure`、`type Name = class`、`unit`。 +- `uses` 可以出现在顶层,但这里只把它当成辅助语句,不把它当成主体声明;函数体和类定义体里的位置限制见 [10_units_and_scope.md](10_units_and_scope.md)。 +- 裸 `class Name` 不作为类定义写法使用。 +- 如果一个文件已经采用“顶层 `function / procedure`”模型,就不要再混入松散语句。 +- `unit` 默认先按完整形态理解;它也可以省略 `interface` / `implementation` 写成简写形态,见 [10_units_and_scope.md](10_units_and_scope.md)。 + +## 已验证语法 + +顶层主体的最小形态: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(); +begin + return 1; +end; +``` + +代码块身份:已验证可执行示例 + +```tsl +procedure DemoProc(); +begin +end; +``` + +代码块身份:已验证可执行示例 + +```tsl +type DemoType = class +end; +``` + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface +function Ping(); +implementation +function Ping(); +begin + return 1; +end; +end. +``` + +已验证失败的形态: + +代码块身份:反例 / 不可照写 + +```text +class DemoType +end; +``` + +上面这种裸 `class` 顶层写法会编译失败。 + +## 最小可编译示例 + +如果当前任务只是“先让 session 判断当前文件属于哪一种模型”,先记住下面这组归类: + +- 顶层语句骨架:直接写松散语句。 +- 顶层函数 / 过程骨架:写 `function ... begin ... end;` 或 `procedure ... begin ... end;`。 +- 顶层类骨架:写 `type Name = class ... end;`。 +- 顶层单元骨架:默认先写 `unit ... interface ... implementation ... end.`;简写形态见 [10_units_and_scope.md](10_units_and_scope.md)。 + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +``` + +## 常见误写 + +- 误以为扩展名本身就完全决定能否写函数、类或 `unit`。 +- 把 `uses` 当成主体声明,而不是辅助组织语句。 +- 把 `function / procedure` 定义体和松散语句混写。 + +## 跳转指引 + +- 先看整体读法:见 [01_introduction.md](01_introduction.md) +- 写最短骨架:见 [02_quickstart.md](02_quickstart.md) +- 写函数 / 过程:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- 写 unit / uses:见 [10_units_and_scope.md](10_units_and_scope.md) +- 写类:见 [09_objects_and_classes.md](09_objects_and_classes.md) diff --git a/docs/tsl/syntax/04_values_and_literals.md b/docs/tsl/syntax/04_values_and_literals.md new file mode 100644 index 00000000..31220cbe --- /dev/null +++ b/docs/tsl/syntax/04_values_and_literals.md @@ -0,0 +1,591 @@ +# Basic Types And Values + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[05_variables_and_constants.md](05_variables_and_constants.md)、[07_expressions_and_operators.md](07_expressions_and_operators.md)、[20_strings_and_text.md](20_strings_and_text.md) + +手册位置:第 4 篇,共 32 篇。上一篇:[03_core_model.md](03_core_model.md)。下一篇:[05_variables_and_constants.md](05_variables_and_constants.md)。 + +这一篇整理基本类型、字面量、数组、字符串与基础值模型,避免把值规则分散在函数或金融示例里。 + +## 这一篇解决什么问题 + +回答“基本类型怎么写、数组和字符串怎么索引、哪些值规则属于语言级事实”。 + +## 必须记住的规则 + +- 最先掌握的几类值是:整数、实数、字符串、布尔和 `array`。 +- 普通字符串既可以用双引号,也可以用单引号。 +- 同类引号本身可以通过连续写两个同类引号放进字符串里。 +- `\\`、`\"`、`\n` 这类基础转义已验证可用。 +- `\t` 和 `\xNN` 这类转义也已验证可用。 +- `\r`、`\r\n`、`\a`、`\b`、`\f`、`\v` 这些经典转义也已验证可用。 +- 当前解释器接受 `%%` 原始字符串;开头的 `%%` 或 `%%tag` 后面必须先跟一个空白分隔符,正文才开始。 +- `%%` 原始字符串里的反斜杠不做转义处理,并且支持多行内容。 +- `array(...)` 既可以写顺序数组,也可以写字符串键表。 +- 顺序数组下标从 `0` 开始。 +- `Binary(...)` 创建的二进制缓冲区,当前也用 `[]` 访问,并且下标从 `0` 开始。 +- 字符串下标从 `1` 开始。 +- `s[0]` 在运行时会越界,不要把字符串当成 0 基下标。 +- 字符串取子串用 `s[start:end]`,并且 `end` 是包含在结果里的。 +- 字符串替换子串用 `s[start:end] := "..."`。 +- 字符串删除子串,本质上就是 `s[start:end] := ""`。 +- 字符串插入子串用 `s[index:0] := "..."`。 +- 当前解释器接受 `L""` 与 `U""` 前缀字符串,但当前手册默认仍优先普通字符串。 +- 当前解释器也接受 `L%% ...%%` 与 `U%% ...%%` 前缀原始字符串。 +- 当前最小验证表明:从 `IfWString(...)` 观察,混合拼接时结果是否为宽串,取决于左操作数是否为宽串;`U""` 在这里仍按非宽串处理。 +- 当前最小验证表明:可以用 `String(...)` 把宽串显式转回普通串,也可以用 `WideString(...)` 把普通串显式转成宽串。 +- 当前最小验证表明:`U""` 可以和 `UnicodetoUTF8(...)`、`UTF8ToUnicode(...)`、`UTF8ToAnsi(...)`、`AnsiToUTF8(...)` 组成一条清晰的 UTF8 转换链;`U""` 本身不等同于宽串。 +- 当前最小验证表明:`\uXXXX` 在普通字符串里不要直接当成“单个字符宽串”;例如 `Length("\u0041")` 为 `2`,而 `Length(L"\u0041")` 和 `Length(U"\u0041")` 都为 `1`。 +- 当前最小验证表明:字符串可以包含 ASCII `0` 字符;`\0` 和 `#0` 都能构造这个字符,并且不会把字符串截断。 +- `#number` 可以按字符码直接拼进字符串里;`#13#10` 这类写法可直接形成换行。 + +## 已验证语法 + +最基础的值写法: + +代码块身份:已验证可执行示例 + +```tsl +count := 1; +price := 12.5; +name := "ABC"; +flag1 := true; +flag2 := false; +items := array(1, 2, 3); +``` + +其中已经验证: + +- `true` 可以直接写成布尔值。 +- `false` 可以直接写成布尔值。 +- 运行输出里,`true` / `false` 分别表现为 `1` / `0`。 + +普通字符串字面量: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("ABC"); +WriteLn('XYZ'); +``` + +已验证运行结果: + +- 依次输出 `ABC`、`XYZ` + +字符串内引号与基础转义: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("A""B"); +WriteLn('A''B'); +WriteLn("A\\B"); +WriteLn("A\"B"); +WriteLn("A\nB"); +``` + +已验证运行结果: + +- 依次输出 `A"B`、`A'B`、`A\B` +- `"A\nB"` 会分成两行输出 `A` 和 `B` + +更多基础转义: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("A\tB" = "A"#9"B"); +WriteLn("A\x30B" = "A0B"); +``` + +已验证运行结果: + +- 两行都输出 `1` +- 说明 `\t` 可以表示制表符,`\x30` 这类写法可以按 ANSI 字节值插入字符 + +经典控制字符转义: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn("\r" = #13); + WriteLn("\r\n" = #13#10); + WriteLn(Length("\r\n")); + WriteLn("\a" = #7); + WriteLn("\b" = #8); + WriteLn("\f" = #12); + WriteLn("\v" = #11); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`2`、`1`、`1`、`1`、`1` +- 说明 `\r` / `\r\n` 可以直接表示回车和回车换行 +- 说明 `\a`、`\b`、`\f`、`\v` 也已经在当前解释器里拿到正向最小结果 + +`L""` / `U""` 前缀的最小已验证事实: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn(L"A" = L"\u0041"); +WriteLn(U"Hello" = "Hello"); +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 说明当前解释器接受 `L""`、`U""` 和 ASCII 范围的 `\u` 表达 +- 但在当前控制台里直接 `WriteLn(L"Hello")` 会显示成带空字节的宽串输出,因此当前手册不把 `L""` 作为默认示例写法 + +非 ASCII 宽串的最小已验证事实: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn(L"\u5929\u8F6F" = L""#0x5929#0x8F6F); +``` + +已验证运行结果: + +- 输出 `1` +- 说明当前解释器接受非 ASCII 宽串的 `\uXXXX` 与 `#0xXXXX` 这两种构造方式 +- 但当前手册仍优先把它们当作边界写法,而不是默认入门写法 + +原始字符串 `%%`: + +代码块身份:已验证可执行示例 + +```tsl +s := %% ABC%%; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `ABC` +- 说明 `%%` 开头后面的第一个空白只是分隔符,不计入最终字符串内容 + +原始字符串不会处理转义: + +代码块身份:已验证可执行示例 + +```tsl +s := %% a\r\nb%%; +WriteLn(s = "a\\r\\nb"); +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `%%` 原始字符串里的 `\r`、`\n` 只是普通字符,不会变成回车换行 + +带标识符的原始字符串: + +代码块身份:已验证可执行示例 + +```tsl +s := %%tag A"B'C%%tag; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `A"B'C` +- 说明 `%%tag ...%%tag` 的首尾标识符可以配对使用,正文里可直接放单双引号 + +多行原始字符串: + +代码块身份:已验证可执行示例 + +```tsl +s := %%m +A +B%%m; +WriteLn(s); +``` + +已验证运行结果: + +- 输出两行 `A`、`B` +- 说明 `%%` 原始字符串支持直接跨行 + +带前缀的原始字符串: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn(L%% ABC%% = L"ABC"); +WriteLn(U%% ABC%% = "ABC"); +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 说明 `L%% ...%%` 和 `U%% ...%%` 在当前解释器里都可用 + +前缀字符串与混合拼接的最小类型观察: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(IfWString("A" + L"B")); + WriteLn(IfWString(L"A" + "B")); + WriteLn(IfWString(U"A")); + WriteLn(IfWString(U"A" + L"B")); + WriteLn(IfWString(L"A" + U"B")); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`1`、`0`、`0`、`1` +- 说明从 `IfWString(...)` 的观察角度看,混合拼接是否得到宽串,取决于左操作数是否为宽串 +- 也说明 `U""` 前缀字符串在这里仍按非宽串处理,不等同于 `L""` + +显式字符串类型转换: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := String(L"abcd"); + b := WideString("abcd"); + WriteLn(a = "abcd"); + WriteLn(IfWString(a)); + WriteLn(b = L"abcd"); + WriteLn(IfWString(b)); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`0`、`1`、`1` +- 说明 `String(...)` 可以把宽串显式转回普通串 +- 说明 `WideString(...)` 可以把普通串显式转成宽串 + +`U""` 与 UTF8 显式转换: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + utf8_s := U"\u5929\u8F6F"; + utf8_s2 := UnicodetoUTF8(L"\u5929\u8F6F"); + wide_s := UTF8ToUnicode(utf8_s); + ansi_s := UTF8ToAnsi(utf8_s); + WriteLn(IfWString(utf8_s)); + WriteLn(utf8_s = utf8_s2); + WriteLn(wide_s = L"\u5929\u8F6F"); + WriteLn(ansi_s = String(L"\u5929\u8F6F")); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`1`、`1`、`1` +- 说明 `U""` 在当前解释器里不是宽串 +- 说明 `U"\u5929\u8F6F"` 和 `UnicodetoUTF8(L"\u5929\u8F6F")` 可以对应到同一个 UTF8 串 +- 说明 `UTF8ToUnicode(...)` 可以把 UTF8 串转回宽串,`UTF8ToAnsi(...)` 可以把 UTF8 串转回普通串 + +ANSI / UTF8 / 宽串的最小往返: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + ansi_s := String(L"\u5929\u8F6F"); + utf8_s := AnsiToUTF8(ansi_s); + ansi_back := UTF8ToAnsi(utf8_s); + wide_s := UTF8ToUnicode(utf8_s); + WriteLn(IfWString(ansi_s)); + WriteLn(IfWString(utf8_s)); + WriteLn(IfWString(wide_s)); + WriteLn(ansi_back = ansi_s); + WriteLn(wide_s = L"\u5929\u8F6F"); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`0`、`1`、`1`、`1` +- 说明 `AnsiToUTF8(...)` 产物在这里仍按非宽串处理 +- 说明 `UTF8ToAnsi(...)` 和 `UTF8ToUnicode(...)` 都已经在当前解释器里拿到了正向最小结果 + +`\uXXXX` 在普通字符串、宽串和 `U` 串里的最小边界: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(Length("\u0041")); + WriteLn(Length(L"\u0041")); + WriteLn(Length(U"\u0041")); +end. +``` + +已验证运行结果: + +- 依次输出 `2`、`1`、`1` +- 因此不要把普通字符串里的 `"\u0041"` 直接理解成和 `L"\u0041"` 一样的“单字符宽串”语义 + +ASCII `0` 字符不会截断字符串: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s1 := "A\0B"; + s2 := "A"#0"B"; + WriteLn(Length(s1)); + WriteLn(Length(s2)); + WriteLn(s1 = s2); + WriteLn(s1[2] = #0); +end. +``` + +已验证运行结果: + +- 依次输出 `3`、`3`、`1`、`1` +- 说明 `\0` 和 `#0` 都可以把 ASCII `0` 放进字符串 +- 也说明当前字符串不是遇到 `#0` 就自动截断的 C 风格零结尾串 + +带 ASCII `0` 的字符串切片仍然保留该字符: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s := "A"#0"B"; + t := s[1:3]; + WriteLn(Length(t)); + WriteLn(t = s); + u := s[2:2]; + WriteLn(Length(u)); + WriteLn(u = #0); +end. +``` + +已验证运行结果: + +- 依次输出 `3`、`1`、`1`、`1` +- 说明字符串切片和单字符读取对 ASCII `0` 仍然稳定,不会在中间被截断 + +字符码拼接: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("A"#48"B"); +WriteLn("A"#13#10"B"); +``` + +已验证运行结果: + +- 第一行输出 `A0B` +- 第二组输出会分成两行 `A`、`B` +- 说明 `#48` 这类写法会按字符码直接参与字符串拼接,`#13#10` 可直接表示换行 + +代码块身份:已验证可执行示例 + +```tsl +arr := array(10, 20, 30); +hash := array("Code": "0001", "Price": 12.3); +s := "ABC"; +WriteLn("ARR0=", arr[0]); +WriteLn("ARR1=", arr[1]); +WriteLn("HASH=", hash["Code"]); +WriteLn("STR1=", s[1]); +WriteLn("STR2=", s[2]); +WriteLn("STR3=", s[3]); +``` + +已验证运行结果对应关系: + +- `arr[0] = 10` +- `arr[1] = 20` +- `hash["Code"] = "0001"` +- `s[1] = "A"` +- `s[2] = "B"` +- `s[3] = "C"` + +二进制缓冲区: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + b := Binary("30"); + WriteLn(IfBinary(b)); + WriteLn(b[0] = "3"); + WriteLn(b[1] = "0"); + b[1] := 0x31; + WriteLn(b[1] = "1"); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1`、`1` +- 说明 `Binary(...)` 当前确实得到二进制缓冲区 +- 说明二进制缓冲区的 `[]` 下标从 `0` 开始 +- 也说明二进制缓冲区项可以直接按单字节读写 + +字符串子串读取: + +代码块身份:已验证可执行示例 + +```tsl +s := "ABCDE"; +WriteLn(s[2:4]); +``` + +已验证运行结果: + +- 输出 `BCD` +- 这说明字符串区间 `2:4` 会包含结束位 `4` + +字符串替换子串: + +代码块身份:已验证可执行示例 + +```tsl +s := "ABCDE"; +s[2:4] := "XYZ"; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `AXYZE` + +字符串删除子串: + +代码块身份:已验证可执行示例 + +```tsl +s := "ABCDE"; +s[2:4] := ""; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `AE` + +字符串插入子串: + +代码块身份:已验证可执行示例 + +```tsl +s := "AAABBB"; +s[4:0] := "111"; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `AAA111BBB` +- 这说明 `s[index:0] := ...` 是在指定位置插入,而不是删除或替换区间 + +## 最小可编译示例 + +如果你只是要抓住“基本类型 + array”的第一层,用这个最短例子: + +代码块身份:已验证可执行示例 + +```tsl +count := 1; +price := 12.5; +name := "ABC"; +flag := true; +items := array(1, 2, 3); +``` + +## 常见误写 + +- 用 `s[0]` 访问字符串首字符。 +- 误以为 `array(...)` 只能写顺序数组,不能写字符串键表。 +- 误以为字符串区间和数组一样从 `0` 开始。 +- 把 `s[index:0] := ...` 误解成“替换到第 0 位”。 +- 把二进制缓冲区也按字符串的 `1` 基下标去理解。 +- 在普通字符串示例里默认切到 `L""`,却没有先确认下游场景真的需要宽串。 +- 把 `U""` 误解成和 `L""` 一样的宽串。 +- 把普通字符串里的 `"\uXXXX"` 直接当成和 `L"\uXXXX"` 一样的单字符写法。 +- 把带 `#0` / `\0` 的字符串当成会自动截断的 C 风格零结尾串。 +- 把 `%%ABC%%` 当成合法的原始字符串起手式。 + +代码块身份:反例 / 不可照写 + +```text +s := "ABC"; +WriteLn(s[0]); +``` + +上面这类写法在运行时会报字符串下标越界。 + +代码块身份:反例 / 不可照写 + +```text +s := "ABCDE"; +WriteLn(s[1:3]); +``` + +不要把上面这个区间访问类比成数组切片的半开区间。当前解释器里它输出的是 `ABC`,不是 `AB`;字符串区间的结束位会被包含进结果。 + +代码块身份:反例 / 不可照写 + +```text +s := %%ABC%%; +``` + +上面这种写法在当前解释器里会报 `missing or invalid characters`。`%%` 原始字符串开头后面必须先跟一个空白分隔符,或者写成 `%%tag ` 这种“标识符 + 空白”形式。 + +代码块身份:反例 / 不可照写 + +```text +WriteLn(Length("\u0041")); +WriteLn(Length(L"\u0041")); +``` + +不要把上面这两行想成同一件事。当前解释器里前者输出 `2`,后者输出 `1`;普通字符串里的 `\uXXXX` 不能直接按宽串单字符去理解。 + +代码块身份:反例 / 不可照写 + +```text +WriteLn(IfWString(U"\u5929\u8F6F")); +WriteLn(IfWString(L"\u5929\u8F6F")); +``` + +不要把 `U""` 和 `L""` 当成同一种“宽串前缀”。当前解释器里前者输出 `0`,后者输出 `1`。 + +代码块身份:反例 / 不可照写 + +```text +s := "A"#0"B"; +WriteLn(Length(s)); +``` + +不要把上面这类字符串想成遇到 `#0` 就结束。当前解释器里这里输出 `3`,说明 ASCII `0` 是字符串内容的一部分。 + +## 跳转指引 + +- 值有了名字以后怎么看:见 [05_variables_and_constants.md](05_variables_and_constants.md) +- 值怎样组成表达式:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 看字符串与编码深水专题:见 [20_strings_and_text.md](20_strings_and_text.md) diff --git a/docs/tsl/syntax/05_variables_and_constants.md b/docs/tsl/syntax/05_variables_and_constants.md new file mode 100644 index 00000000..74866f1a --- /dev/null +++ b/docs/tsl/syntax/05_variables_and_constants.md @@ -0,0 +1,301 @@ +# Variables And Constants + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[04_values_and_literals.md](04_values_and_literals.md)、[06_functions_and_calls.md](06_functions_and_calls.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 5 篇,共 32 篇。上一篇:[04_values_and_literals.md](04_values_and_literals.md)。下一篇:[06_functions_and_calls.md](06_functions_and_calls.md)。 + +这一篇收拢变量、常量与两种常量写法。 + +## 这一篇解决什么问题 + +回答“普通变量怎样直接使用、`var` 在什么位置出现、常量有哪些基本写法、哪些名字一旦绑定就不能再赋值”。 + +## 必须记住的规则 + +- 默认变量模型是“直接赋值即得到变量”,不要求先写 `var`。 +- 例如:`a := 1; b := array(1, 2, 3);` 这种写法已验证可直接编译。 +- `var name;` 目前只能当成一种显式声明写法,不能当成默认必需步骤。 +- `const Name = value;` 和 `const name := value;` 不能当成完全等价的两种写法。 +- 已验证: + - `const Name = value;` 适合函数内部 `const` 段、`unit` 接口常量、类成员常量。 + - `const name := value;` 适合顶层直接写的常量,单独成段也能编译。 +- 当前已验证:函数内部 `const = expr`、以及松散脚本顶层的 `const = expr` / `const := expr`,都可以把右侧写成常量表达式。 +- 这两种常量在当前解释器里都不能再次赋值。 +- 当前解释器接受多参数赋值:`[a, b] := array(...)`。 +- 左侧只有一个变量时,末尾逗号不能省略,必须写成 `[a, ] := array(...)`。 +- 当左侧变量数大于右侧数组长度时,多出的变量会得到 `nil`。 +- 右侧数组元素也可以是数组;拆出来的变量会直接得到对应子数组。 +- 多参数赋值也可以出现在函数调用参数里。 +- 截至 `2026-04-15` 的最小验证里,`{$Explicit+}` 开启后,后续变量必须先用 `var` 声明;未声明变量会报 `variable not defined`。 + +## 已验证语法 + +默认变量模型: + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +b := array(1, 2, 3); +``` + +显式 `var` 写法: + +代码块身份:已验证可执行示例 + +```tsl +var a; +a := 1; +``` + +`{$Explicit+}` 下的显式声明: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$Explicit+} + var a; + a := 1; + WriteLn(a); +end. +``` + +顶层最稳的常量写法: + +代码块身份:已验证可执行示例 + +```tsl +const value := 1; +``` + +顶层 `const :=` 也可以写常量表达式: + +代码块身份:已验证可执行示例 + +```tsl +const value := 1 + 2 * 3; +WriteLn(value); +``` + +函数内部 `const` 段: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(); +const MaxRetries = 1 + 2 * 3; +begin + return MaxRetries; +end; +``` + +`unit` 接口常量: + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface +const value = 1; +function GetValue(); +implementation +function GetValue(); +begin + return value; +end; +end. +``` + +类成员常量: + +代码块身份:已验证可执行示例 + +```tsl +type DemoType = class + const value = 1; +end; +``` + +顶层 `const =` 只有在“后面继续接可执行语句”的脚本模型里才已验证成立: + +代码块身份:已验证可执行示例 + +```tsl +const MaxRetries = 3 + 4; +value := MaxRetries; +``` + +代码块身份:已验证可执行示例 + +```tsl +var a; +a := 1; +``` + +多参数赋值: + +代码块身份:已验证可执行示例 + +```tsl +[r1, r2] := array(1, 3, 5, 7, 9); +WriteLn(r1); +WriteLn(r2); +``` + +已验证运行结果: + +- 依次输出 `1`、`3` + +单变量拆包时,末尾逗号不能省略: + +代码块身份:已验证可执行示例 + +```tsl +[re, ] := array(1, 2, 3, 4); +WriteLn(re); +``` + +已验证运行结果: + +- 输出 `1` + +左侧变量比右侧数组更长时,多出的变量为 `nil`: + +代码块身份:已验证可执行示例 + +```tsl +[r1, r2] := array(1); +WriteLn(r1); +WriteLn(r2 = nil); +``` + +已验证运行结果: + +- `r1` 输出 `1` +- `r2 = nil` 输出 `1` + +右侧元素也可以是数组: + +代码块身份:已验证可执行示例 + +```tsl +[r1, r2] := array((1, 2), (3, 4)); +WriteLn(r1[0]); +WriteLn(r1[1]); +WriteLn(r2[0]); +WriteLn(r2[1]); +``` + +已验证运行结果: + +- 依次输出 `1`、`2`、`3`、`4` + +函数返回数组后也可以直接拆包: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function PairAdd(a, b); +begin + return array(0, a + b); +end; +begin + [error, re] := PairAdd(3, 4); + WriteLn(error); + WriteLn(re); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`7` + +函数参数里也可以使用多参数赋值: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Test(a, b, c); +begin + return a + b + c; +end; +begin + WriteLn(Test(e := 3, [f, g] := array(1, 2), g)); +end. +``` + +已验证运行结果: + +- 输出 `6` + +## 最小可编译示例 + +如果你只是想先落一个可续写的普通变量和顶层常量骨架,用下面这组: + +代码块身份:已验证可执行示例 + +```tsl +const MaxRetries := 3; +counter := MaxRetries; +items := array(1, 2, 3); +``` + +## 常见误写 + +- 以为普通变量必须先写 `var` 才能使用。 +- 以为 `const =` 和 `const :=` 只是初始化方式不同,可以在任何上下文里互换。 +- 以为 `const =` 顶层单独写一行就一定成立。 +- 以为单变量拆包可以写成 `[a] := array(...)`。 +- 以为 `{$Explicit+}` 开启后仍然可以继续直接写未声明变量。 + +代码块身份:反例 / 不可照写 + +```text +const value := 1; +value := 2; +``` + +上面这类写法会编译失败,报错点在重新赋值这一行。 + +代码块身份:反例 / 不可照写 + +```text +const value = 1; +``` + +上面这类“顶层单独一行”的 `const =` 在当前解释器里也会编译失败。 + +代码块身份:反例 / 不可照写 + +```text +[re] := array(1, 2, 3); +``` + +上面这种单变量拆包写法在当前解释器里会报 `left side can not be assign to`。单变量时必须写成 `[re, ] := ...`。 + +代码块身份:反例 / 不可照写 + +```text +program test; +begin +{$Explicit+} + a := 1; +end. +``` + +上面这类写法在当前解释器里会编译失败,主因是 `variable not defined`。 + +## 跳转指引 + +- 回看基本类型:见 [04_values_and_literals.md](04_values_and_literals.md) +- 进入表达式:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 看词法和编译选项:见 [18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md) +- 看类型与转换:见 [19_types_and_conversions.md](19_types_and_conversions.md) diff --git a/docs/tsl/syntax/06_functions_and_calls.md b/docs/tsl/syntax/06_functions_and_calls.md new file mode 100644 index 00000000..4748f2cb --- /dev/null +++ b/docs/tsl/syntax/06_functions_and_calls.md @@ -0,0 +1,972 @@ +# Functions And Calls + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[03_core_model.md](03_core_model.md)(优先)、[10_units_and_scope.md](10_units_and_scope.md)、[21_external_calls_and_threads.md](21_external_calls_and_threads.md) + +手册位置:第 6 篇,共 32 篇。上一篇:[05_variables_and_constants.md](05_variables_and_constants.md)。下一篇:[07_expressions_and_operators.md](07_expressions_and_operators.md)。 + +这一篇只负责 `function` / `procedure` 的定义、调用、参数传递和值返回,不延伸到业务函数库。 + +## 这一篇解决什么问题 + +回答“如何正确声明 `function` 和 `procedure`、如何组织主函数和子函数、怎样使用参数修饰、默认参数与可变参数,以及哪些混写方式会直接编译失败”。 + +## 必须记住的规则 + +- 最稳妥的函数骨架仍然是 `function Name(...); begin ... end;`。 +- 不需要返回值时,可以改用 `procedure Name(...); begin ... end;`。 +- 在文件模型层,`function` 和 `procedure` 归同一类顶层外形;见 [03_core_model.md](03_core_model.md)。 +- 当前解释器接受省略函数头后的分号,但文档默认仍保留这个分号。 +- 一个函数定义体里可以同时出现主函数和子函数。 +- 函数支持参数类型注解和返回值类型注解。 +- 不带类型注解时,多个参数用逗号分隔。 +- 带类型注解时,多个参数用分号分隔。 +- 当前解释器接受 `const` 与 `var` 形参修饰。 +- 当前解释器的运行时默认行为是:未修饰参数可以写回调用方;这是运行时默认,不是语言规范保证。 +- `{$VarByRef-}` 会把未修饰参数切换成按值传递;`var` 形参仍保持引用语义。 +- 在 `{$VarByRef-}` 下,调用时可以用 `in` / `out` 前缀逐个参数覆盖默认传递方式。 +- 如果不确定当前任务是否需要写回语义,优先显式用 `const` 形参,或先切到 `{$VarByRef-}`;不要依赖未修饰参数的运行时默认行为。 +- `return expr;` 会直接返回当前函数结果。 +- `exit;` 会立即结束当前函数;在当前最小样例里,如果此前没有写入返回结果,调用方观察到的是默认值 `0`。 +- 调用时支持命名参数,写法是 `name: value`。 +- 命名参数当前也支持 `call(...)` 这类按函数名或函数指针转调的模型。 +- 一旦某次调用里开始使用命名参数,后面的参数就不能再退回位置参数。 +- 对二进制函数 / 系统函数直接使用命名参数,当前会报 `named parameter mode can't support here`;这类函数要先用 TSL 再封一层。 +- 函数参数支持默认值。 +- 普通函数的默认值规则不要直接等同到 `unit interface` 声明;跨 `unit` 的默认参数边界见这一篇后面的对照例子,以及 [10_units_and_scope.md](10_units_and_scope.md)。 +- 当前解释器支持尾部 `...` 形式的可变参数。 +- 在可变参数函数体里,`Params`、`ParamCount`、`RealParamCount` 都已验证可用。 +- 可变参数组可以通过 `...` 转发给另一个函数调用。 +- 可变参数组也可以通过 `call(fc, ...)`、`##fc(...)`、`invoke(obj, name, 0, ...)` 转发。 +- 当前解释器接受 `a := function(...) begin ... end;` 这种匿名函数写法。 +- 匿名函数可以直接作为参数传入另一个函数。 +- 当前解释器接受 `ThisFunction(FuncName)` 把已知函数绑定成函数值。 +- 当前解释器里,匿名函数和函数指针的稳定调用方式仍是 `call(f, ...)` 或 `##f(...)`。 +- 当前解释器没有通过 `f(...)` 这种“函数变量直接调用”写法;无论 `f` 是匿名函数、`FindFunction(...)` 还是 `ThisFunction(...)` 返回的函数指针,都不要默认写成直调。 +- 当前解释器接受 `::FuncName(...)` 指向全局/系统函数,用来绕过当前作用域里的同名局部函数。 +- `external`、`MakeInstance` 和线程调用统一移到 [21_external_calls_and_threads.md](21_external_calls_and_threads.md)。 +- 不要把顶层函数定义和松散语句混在同一个文件模型里。 + +## 已验证语法 + +### 基础函数 / 过程骨架 + +最短函数骨架: + +代码块身份:已验证可执行示例 + +```tsl +function Add(a, b); +begin + return a + b; +end; +``` + +主函数加子函数: + +代码块身份:已验证可执行示例 + +```tsl +function MultiFunc(); +begin + return Twice(3); +end; + +function Twice(x); +begin + return x * 2; +end; +``` + +函数头省略分号在当前解释器里也可编译: + +代码块身份:已验证可执行示例 + +```tsl +function MissingSemi() +begin + return 1; +end; +``` + +最短 `procedure` 骨架: + +代码块身份:已验证可执行示例 + +```tsl +procedure LogDone(); +begin +end; +``` + +`procedure` 写回参数的最小运行样例: + +这是验证样例外壳,不作为正式顶层模型归类依据。 + +代码块身份:已验证可执行示例 + +```tsl +program test; +procedure Bump(var x); +begin + x := x + 1; +end; +begin + a := 1; + Bump(a); + WriteLn(a); +end. +``` + +已验证运行结果: + +- `Bump(a)` 后输出 `2` + +### 签名增强 + +带参数类型和返回值类型: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(a: integer): integer; +begin + return a; +end; +``` + +带类型时的多参数分隔: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(a: integer; b: integer); +begin + return a + b; +end; +``` + +类型名可以写成更偏说明性的名字: + +代码块身份:已验证可执行示例 + +```tsl +function Demo(a: input_value; b: handler): result_type; +begin + return a; +end; +``` + +参数修饰: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function ReadConst(const x); +begin + return x + 1; +end; +procedure SetVar(var x); +begin + x := x + 5; +end; +begin + a := 10; + WriteLn(ReadConst(a)); + SetVar(a); + WriteLn(a); +end. +``` + +已验证运行结果: + +- `ReadConst(a)` 输出 `11` +- `SetVar(a)` 之后,`a` 输出 `15` +- 直接给 `const` 形参赋值会编译失败 + +### 参数传递方式 + +默认参数写回调用方: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TouchDefault(a); +begin + a := 9; +end; +begin + x := 1; + TouchDefault(x); + WriteLn(x); +end. +``` + +已验证运行结果: + +- `TouchDefault(x)` 之后,`x` 输出 `9` + +`{$VarByRef-}` 与 `var` 形参: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TouchDefault(a); +begin + a := 9; +end; +{$VarByRef-} +function TouchValue(a); +begin + a := 8; +end; +function TouchForcedVar(var a); +begin + a := 7; +end; +{$VarByRef+} +begin + x := 1; + TouchDefault(x); + WriteLn(x); + y := 1; + TouchValue(y); + WriteLn(y); + z := 1; + TouchForcedVar(z); + WriteLn(z); +end. +``` + +已验证运行结果: + +- 默认模式下,`TouchDefault(x)` 后 `x` 输出 `9` +- `{$VarByRef-}` 下,未修饰参数版本 `TouchValue(y)` 之后,`y` 仍输出 `1` +- `{$VarByRef-}` 下,`var` 形参版本 `TouchForcedVar(z)` 之后,`z` 输出 `7` + +`in` / `out` 调用前缀: + +代码块身份:已验证可执行示例 + +```tsl +program test; +{$VarByRef-} +procedure Touch3(a, b, c); +begin + a := 1; + b := 2; + c := 3; +end; +begin + a := 0; + b := 0; + c := 0; + Touch3(a, b, c); + WriteLn(a); + WriteLn(b); + WriteLn(c); + Touch3(in a, out b, c); + WriteLn(a); + WriteLn(b); + WriteLn(c); +end. +``` + +已验证运行结果: + +- 在 `{$VarByRef-}` 下,直接调用 `Touch3(a, b, c)` 后依次输出 `0`、`0`、`0` +- 同样在 `{$VarByRef-}` 下,`Touch3(in a, out b, c)` 后依次输出 `0`、`2`、`0` +- 说明 `in` / `out` 可以在调用点逐个参数覆盖当前默认传递方式 + +### `return` 与 `exit` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Demo(x); +begin + if x > 0 then + exit; + return 99; +end; +begin + WriteLn(Demo(1)); + WriteLn(Demo(0)); +end. +``` + +已验证运行结果: + +- `Demo(1)` 输出 `0` +- `Demo(0)` 输出 `99` +- 说明 `exit;` 会立即结束当前函数体 +- 在这个最小例子里,因为 `exit;` 之前没有写入返回结果,调用方观察到的是默认值 `0` + +### 调用增强 + +命名参数调用: + +代码块身份:已验证可执行示例 + +```tsl +function NamedArgsDemo(); +begin + return Pack(a: 1, b: 2); +end; + +function Pack(a, b); +begin + return a * 10 + b; +end; +``` + +已验证运行结果: + +- `Pack(a: 1, b: 2)` 返回 `12` +- `Pack(b: 2, a: 1)` 返回 `12` +- `Pack(1, b: 2)` 返回 `12` + +跳过中间参数时,未命中的参数当前保持 `nil`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TestFunc(a, b, c); +begin + WriteLn(IfNil(b)); + return 0; +end; +begin + TestFunc(1, c: 3); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `TestFunc(1, c: 3)` 这种调用里,中间参数 `b` 当前会保持 `nil` + +通过 `call(...)` 也支持命名参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TestFunc(a, b, c); +begin + return a * 100 + b * 10 + c; +end; +begin + WriteLn(call("TestFunc", a: 1, c: 2, b: 3)); +end. +``` + +已验证运行结果: + +- 输出 `132` +- 说明 `call(...)` 当前也支持按参数名传值 +- 说明命名参数传入后不再按位置解释,而是按名字绑定到形参 + +命名参数可以调换顺序: + +代码块身份:已验证可执行示例 + +```tsl +function NamedArgsDemo(); +begin + return Pack(b: 2, a: 1); +end; + +function Pack(a, b); +begin + return a * 10 + b; +end; +``` + +命名参数也可以和位置参数混用: + +代码块身份:已验证可执行示例 + +```tsl +function NamedArgsDemo(); +begin + return Pack(1, b: 2); +end; + +function Pack(a, b); +begin + return a * 10 + b; +end; +``` + +### 默认参数 + +默认值参数: + +代码块身份:已验证可执行示例 + +```tsl +function AddOne(a = 1); +begin + return a + 1; +end; +``` + +带类型时也支持默认值: + +代码块身份:已验证可执行示例 + +```tsl +function TypedAdd(a: integer = 1): integer; +begin + return a + 1; +end; +``` + +多个参数时,后面的参数可以带默认值: + +代码块身份:已验证可执行示例 + +```tsl +function Pack(a, b = 2); +begin + return a * 10 + b; +end; +``` + +代码块身份:已验证可执行示例 + +```tsl +function Pack(a: integer; b: integer = 2): integer; +begin + return a * 10 + b; +end; +``` + +默认值也可以写成表达式: + +代码块身份:已验证可执行示例 + +```tsl +function ExprDefault(a = 1 + 2); +begin + return a; +end; +``` + +已验证运行结果: + +- `AddOne()` 返回 `2` +- `AddOne(5)` 返回 `6` +- `TypedAdd()` 返回 `2` +- `TypedAdd(5)` 返回 `6` +- `Pack(1)` 返回 `12` +- `Pack(a: 1)` 返回 `12` +- `ExprDefault()` 返回 `3` + +`unit interface` 声明下的默认参数要单独看: + +以下是不可照写的对比:普通函数默认参数能跑通,不等于跨 `unit` 声明边界也同样可靠。 + +代码块身份:反例 / 不可照写 + +```text +// P.tsf +function P(a = 5, b = 6); +begin + return a + b; +end; + +// UnitLiteral.tsf +unit UnitLiteral; +interface +function H(a = 5); +implementation +function H(a); +begin + return a; +end; +end. + +// UnitConst.tsf +unit UnitConst; +interface +const CS = 888; +function F(a, b = 100, c = CS); +implementation +function F(a, b, c); +begin + return a + b + c; +end; +end. + +// main.tsl +program test; +uses UnitLiteral, UnitConst; +begin + WriteLn(P()); + WriteLn(H()); + WriteLn(F(1)); + WriteLn(F(1, 2)); +end. + +// command +tsl .\main.tsl -LIBPATH "D:\path\to\dir\" +``` + +已验证运行结果: + +- 普通函数 `P()` 输出 `11` +- `unit interface` 里声明的字面量默认值 `H()` 输出 `5` +- `F(1)` 输出 `101`,`F(1, 2)` 输出 `3` +- 同一组文件下,`UnitConst.CS` 当前仍可读到 `888`,而 `F(1, 2, 3)` 输出 `6` +- 因此当前解释器下,不要把“普通函数默认参数可用”直接泛化成“`unit interface` 里引用 `unit const` 的默认参数也同样可靠” +- 这组多文件结果依赖真实查找路径;当前验证命令是把对应目录放进 `-LIBPATH` +- 这类跨 `unit` 的声明边界,统一回看 [10_units_and_scope.md](10_units_and_scope.md) + +### 可变参数 `...` + +尾部可变参数: + +代码块身份:已验证可执行示例 + +```tsl +function SumAll(...); +begin + s := 0; + for i, v in Params do + s := s + v; + return s; +end; +``` + +可变参数转发: + +代码块身份:已验证可执行示例 + +```tsl +function Forward(...); +begin + return SumAll(...); +end; + +function SumAll(...); +begin + s := 0; + for i, v in Params do + s := s + v; + return s; +end; +``` + +`ParamCount` 与 `RealParamCount`: + +代码块身份:已验证可执行示例 + +```tsl +function CountArgs(a, b, ...); +begin + return ParamCount * 10 + RealParamCount; +end; +``` + +已验证运行结果: + +- `SumAll(1, 2, 3, 4)` 返回 `10` +- `Forward(1, 2, 3, 4)` 返回 `10` +- `CountArgs(1, 2, 3, 4)` 返回 `44` +- `CountArgs(1, 2)` 返回 `22` + +通过 `call` 与 `##` 转发可变参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Sum3(a, b, c); +begin + return a + b + c; +end; +function DoFunc(fc, ...); +begin + return call(fc, ...); +end; +function DoFunc2(fc, ...); +begin + return ##fc(...); +end; +begin + WriteLn(DoFunc("Sum3", 1, 2, 3)); + WriteLn(DoFunc2(thisfunction(Sum3), 1, 2, 3)); +end. +``` + +已验证运行结果: + +- `DoFunc("Sum3", 1, 2, 3)` 输出 `6` +- `DoFunc2(thisfunction(Sum3), 1, 2, 3)` 输出 `6` + +通过 `invoke` 转发可变参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TestC = class +public + function FuncA(a, b, c); + begin + return a + b + c; + end; + function FuncB(a, b, c); + begin + return a * 100 + b * 10 + c; + end; + function Dispatch(kind, ...); + begin + if kind = "Int" then + return FuncA(...) + else + return FuncB(...); + end; +end; +function DoInvoke(fc_name, ...); +begin + obj := new TestC(); + return invoke(obj, fc_name, 0, ...); +end; +begin + WriteLn(DoInvoke("Dispatch", "Int", 2, 20, 200)); + WriteLn(DoInvoke("Dispatch", "Other", 1, 2, 3)); +end. +``` + +已验证运行结果: + +- `DoInvoke("Dispatch", "Int", 2, 20, 200)` 输出 `222` +- `DoInvoke("Dispatch", "Other", 1, 2, 3)` 输出 `123` + +### 匿名函数与函数指针 + +匿名函数变量: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := function(x, y) + begin + return x + y; + end; + WriteLn(call(a, 1, 2)); + WriteLn(##a(5, 6)); +end. +``` + +已验证运行结果: + +- `call(a, 1, 2)` 输出 `3` +- `##a(5, 6)` 输出 `11` + +匿名函数也可以直接作为参数传入: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Apply(fun); +begin + return call(fun, 2, 3); +end; +begin + WriteLn(Apply(function(x, y) + begin + return x * y; + end)); +end. +``` + +已验证运行结果: + +- 输出 `6` + +函数指针变量也可以通过 `FindFunction(...)` 拿到: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Add(a, b); +begin + return a + b; +end; +begin + f := FindFunction("Add"); + WriteLn(##f(1, 2)); +end. +``` + +已验证运行结果: + +- 输出 `3` + +也可以通过 `ThisFunction(...)` 从已知函数名直接拿到: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Add(a, b); +begin + return a + b; +end; +begin + f := ThisFunction(Add); + WriteLn(Call(f, 3, 4)); +end. +``` + +已验证运行结果: + +- 输出 `7` +- 说明 `ThisFunction(Add)` 当前可以得到稳定可调用的函数值 + +直接 `f(...)` 在当前解释器里不要当成可靠写法: + +代码块身份:反例 / 不可照写 + +```text +// 匿名函数变量直接调用 +program test; +begin + a := function(x, y) + begin + return x + y; + end; + WriteLn(a(7, 8)); +end. + +// FindFunction 返回值直接调用 +program test; +function Add(a, b); +begin + return a + b; +end; +begin + f := FindFunction("Add"); + WriteLn(f(3, 4)); +end. + +// ThisFunction 返回值直接调用 +program test; +function Add(a, b); +begin + return a + b; +end; +begin + f := ThisFunction(Add); + WriteLn(f(3, 4)); +end. +``` + +已验证结果: + +- 上面三种 `f(...)` 直调写法都会报 `function: compile error or not found` +- 因此当前手册只把 `call(f, ...)` 和 `##f(...)` 写成稳定规则 + +### `::` 指向全局函数 + +当当前作用域里有同名局部函数时,可以用 `::FuncName(...)` 指定去调全局/系统函数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Demo(); +begin + return array(StrToInt("123"), ::StrToInt("123")); +end; +function StrToInt(s); +begin + return 888; +end; +begin + r := Demo(); + WriteLn(r[0]); + WriteLn(r[1]); +end. +``` + +已验证运行结果: + +- 第一项 `StrToInt("123")` 命中局部函数,输出 `888` +- 第二项 `::StrToInt("123")` 命中全局系统函数,输出 `123` +- 说明 `::` 可以绕过当前作用域的同名局部函数,直接指向全局/系统函数 + +如果 `::FuncName(...)` 指向的全局函数本身不存在,当前解释器会在运行时报 `function: compile error or not found` + +### 系统交互专题 + +`external`、动态库函数指针、`MakeInstance` 和线程调用,统一见 [21_external_calls_and_threads.md](21_external_calls_and_threads.md)。这一篇只保留“普通函数怎样定义和调用”的主线。 + +## 最小可编译示例 + +如果你只是要写一个能被 session 稳定续写的函数 / 过程,从下面任一骨架起步: + +代码块身份:已验证可执行示例 + +```tsl +function Hello(); +begin + return 1; +end; +``` + +代码块身份:已验证可执行示例 + +```tsl +procedure HelloProc(); +begin +end; +``` + +## 常见误写 + +- 把顶层函数定义和松散语句混写。 +- 以为函数头后的分号是当前解释器的硬性要求。 +- 以为 `procedure` 只是 `function` 的别名,不涉及参数传递语义。 +- 带类型注解时仍然用逗号分隔参数。 +- 以为默认未修饰参数天然就是按值传递。 +- 把 `a = 1` 这种比较表达式误当成命名参数调用。 +- 以为默认值只能用于无类型参数。 +- 在 `const` 形参上直接赋值。 +- 把普通函数的默认值规则原样套到 `unit interface` 里的 `const` 默认参数上。 +- 把匿名函数或 `FindFunction(...)` 返回值默认写成 `f(...)` 直调。 +- 把命名参数直接套到二进制函数或系统函数上。 +- 在一次调用里先进入命名参数模式,后面又退回位置参数。 + +代码块身份:反例 / 不可照写 + +```text +function Add(a, b); +begin + return a + b; +end; + +value := Add(1, 2); +``` + +上面这种混写方式会编译失败,问题不在 `Add` 本身,而在于文件模型混了“函数定义体”和“松散语句”两种写法。 + +代码块身份:反例 / 不可照写 + +```text +function Demo(a: integer, b: integer); +begin + return a + b; +end; +``` + +上面这种写法会编译失败;参数一旦带类型,分隔符应改成分号。 + +代码块身份:反例 / 不可照写 + +```text +Pack(a = 1, b = 2) +``` + +这类写法不要当成命名参数。它虽然可能编译通过,但在我于 `2026-04-09` 的实测里返回结果不对,不能当成可靠的命名参数语法。 + +代码块身份:反例 / 不可照写 + +```text +function Demo(a: integer, b: integer = 2): integer; +begin + return a + b; +end; +``` + +上面这种写法也不对;参数一旦带类型,分隔符仍然应保持分号。 + +代码块身份:反例 / 不可照写 + +```text +function TouchDefault(a); +begin + a := 9; +end; +``` + +不要把上面这种未修饰参数自动理解成“按值传递”。在当前解释器里,它会把调用方实参改掉;如果当前任务要求按值语义,先看 `{$VarByRef-}` 和 `in` / `out` 的例子。 + +代码块身份:反例 / 不可照写 + +```text +procedure Bad(const x); +begin + x := 2; +end; +``` + +上面这种写法会编译失败;`const` 形参在当前解释器里不能被重新赋值。 + +代码块身份:反例 / 不可照写 + +```text +unit UnitConst; +interface +const CS = 888; +function F(a, b = 100, c = CS); +``` + +不要把上面这种 `unit interface` 声明直接当成已经等价于普通函数默认参数规则。在当前解释器里,对应的 `F(1)` 实测输出是 `101`,不是按 `CS = 888` 补成的结果;具体边界见 [10_units_and_scope.md](10_units_and_scope.md)。 + +代码块身份:反例 / 不可照写 + +```text +a := function(x, y) +begin + return x + y; +end; +WriteLn(a(7, 8)); +``` + +不要把上面这种匿名函数变量的直调写法直接当成可靠规则。在当前解释器里,它会报 `function:a compile error or not found`;稳定写法仍然是 `call(a, 7, 8)` 或 `##a(7, 8)`。 + +代码块身份:反例 / 不可照写 + +```text +WriteLn(IntToStr(value: 200)); +``` + +不要把上面这种写法直接套到二进制函数或系统函数上。当前解释器里,它会报 `named parameter mode can't support here`;如果确实要命名传参,先用 TSL 函数再封一层。 + +代码块身份:反例 / 不可照写 + +```text +function Pack(a, b, c); +begin + return a * 100 + b * 10 + c; +end; +begin + WriteLn(Pack(a: 1, 2, c: 3)); +end. +``` + +不要在同一次调用里“先进入命名参数模式,再退回位置参数”。当前这类写法会直接编译失败,错误信息包含 `paramname: not found`。 + +## 跳转指引 + +- 回看最短骨架:见 [02_quickstart.md](02_quickstart.md) +- 回看流程控制:见 [08_control_flow.md](08_control_flow.md) +- 当函数变多时:见 [10_units_and_scope.md](10_units_and_scope.md) +- 看 `external`、`MakeInstance` 和线程调用:见 [21_external_calls_and_threads.md](21_external_calls_and_threads.md) diff --git a/docs/tsl/syntax/07_expressions_and_operators.md b/docs/tsl/syntax/07_expressions_and_operators.md new file mode 100644 index 00000000..bcc2c7a6 --- /dev/null +++ b/docs/tsl/syntax/07_expressions_and_operators.md @@ -0,0 +1,413 @@ +# Expressions And Operators + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[08_control_flow.md](08_control_flow.md)、[09_objects_and_classes.md](09_objects_and_classes.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 7 篇,共 32 篇。上一篇:[06_functions_and_calls.md](06_functions_and_calls.md)。下一篇:[08_control_flow.md](08_control_flow.md)。 + +这一篇集中放语言级表达式与运算符,避免与业务计算示例混用。 + +## 这一篇解决什么问题 + +回答“赋值、比较、条件求值、可空访问和一部分新表达式在 TSL 里怎样写”。 + +## 必须记住的规则 + +- 当前页只收已经单独验证过的基础表达式,不把未经逐条验证的扩展运算体系一次并进正文。 +- 赋值使用 `:=`。 +- 当前解释器接受 `+=`、`-=`、`*=`、`/=`、`%=` 这几种基础运算赋值。 +- 当前解释器接受语句级 `a++;` 与 `a--;`。 +- `=` 用于比较,不用于赋值。 +- 当前解释器接受字符串 `+` 拼接、字符串比较和 `like` 正则匹配。 +- 当前解释器同时接受 `flag ? true_value : false_value` 和 `if condition then true_value else false_value` 这两种条件求值写法。 +- 当前解释器接受 `@expr` 把后面的内容声明成表达式对象。 +- 当前解释器接受 `&"..."` 把字符串编译成表达式对象。 +- 当前解释器接受逗号表达式 `(exp1, exp2, ..., expN)`,并按从左到右顺序求值。 +- 当前解释器接受空安全访问 `a?.member` 与 `a?.[index]`。 +- 当前解释器接受 `not in`、`not like`、`not sqlin`、`not is` 这几种否定形式运算。 +- 当前解释器接受标量链式比较 `:>`、`:<`、`:<>`、`:==`、`:>=`、`:<=`。 +- 当前解释器接受矩阵链式比较 `::>`、`::<`、`::<>`、`::==`、`::>=`、`::<=`。 +- 当前环境里 `{$IFDEF ifexp}` 为真,可用于探测 `if ... then ... else ...` 表达式能力。 +- 当前环境里 `{$IFDEF nilinvoke}` 为真,可用于探测 nil 调用相关能力。 +- 不要把外部资料里的更深链式可空访问修正,直接当成当前解释器必然支持。 + +## 已验证语法 + +### 基础赋值和条件求值 + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +b := 2; +flag := a < b; +value := flag ? 10 : 20; +``` + +运算赋值: + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +a += 2; +WriteLn(a); +``` + +已验证运行结果: + +- 输出 `3` + +基础算术复合赋值: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := 10; + a -= 3; + WriteLn(a); + a *= 4; + WriteLn(a); + a /= 7; + WriteLn(a); + a %= 5; + WriteLn(a); +end. +``` + +已验证运行结果: + +- `a -= 3` 后输出 `7` +- `a *= 4` 后输出 `28` +- `a /= 7` 后输出 `4` +- `a %= 5` 后输出 `4` + +字符串同样支持 `+=`: + +代码块身份:已验证可执行示例 + +```tsl +s := "A"; +s += "B"; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `AB` + +字符串拼接、比较和 `like`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn("222" + "888"); + WriteLn("A" < "a"); + WriteLn("AB" < "ABC"); + WriteLn("ABC" = "ABC"); + WriteLn("2009-01-01" like "\\d{4}-\\d{2}-\\d{2}"); +end. +``` + +已验证运行结果: + +- 依次输出 `222888`、`1`、`1`、`1`、`1` +- 说明字符串可以直接用 `+` 拼接 +- 说明字符串比较区分字符序和大小写;当前例子里 `"A" < "a"` 为真 +- 说明当前 `like` 的右侧可以直接写正则模式 + +`like` 不要按 SQL `%` 通配去理解: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn("abc" like "a.*"); + WriteLn("abc" like "a%"); +end. +``` + +已验证运行结果: + +- 第一行输出 `1` +- 第二行输出 `0` +- 因此当前解释器里的 `like` 更接近“正则匹配”,不是 SQL 那套 `%` / `_` 通配语义 + +自增与自减: + +代码块身份:已验证可执行示例 + +```tsl +a := 1; +a++; +WriteLn(a); +a--; +WriteLn(a); +``` + +已验证运行结果: + +- 先输出 `2` +- 再输出 `1` + +`if` 表达式: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(if 2 > 1 then 2 else 1); +end. +``` + +已验证运行结果: + +- `if 2 > 1 then 2 else 1` 返回 `2` + +`@` 表达式前导: + +代码块身份:已验证可执行示例 + +```tsl +A := 1; +B := @A + 1; +C := eval(B); +WriteLn(C); +``` + +已验证运行结果: + +- 输出 `2` +- 说明 `@A + 1` 会得到一个可交给 `eval(...)` 求值的表达式对象 + +`&"..."` 表达式常量: + +代码块身份:已验证可执行示例 + +```tsl +A := 1; +B := &"A + 1"; +C := eval(B); +WriteLn(C); +``` + +已验证运行结果: + +- 输出 `2` +- 说明 `&"A + 1"` 会把字符串编译成表达式对象,再由 `eval(...)` 求值 + +逗号表达式: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Demo(); +begin + return (a := 1, b := 2, c := 3, a + b + c); +end; +begin + WriteLn(Demo()); +end. +``` + +已验证运行结果: + +- 输出 `6` +- 说明逗号表达式会按从左到右顺序执行前面的赋值,再返回最后一个表达式结果 + +逗号表达式也可以继续参与外层计算: + +代码块身份:已验证可执行示例 + +```tsl +A := (b := 2, c := 3, b * c) * c; +WriteLn(A); +``` + +已验证运行结果: + +- 输出 `18` +- 说明逗号表达式本身可以作为一个普通子表达式继续参与后续运算 + +### 空安全访问 + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Holder = class + value; +end; +begin + a := nil; + WriteLn(a?.value = nil); + h := new Holder(); + h.value := 7; + WriteLn(h?.value); + arr := nil; + WriteLn(arr?.[0] = nil); +end. +``` + +已验证运行结果: + +- `a?.value = nil` 输出 `1` +- `h?.value` 输出 `7` +- `arr?.[0] = nil` 输出 `1` + +### 否定形式运算 + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class +end; +type B = class +end; +begin + WriteLn(1 not in array(2, 3)); + WriteLn("2009-1-1" not like "\\d{4}-\\d{2}-\\d{2}"); + WriteLn(1 not sqlin array(2, 3)); + obj := new A(); + WriteLn(obj not is class(B)); +end. +``` + +已验证运行结果: + +- `1 not in array(2, 3)` 输出 `1` +- `"2009-1-1" not like "\\d{4}-\\d{2}-\\d{2}"` 输出 `1` +- `1 not sqlin array(2, 3)` 输出 `1` +- `obj not is class(B)` 输出 `1` + +### 标量链式比较 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(1 :< 2 :< 3); + WriteLn(3 :> 2 :> 1); + WriteLn(1 :== 1 :== 1); + WriteLn(3 :>= 2 :>= 2); + WriteLn(1 :<= 2 :<= 3); + WriteLn(1 :<> 2 :<> 3); +end. +``` + +已验证运行结果: + +- `1 :< 2 :< 3` 输出 `1` +- `3 :> 2 :> 1` 输出 `1` +- `1 :== 1 :== 1` 输出 `1` +- `3 :>= 2 :>= 2` 输出 `1` +- `1 :<= 2 :<= 3` 输出 `1` +- `1 :<> 2 :<> 3` 输出 `1` + +### 矩阵链式比较 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + r := array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1); + WriteLn(r[0]); + WriteLn(r[1]); + WriteLn(r[2]); + s := array(1, 2, -1) ::< 2 ::< array(3, 2, 1); + WriteLn(s[0]); + WriteLn(s[1]); + WriteLn(s[2]); +end. +``` + +已验证运行结果: + +- `array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`1` +- `array(1, 2, -1) ::< 2 ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`0` +- 说明矩阵链式比较会按元素位置分别得到结果数组,并且可以和标量混用 + +### 条件编译探测 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$IFDEF ifexp} + WriteLn(1); +{$ELSE} + WriteLn(0); +{$ENDIF} +{$IFDEF nilinvoke} + WriteLn(1); +{$ELSE} + WriteLn(0); +{$ENDIF} +end. +``` + +已验证运行结果: + +- `{$IFDEF ifexp}` 输出 `1` +- `{$IFDEF nilinvoke}` 输出 `1` + +## 最小可编译示例 + +如果你只需要最小的“比较 + 三目”例子,直接用这个: + +代码块身份:已验证可执行示例 + +```tsl +flag := 1 < 2; +value := flag ? 10 : 20; +``` + +## 常见误写 + +- 用 `=` 当赋值运算符。 +- 把 `if` 表达式写成没有 `else` 的半句。 +- 把更深链式可空访问 `c?.a?.[1]` 直接当成当前解释器已支持事实。 + +代码块身份:反例 / 不可照写 + +```text +a = 1; +``` + +上面这种写法会编译失败,因为单独的 `=` 在这里会被当成不成立的表达式。 + +代码块身份:反例 / 不可照写 + +```text +v := if 2 > 1 then 2; +``` + +上面这种写法也会编译失败;`if` 表达式当前必须带 `else`。 + +代码块身份:反例 / 不可照写 + +```text +c := nil; +WriteLn(c?.a?.[1] = nil); +``` + +上面这种更深的混合可空访问,在当前已记录验证里没有通过,不要提前把后续版本的修正结果写进结论。 + +## 跳转指引 + +- 回看基本类型:见 [04_values_and_literals.md](04_values_and_literals.md) +- 把表达式放进流程里:见 [08_control_flow.md](08_control_flow.md) diff --git a/docs/tsl/syntax/08_control_flow.md b/docs/tsl/syntax/08_control_flow.md new file mode 100644 index 00000000..72c7e4bb --- /dev/null +++ b/docs/tsl/syntax/08_control_flow.md @@ -0,0 +1,374 @@ +# Control Flow + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[07_expressions_and_operators.md](07_expressions_and_operators.md)、[16_debug_and_profiler.md](16_debug_and_profiler.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 8 篇,共 32 篇。上一篇:[07_expressions_and_operators.md](07_expressions_and_operators.md)。下一篇:[09_objects_and_classes.md](09_objects_and_classes.md)。 + +这一篇只收录流程控制与异常控制,不讨论金融语义。 + +## 这一篇解决什么问题 + +回答“`if`、`case`、`for`、`while`、`repeat`、`break`、`continue`、`try`、`raise` 这些流程结构在 TSL 里到底怎么写,哪些写法已经被当前解释器实测验证过”。 + +## 必须记住的规则 + +- `if ... then ... else ...` 可以直接跟单条语句;需要多条语句时再补 `begin ... end`。 +- `for` 已验证支持 `to`、`downto`、可选 `step`,以及 `for i, v in array` 遍历。 +- `while` 和 `repeat ... until` 都可直接使用;`repeat` 至少会先执行一轮再判断结束条件。 +- `break` 会跳出当前最近一层循环,`continue` 会跳过当前轮剩余语句。 +- `case ... of ... else ... end;` 已验证支持语句形态和表达式形态。 +- `case` 分支标签已验证支持逗号并列和 `to` 区间。 +- `try ... except ... end;` 可以捕获 `raise` 产生的错误,并继续执行后续语句。 +- `ExceptObject.ErrInfo` 在 `except` 块中可读,能拿到当前错误信息。 +- `ExceptObject.ErrLine` 和 `ExceptObject.ErrNo` 在 `except` 块中当前也可读。 +- `try ... finally ... end;` 无论是否报错,都会先执行 `finally`;如果没有 `except` 吞掉错误,脚本仍会在 `finally` 之后报错终止。 +- `raise "message"` 是当前解释器已验证可用的最小抛错写法。 +- `goto`、`DEBUGRETURN`、`DebugRunEnv`、计时和 profiler 这类“控制流补充工具”统一放到 [16_debug_and_profiler.md](16_debug_and_profiler.md)。 + +## 已验证语法 + +### `if`、`while`、`repeat ... until` + +代码块身份:已验证可执行示例 + +```tsl +flag := 1; +if flag > 0 then + value := 1 +else + value := 0; + +counter := 0; +while counter < 3 do + counter := counter + 1; + +repeat + counter := counter - 1; +until counter = 0; +``` + +### `for` 的几种主干写法 + +最基础的递增循环: + +代码块身份:已验证可执行示例 + +```tsl +sum := 0; +for i := 0 to 2 do + sum := sum + i; +``` + +带 `step` 的递增循环: + +代码块身份:已验证可执行示例 + +```tsl +s := 0; +for i := 1 to 5 step 2 do + s := s + i; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `9` + +带 `step` 的 `downto` 递减循环: + +代码块身份:已验证可执行示例 + +```tsl +s := 0; +for i := 5 downto 1 step 2 do + s := s + i; +WriteLn(s); +``` + +已验证运行结果: + +- 输出 `9` + +数组遍历: + +代码块身份:已验证可执行示例 + +```tsl +data := array(10, 20, 30); +for i, v in data do + WriteLn(i * 100 + v); +``` + +已验证运行结果: + +- 依次输出 `10`、`120`、`230` +- 这说明 `for i, v in data` 里的 `i` 从 `0` 开始 + +### `break` 与 `continue` + +`break`: + +代码块身份:已验证可执行示例 + +```tsl +i := 0; +sum := 0; +while true do +begin + i := i + 1; + if i > 3 then + break; + sum := sum + i; +end; +WriteLn(sum); +WriteLn(i); +``` + +已验证运行结果: + +- `sum` 输出 `6` +- `i` 输出 `4` + +`continue`: + +代码块身份:已验证可执行示例 + +```tsl +i := 0; +sum := 0; +while i < 4 do +begin + i := i + 1; + if i = 2 then + continue; + sum := sum + i; +end; +WriteLn(sum); +``` + +已验证运行结果: + +- 输出 `8` + +### `case` 语句形态 + +普通分支: + +代码块身份:已验证可执行示例 + +```tsl +a := 2; +case a of +1: + WriteLn("one"); +2: + WriteLn("two"); +else + WriteLn("other"); +end; +``` + +已验证运行结果: + +- 输出 `two` + +并列标签与区间: + +代码块身份:已验证可执行示例 + +```tsl +a := 4; +case a of +1, 2: + WriteLn("small"); +3 to 5: + WriteLn("mid"); +else + WriteLn("other"); +end; +``` + +已验证运行结果: + +- 输出 `mid` + +### `case` 表达式形态 + +代码块身份:已验证可执行示例 + +```tsl +a := 2; +b := case a of +1: + "one"; +2: + "two"; +else + "other"; +end; +WriteLn(b); +``` + +已验证运行结果: + +- 输出 `two` + +### `try ... except` + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("before"); +try + raise "boom"; +except + WriteLn("caught"); + WriteLn(ExceptObject.ErrInfo); +end; +WriteLn("after"); +``` + +已验证运行结果: + +- 先输出 `before` +- 再输出 `caught` +- `ExceptObject.ErrInfo` 输出包含 `raise: boom` 的错误信息 +- 最后继续输出 `after` + +`ExceptObject` 的扩展字段: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + try + raise "boom"; + except + WriteLn(ExceptObject.ErrLine); + WriteLn(ExceptObject.ErrNo); + end; +end. +``` + +已验证运行结果: + +- `ExceptObject.ErrLine` 输出 `4` +- `ExceptObject.ErrNo` 输出 `2` +- 说明当前解释器里,异常对象除了 `ErrInfo` 以外,也能直接提供出错行号和错误号 + +### `try ... finally` + +正常路径: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("before"); +try + WriteLn("body"); +finally + WriteLn("finally"); +end; +WriteLn("after"); +``` + +已验证运行结果: + +- 依次输出 `before`、`body`、`finally`、`after` + +报错路径: + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("before"); +try + WriteLn("body"); + raise "boom"; +finally + WriteLn("finally"); +end; +WriteLn("after"); +``` + +已验证运行结果: + +- 先输出 `before` +- 再输出 `body` +- 然后仍会输出 `finally` +- 随后脚本报错终止,`after` 不会执行 + +### `raise` + +代码块身份:已验证可执行示例 + +```tsl +WriteLn("before"); +raise "boom"; +WriteLn("after"); +``` + +已验证运行结果: + +- 先输出 `before` +- 随后脚本报错终止,`after` 不会执行 + +## 最小可编译示例 + +如果你只想先写一个最短条件分支,从这个开始: + +代码块身份:已验证可执行示例 + +```tsl +flag := 1; +if flag > 0 then + value := 1 +else + value := 0; +``` + +## 常见误写 + +- 在 `else` 前面误加分号。 +- 以为 `try ... finally` 会吞掉异常。 +- 把 `@case` 直接当成普通 `case` 表达式主写法。 +- 在还没搞清表达式规则前,先把复杂业务函数塞进条件里。 +- 把控制流问题和函数文件模型问题混在一起排查。 + +代码块身份:反例 / 不可照写 + +```text +if flag > 0 then + value := 1; +else + value := 0; +``` + +上面这种写法会编译失败,因为 `else` 前面的分号会让 `if` 语句在上一行提前结束。 + +代码块身份:反例 / 不可照写 + +```text +b := @case a of + 1: + "one"; + 2: + "two"; +else + "other"; +end; +WriteLn(b); +``` + +我在 `2026-04-13` 用当前解释器实测,上面这类最小例子输出的是 ``,不能把它当成普通 `case` 表达式的可靠主语法写进新 session 默认生成结果。 + +## 跳转指引 + +- 回看条件表达式:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 继续封装成函数:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- 看 `goto`、`DEBUGRETURN`、计时和 profiler:见 [16_debug_and_profiler.md](16_debug_and_profiler.md) diff --git a/docs/tsl/syntax/09_objects_and_classes.md b/docs/tsl/syntax/09_objects_and_classes.md new file mode 100644 index 00000000..8adbc1d8 --- /dev/null +++ b/docs/tsl/syntax/09_objects_and_classes.md @@ -0,0 +1,1320 @@ +# Objects And Classes + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[10_units_and_scope.md](10_units_and_scope.md)(优先)、[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 9 篇,共 32 篇。上一篇:[08_control_flow.md](08_control_flow.md)。下一篇:[10_units_and_scope.md](10_units_and_scope.md)。 + +这一篇收拢面向对象语法,只保留语言层规则。 + +## 这一篇解决什么问题 + +回答“`type Name = class`、字段、`static`、方法、`property`、析构、类类型、继承和对象创建在 TSL 里怎样写”。 + +本页后半段有少量依赖 `unit` 的双文件示例;如果你还没建立 `unit` / `uses` 的多文件心智模型,先看 [10_units_and_scope.md](10_units_and_scope.md)。 + +## 必须记住的规则 + +- 类定义统一按 `type Name = class ... end;` 写。 +- 顶层类声明当前已验证可以放在松散语句之后(单向允许)。 +- 顶层类声明当前也已验证可以放在顶层 `function / procedure` 之后。 +- 类声明当前没有通过写在函数体内部。 +- 在松散语句脚本里,可以先写松散语句再进入顶层类声明;但一旦进入顶层 `type Name = class ... end;` 声明,后面不能再回到松散语句模式。 +- 类里可以直接写字段和方法。 +- `static` 字段已验证可用;可以通过类类型访问,也可以通过实例访问。 +- `const` 成员已验证可用;实例常量可通过实例读取,`static const` 可通过类类型读取,也已验证可用于成员函数默认参数。 +- 方法体里可以用 `self` 指向当前实例。 +- `overload` 方法已验证可用;同名不同参数个数的方法可以共存。 +- 基础 `property` 形态已验证:`property Name read fieldOrMethod write fieldOrMethod`。 +- `property Name: Type ...` 这种类型注解写法已验证可用。 +- 参数化 `property` 已验证;当前这篇只写已经单独跑通的基础模式。 +- 参数化 `property` 的 accessor 方法当前已验证两种常见模式:读方法接同参数个数,写方法接“参数个数 + 赋值值”。 +- 索引型 `property` 已验证;调用时用圆括号 `obj.Prop(index)`。 +- 固定 `index` property 已验证;它可以把某个固定索引直接映射成普通属性读写。 +- `class(Name)` 和 `FindClass("Name")` 都可以拿到类类型。 +- `FindClass("ClassName", obj)` 已验证可把对象转成指定父类视图。 +- `class function` 已验证可用;本页里的“类方法”就是指 `class function`,前者是中文描述,后者是代码写法。 +- 当前解释器下更稳妥的类方法调用方式是先拿到类类型,再在类类型上调用。 +- 基础继承写法是 `type Child = class(Parent)`。 +- 多重继承写法 `type Child = class(Base1, Base2)` 已验证可用。 +- 基础覆盖写法是:父类方法声明为 `virtual`,子类对应方法声明为 `override`。 +- 基础祖先类调用已验证:可以用 `Inherited;`、`Inherited MethodName(...)` 或 `class(BaseClass, ObjectName).MethodName()`。 +- 已验证的对象创建写法至少有三种:`CreateObject("ClassName")`、`CreateObject(ClassType)` 和 `new ClassName()`。 +- 如果没有特殊需求,默认优先用 `new ClassName()`;只有需要字符串路径、类类型变量或跨 `unit` 路径时,再改用 `CreateObject(...)`。 +- 如果类里定义了 `function create(...)`,`new`、`CreateObject("ClassName", ...)` 和 `CreateObject(ClassType, ...)` 都已验证可以透传构造参数,也都已验证支持默认参数和命名参数。 +- 当前已验证的析构写法是无参 `function destroy();`;把对象引用设为 `nil` 时会触发它。 +- 工厂式 `self(0)` / `self(1)` 已验证可用;当前解释器没有通过 `self()` 这种无参工厂式写法。 +- 已做双文件运行验证:如果类定义在 `unit` 的嵌套路径里,可以用 `CreateObject("Unit1.Class1.Class2")` 这种字符串路径创建对象。 +- 已做双文件运行验证:可以写 `type MyNewClass = class(Unit1.Class1.Class2)` 直接继承单元里的嵌套类路径。 +- 当前环境里 `{$IFDEF ParentClassInUnit}` 为真,可用于探测“继承和构造单元中的类”能力是否可用。 +- `private` / `protected` / `public` 已验证可用;类开头未写可见性时,成员默认按 `public` 处理。 +- 同一个可见性段里后续没有切换关键字的成员,会沿用前一个可见性。 +- 外部访问 `private` / `protected` 字段或方法,会在执行时报对象成员访问错误。 +- 子类可以通过 `self` 访问父类 `protected` 成员;不能通过 `self` 访问父类 `private` 成员。 +- `create` 写成 `private` 或 `protected` 时,对象仍能创建,但 `new` 和 `CreateObject(...)` 不会执行该构造逻辑;构造函数应保持 `public`。 +- 更复杂的多重继承边界和更复杂的对象模型还没有在这篇里完整展开。 + +## 已验证语法 + +最短类骨架: + +如果你现在只是要“先写出一个类”,先从这个骨架起手;后面的例子再逐步进入字段、工厂函数和声明位置边界。 + +代码块身份:已验证可执行示例 + +```tsl +type Person = class +end; +``` + +字段、方法和 `CreateObject`: + +代码块身份:已验证可执行示例 + +```tsl +type Person = class + name; + function SetName(new_name); + begin + name := new_name; + end; +end; + +function MakePerson(); +begin + return CreateObject("Person"); +end; +``` + +类声明位置: + +代码块身份:已验证可执行示例 + +```tsl +obj := CreateObject("MyClass"); +obj.value := 5; +WriteLn(obj.value); + +type MyClass = class + value; +end; +``` + +已验证运行结果: + +- 输出 `5` +- 说明在当前解释器里,顶层类声明可以放在松散语句之后 +- 同时也说明 `CreateObject("MyClass")` 可以解析到后面才出现的类声明 + +顶层函数后面也可以继续声明类: + +代码块身份:已验证可执行示例 + +```tsl +function MakeObj(); +begin + return 1; +end; + +type MyClass = class + value; +end; +``` + +已验证结果: + +- 上述 `.tsf` 例子可以编译通过 + +类声明位置的反例: + +代码块身份:反例 / 不可照写 + +```text +// 函数体内部声明类 +function Demo(); +begin + type InnerClass = class + value; + end; + return 1; +end; + +// 松散语句在 type 之后继续出现 +a := 1; +type MyClass = class + value; +end; +WriteLn(a); +``` + +已验证结果: + +- 函数体内部声明类会报 `invalid statement` +- 在松散语句脚本里,`type MyClass = class ... end;` 之后继续写 `WriteLn(a);` 也会报 `invalid statement` + +`static` 字段: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type THuman = class + static + mCount; + function create(); + begin + mCount := (mCount ?: 0) + 1; + end; +end; +begin + class(THuman).mCount := 100; + WriteLn(class(THuman).mCount); + h := new THuman(); + WriteLn(class(THuman).mCount); + WriteLn(h.mCount); +end. +``` + +已验证运行结果: + +- `class(THuman).mCount := 100` 可以直接写静态字段 +- `class(THuman).mCount` 先输出 `100` +- 创建对象后,`class(THuman).mCount` 输出 `101` +- 通过实例读取 `h.mCount` 也输出 `101` + +同一字段也接受内联声明: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type THuman = class + static mCount; + function create(); + begin + mCount := (mCount ?: 0) + 1; + end; +end; +begin + class(THuman).mCount := 100; + h := new THuman(); + WriteLn(class(THuman).mCount); +end. +``` + +已验证运行结果: + +- `static mCount;` 这种内联写法也可以通过 +- 上述例子中的 `class(THuman).mCount` 输出 `101` + +`const` 成员: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type C = class +public + const mA = 1; + static const mB = mA + 10; + function TestConst(); + begin + return mA + mB; + end; + function TestConstInParam(b = mB); + begin + return b; + end; +end; +begin + o := new C(); + WriteLn(o.TestConst()); + WriteLn(o.TestConstInParam()); + WriteLn(o.mA); + WriteLn(class(C).mB); +end. +``` + +已验证运行结果: + +- 依次输出 `12`、`11`、`1`、`11` +- 说明类里可以定义实例常量和 `static const` +- 说明实例常量可通过实例读取,`static const` 可通过 `class(C)` 读取 +- 说明成员常量当前也可用于成员函数默认参数 + +`self` 指向当前实例: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Counter = class + value; + function create(v); + begin + self.value := v; + end; + function Inc(); + begin + self.value := self.value + 1; + return self.value; + end; +end; +begin + c := new Counter(10); + WriteLn(c.Inc()); +end. +``` + +已验证运行结果: + +- `c.Inc()` 输出 `11` + +可见性 `private` / `protected` / `public`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + value; +private + secret; + backup; +public + function create(); + begin + self.secret := 2; + self.backup := 3; + end; + function ReadSecret(); + begin + return self.secret + self.backup; + end; +end; +begin + a := new A(); + a.value := 9; + WriteLn(a.value); + WriteLn(a.ReadSecret()); +end. +``` + +已验证运行结果: + +- 类开头没有显式可见性时,`value` 默认按 `public` 处理,因此 `a.value := 9` 可以直接写。 +- `backup` 跟在 `private` 段后面,没有重新切换关键字,因此仍按 `private` 处理。 +- 上述例子依次输出 `9`、`5`。 + +`protected` 可供子类通过 `self` 访问: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class +protected + value; + function Hidden(); + begin + return 88; + end; +end; +type B = class(A) +public + function SetValue(v); + begin + self.value := v; + end; + function GetValue(); + begin + return self.value; + end; + function TryCall(); + begin + return self.Hidden(); + end; +end; +begin + b := new B(); + b.SetValue(66); + WriteLn(b.GetValue()); + WriteLn(b.TryCall()); +end. +``` + +已验证运行结果: + +- 子类里可以通过 `self.value` 访问父类 `protected` 字段。 +- 子类里也可以通过 `self.Hidden()` 调用父类 `protected` 方法。 +- 上述例子依次输出 `66`、`88`。 + +`private` 的失败场景,因为是已验证反例,这里用 `text` 展示: + +代码块身份:反例 / 不可照写 + +```text +// 外部访问 private 字段 +program test; +type A = class +private + secret; +public + function create(); + begin + self.secret := 7; + end; +end; +begin + a := new A(); + WriteLn(a.secret); +end. + +// 子类访问父类 private 字段 +program test; +type A = class +private + secret; +public + function ReadSecret(); + begin + return self.secret; + end; +end; +type B = class(A) +public + function SetSecret(v); + begin + self.secret := v; + end; +end; +begin + b := new B(); + b.SetSecret(77); + WriteLn(b.ReadSecret()); +end. +``` + +已验证运行结果: + +- 外部访问 `a.secret` 会在执行时报对象成员访问错误。 +- 子类里通过 `self.secret` 访问父类 `private` 字段也会在执行时报错。 +- 同样的规则也已单独用 `private` / `protected` 方法访问做过复核:外部不能调 `private` / `protected` 方法,子类只能调 `protected` 方法,不能调 `private` 方法。 + +`create` 建议保持 `public`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class +public + value; +private + function create(v); + begin + self.value := v; + end; +end; +begin + a := new A(111); + WriteLn(a.value); +end. +``` + +已验证运行结果: + +- `a := new A(111)` 可以创建对象。 +- 上述例子里的 `a.value` 输出 ``,说明 `private create` 没有执行。 +- 同样的结果已单独用 `protected create`、`CreateObject("A", ...)` 和 `CreateObject(class(A), ...)` 复核;当前解释器里构造函数应保持 `public`。 + +基础 `property`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type MyBox = class + _value; + function SetValue(v); + begin + if v > 0 then + _value := v; + end; + property Value read _value write SetValue; +end; +begin + b := new MyBox(); + b.Value := 7; + WriteLn(b.Value); + b.Value := -1; + WriteLn(b.Value); +end. +``` + +已验证运行结果: + +- `b.Value := 7` 后,`b.Value` 输出 `7` +- `b.Value := -1` 后,`b.Value` 仍输出 `7` + +带类型注解的 `property`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type MyBox = class + _value; + function SetValue(v); + begin + _value := v; + end; + property Value: score_value read _value write SetValue; +end; +begin + b := new MyBox(); + b.Value := 9; + WriteLn(b.Value); +end. +``` + +已验证运行结果: + +- `property Value: score_value ...` 这种类型注解写法可以通过 +- 上述例子中的 `b.Value` 输出 `9` + +索引型 `property`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + arr; + function create(); + begin + arr := array(); + end; + function rIndex(i); + begin + return arr[i]; + end; + function wIndex(i, value); + begin + arr[i] := value; + end; + property idx read rIndex write wIndex; +end; +begin + aa := new A(); + aa.idx(0) := "abc"; + WriteLn(aa.idx(0)); +end. +``` + +已验证运行结果: + +- `aa.idx(0) := "abc"` 可以写入索引 property +- `aa.idx(0)` 输出 `abc` + +固定 `index` property: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + arr; + function create(); + begin + arr := array(); + end; + function rIndex(i); + begin + return arr[i]; + end; + function wIndex(i, value); + begin + arr[i] := value; + end; + property idx read rIndex write wIndex; + property idx0 index 0 read rIndex write wIndex; +end; +begin + aa := new A(); + aa.idx0 := "abc"; + WriteLn(aa.idx0); + WriteLn(aa.idx(0)); +end. +``` + +已验证运行结果: + +- `aa.idx0 := "abc"` 可以写入固定整数索引 property +- `aa.idx0` 输出 `abc` +- `aa.idx(0)` 也输出 `abc` + +固定字符串索引: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + arr; + function create(); + begin + arr := array(); + end; + function rIndex(i); + begin + return arr[i]; + end; + function wIndex(i, value); + begin + arr[i] := value; + end; + property idx read rIndex write wIndex; + property school index "High school" read rIndex write wIndex; +end; +begin + aa := new A(); + aa.school := "math"; + WriteLn(aa.school); + WriteLn(aa.idx("High school")); +end. +``` + +已验证运行结果: + +- `property school index "High school"` 这种固定字符串索引写法可以通过 +- `aa.school` 输出 `math` +- `aa.idx("High school")` 也输出 `math` + +参数化 `property`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type MyDate = class + _year; + _month; + _day; + function getDateV(); + begin + return _year * 10000 + _month * 100 + _day; + end; + function setDateV(y, m, d); + begin + _year := y; + _month := m; + _day := d; + end; + property DateV(y, m) read getDateV write setDateV; +end; +begin + d := new MyDate(); + d.DateV(2025, 8) := 10; + WriteLn(d.DateV()); +end. +``` + +已验证运行结果: + +- `d.DateV(2025, 8) := 10` 可以给参数化 property 赋值 +- `d.DateV()` 输出 `20250810` + +参数化 `property` 的 accessor 方法参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + arr; + function create(); + begin + arr := array(); + end; + function getItem(i); + begin + return arr[i]; + end; + function setItem(i, value); + begin + arr[i] := value; + end; + property Item(i): slot_type read getItem write setItem; +end; +begin + aa := new A(); + aa.Item(2) := "x"; + WriteLn(aa.Item(2)); +end. +``` + +已验证运行结果: + +- `read getItem` 这种“读方法接同参数个数”的写法可以通过 +- `write setItem` 这种“写方法接参数个数 + 赋值值”的写法可以通过 +- 上述例子中的 `aa.Item(2)` 输出 `x` + +`new` 关键字: + +代码块身份:已验证可执行示例 + +```tsl +type Person = class +end; + +function MakePerson(); +begin + return new Person(); +end; +``` + +通过类类型创建对象: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Person = class + value; +end; +begin + cls := FindClass("Person"); + obj := CreateObject(cls); + obj.value := 42; + WriteLn(obj.value); +end. +``` + +已验证运行结果: + +- `CreateObject(cls)` 可以通过类类型创建对象 +- 上述例子中的 `obj.value` 输出 `42` + +也可以用 `class(Name)` 取得类类型: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Person = class + value; + function create(v); + begin + value := v; + end; +end; +begin + cls := class(Person); + obj := CreateObject(cls, 44); + WriteLn(obj.value); +end. +``` + +已验证运行结果: + +- `class(Person)` 可以拿到 `Person` 的类类型 +- `CreateObject(cls, 44)` 输出 `44` + +构造参数、默认值和命名参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Person = class + a; + b; + c; + function create(a, b = 20, c = 30); + begin + self.a := a; + self.b := b; + self.c := c; + end; +end; +begin + a := CreateObject("Person", 11); + WriteLn(a.a); + WriteLn(a.b); + WriteLn(a.c); + b := new Person(22, c:99); + WriteLn(b.a); + WriteLn(b.b); + WriteLn(b.c); +end. +``` + +已验证运行结果: + +- `CreateObject("Person", 11)` 依次输出 `11`、`20`、`30` +- `new Person(22, c:99)` 依次输出 `22`、`20`、`99` +- 说明构造函数默认参数和命名参数不只适用于普通函数调用,也适用于对象创建 + +类类型也同样支持默认参数和命名参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Person = class + a; + b; + c; + function create(a, b = 20, c = 30); + begin + self.a := a; + self.b := b; + self.c := c; + end; +end; +begin + cls := FindClass("Person"); + obj := CreateObject(cls, 33, c:77); + WriteLn(obj.a); + WriteLn(obj.b); + WriteLn(obj.c); +end. +``` + +已验证运行结果: + +- `CreateObject(cls, 33, c:77)` 依次输出 `33`、`20`、`77` +- 因此类类型入口下的 `CreateObject(cls, ...)` 也遵循同样的构造参数规则 + +`class function`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type MathBox = class + class function Add(x, y); + begin + return x + y; + end; +end; +begin + cls1 := class(MathBox); + WriteLn(cls1.Add(3, 4)); + cls2 := FindClass("MathBox"); + WriteLn(cls2.Add(5, 6)); +end. +``` + +已验证运行结果: + +- `class(MathBox).Add(...)` 可以调用类方法 +- `FindClass("MathBox").Add(...)` 可以调用类方法 +- 上述例子依次输出 `7`、`11` + +`overload` 方法: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TestClass = class + function fun(p1, p2); overload; + begin + return p1 + p2; + end; + function fun(p1); overload; + begin + return p1 + 10; + end; +end; +begin + t := new TestClass(); + WriteLn(t.fun(1, 2)); + WriteLn(t.fun(5)); +end. +``` + +已验证运行结果: + +- 依次输出 `3`、`15` +- 说明同名不同参数个数的方法当前可以共存 + +基础继承: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Animal = class + function Speak(); + begin + return 1; + end; +end; +type Dog = class(Animal) +end; +begin + d := new Dog(); + WriteLn(d.Speak()); +end. +``` + +已验证运行结果: + +- `type Dog = class(Animal)` 可以继承父类实例方法 +- 上述例子中的 `d.Speak()` 输出 `1` + +多重继承: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Fa(); + begin + return 1; + end; +end; +type B = class + function Fb(); + begin + return 2; + end; +end; +type C = class(A, B) +end; +begin + obj := new C(); + WriteLn(obj.Fa()); + WriteLn(obj.Fb()); +end. +``` + +已验证运行结果: + +- `type C = class(A, B)` 可以同时继承 `A` 和 `B` 的方法 +- 上述例子依次输出 `1`、`2` + +多重继承下的同名方法优先级: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Speak(); + begin + return 1; + end; +end; +type B = class + function Speak(); + begin + return 2; + end; +end; +type C = class(A, B) +end; +begin + obj := new C(); + WriteLn(obj.Speak()); +end. +``` + +已验证运行结果: + +- 当多个父类存在同名方法时,当前例子优先命中第一个父类 `A` +- 上述例子中的 `obj.Speak()` 输出 `1` + +基础 `virtual` / `override`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Animal = class + function Speak(); virtual; + begin + return 1; + end; +end; +type Dog = class(Animal) + function Speak(); override; + begin + return 2; + end; +end; +begin + d := new Dog(); + WriteLn(d.Speak()); +end. +``` + +已验证运行结果: + +- 父类 `virtual` + 子类 `override` 组合可以通过 +- 上述例子中的 `d.Speak()` 输出 `2` + +`class(BaseClass, ObjectName).MethodName()`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Speak(); virtual; + begin + return 1; + end; +end; +type B = class(A) + function Speak(); override; + begin + return 2; + end; +end; +begin + obj := new B(); + WriteLn(obj.Speak()); + WriteLn(class(A, obj).Speak()); +end. +``` + +已验证运行结果: + +- `obj.Speak()` 输出 `2` +- `class(A, obj).Speak()` 会定向调用祖先类方法,因此输出 `1` + +`FindClass("ClassName", obj)` 强制转型: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type ClassA = class + function Fuc(); virtual; + begin + return 1; + end; +end; +type ClassB = class(ClassA) + function Fuc(); override; + begin + return 2; + end; +end; +begin + objb := new ClassB(); + obj := FindClass("ClassA", objb); + WriteLn(obj.Fuc()); + WriteLn(obj is class(ClassA)); + WriteLn(obj is class(ClassB)); +end. +``` + +已验证运行结果: + +- `FindClass("ClassA", objb)` 会把 `objb` 转成 `ClassA` 视图 +- 上述例子中的 `obj.Fuc()` 输出 `1` +- 转型后的 `obj is class(ClassA)` 输出 `1` +- 转型后的 `obj is class(ClassB)` 输出 `0` + +`Inherited;`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Speak(); virtual; + begin + WriteLn(1); + end; +end; +type B = class(A) + function Speak(); override; + begin + Inherited; + WriteLn(2); + end; +end; +begin + obj := new B(); + obj.Speak(); +end. +``` + +已验证运行结果: + +- `Inherited;` 会先执行父类同名同参数方法 +- 上述例子依次输出 `1`、`2` + +`Inherited MethodName(...)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function BaseValue(x); + begin + WriteLn(x + 1); + end; +end; +type B = class(A) + function Run(); + begin + Inherited BaseValue(5); + WriteLn(9); + end; +end; +begin + obj := new B(); + obj.Run(); +end. +``` + +已验证运行结果: + +- `Inherited BaseValue(5)` 可以显式调用父类指定方法 +- 上述例子依次输出 `6`、`9` + +析构函数 `destroy`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type THuman = class + static mCount; + function create(); + begin + mCount := (mCount ?: 0) + 1; + end; + function destroy(); + begin + mCount--; + WriteLn(mCount); + end; + class function GetCount(); + begin + return mCount; + end; +end; +begin + h := new THuman(); + WriteLn(class(THuman).GetCount()); + h := nil; + WriteLn(class(THuman).GetCount()); +end. +``` + +已验证运行结果: + +- 创建对象后,`class(THuman).GetCount()` 输出 `1` +- `h := nil` 时会触发 `destroy()`,中途输出 `0` +- 释放后再次读取 `class(THuman).GetCount()` 也输出 `0` + +`self(0)` / `self(1)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type BaseBox = class + function MakeOwner(); + begin + return self(1); + end; + function MakeBase(); + begin + return self(0); + end; +end; +type ChildBox = class(BaseBox) +end; +begin + c := new ChildBox(); + a := c.MakeOwner(); + b := c.MakeBase(); + WriteLn(a is class(ChildBox)); + WriteLn(b is class(ChildBox)); +end. +``` + +已验证运行结果: + +- `self(1)` 返回的对象在这个例子里是 `ChildBox`,因此输出 `1` +- `self(0)` 返回的对象在这个例子里不是 `ChildBox`,因此输出 `0` + +`unit` 中的嵌套类路径创建,因为依赖多文件环境,这里用 `text` 展示: + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// Unit1.tsf +unit Unit1; +interface +type Class1 = class + type Class2 = class + value; + end; +end; +implementation +end. + +// main.tsl +program test; +begin + obj := CreateObject("Unit1.Class1.Class2"); + obj.value := 42; + WriteLn(obj.value); +end. +``` + +已验证运行结果: + +- `CreateObject("Unit1.Class1.Class2")` 可以创建对象 +- 上述例子中的 `obj.value` 输出 `42` + +继承单元中的嵌套类路径,因为依赖多文件环境,这里也用 `text` 展示: + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// Unit1.tsf +unit Unit1; +interface +type Class1 = class + type Class2 = class + value; + end; +end; +implementation +end. + +// main.tsl +program test; +type MyNewClass = class(Unit1.Class1.Class2) +end; +begin + obj := CreateObject("MyNewClass"); + obj.value := 42; + WriteLn(obj.value); +end. +``` + +已验证运行结果: + +- `type MyNewClass = class(Unit1.Class1.Class2)` 可以通过并继承该路径类 +- 上述例子中的 `obj.value` 输出 `42` + +能力探测: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$IFDEF ParentClassInUnit} + WriteLn(1); +{$ELSE} + WriteLn(0); +{$ENDIF} +end. +``` + +已验证运行结果: + +- 当前环境里 `{$IFDEF ParentClassInUnit}` 输出 `1` + +## 最小可编译示例 + +如果你只是想先起一个最短类骨架,直接复用本页开头的“最短类骨架”。 + +代码块身份:已验证可执行示例 + +```tsl +type Person = class +end; +``` + +## 常见误写 + +- 以下误写中,有代码块的条目都已经单独验证;没有单独代码块展开的文字条目,属于已知语义陷阱或错误泛化,不要把它们当成可写事实。 +- 把类写成裸 `class Person`。 +- 还没建立类定义就直接写 `CreateObject("Person")` 或 `new Person()`。 +- 把 `MathBox.Add(...)` 这种裸类名调用直接当成当前解释器已验证的类方法调用写法。 +- 把 `THuman.mCount` 这种裸类名静态字段访问直接当成当前解释器已验证事实。 +- 把 `self()` 当成当前解释器已验证的工厂式写法。 +- 把 `private` / `protected create` 当成当前解释器一定会自动执行的构造函数。 +- 在子类里把父类 `private` 成员当成 `protected` 成员来访问。 +- 把带命名空间的 `new a.b.c` 直接当成当前解释器已支持事实。 +- 把 `class(Unit1.Class1.Class2)` 这种表达式写法直接当成当前解释器已验证事实。 +- 以为类声明既然能放在松散语句后面,就还能在 `type` 后面继续回到松散语句模式。 + +代码块身份:反例 / 不可照写 + +```text +obj := new Unit1.Class1.Class2(); +``` + +上面这种写法在当前已记录验证里没有通过;当前只把 `CreateObject("Unit1.Class1.Class2")` 这种路径创建写成已验证事实。 + +代码块身份:反例 / 不可照写 + +```text +cls := class(Unit1.Class1.Class2); +``` + +上面这种表达式写法在当前解释器里没有通过;当前只把继承声明里的 `class(Unit1.Class1.Class2)` 和字符串路径创建写成已验证事实。 + +代码块身份:反例 / 不可照写 + +```text +MathBox.Add(1, 2); +``` + +上面这种裸类名调用在当前解释器里没有通过;当前已验证可用的是先拿到类类型,再用 `class(MathBox).Add(...)` 或 `FindClass("MathBox").Add(...)` 调用。 + +代码块身份:反例 / 不可照写 + +```text +THuman.mCount := 7; +``` + +上面这种裸类名静态字段访问在当前解释器里没有通过;当前已验证可用的是 `class(THuman).mCount`。 + +代码块身份:反例 / 不可照写 + +```text +self(); +``` + +上面这种无参工厂式 `self()` 在当前解释器里没有通过;当前只把 `self` 实例引用,以及 `self(0)` / `self(1)` 写成已验证事实。 + +代码块身份:反例 / 不可照写 + +```text +a := 1; +type MyClass = class + value; +end; +WriteLn(a); +``` + +上面这种写法在当前解释器里没有通过,会报 `invalid statement`。当前只把“松散语句后面可以接顶层类声明”写成已验证事实,不把它泛化成“`type` 之后还能继续写松散语句”。 + +## 跳转指引 + +- 回看 unit 与作用域:见 [10_units_and_scope.md](10_units_and_scope.md) +- 最后统一扫坑:见 [12_pitfalls.md](12_pitfalls.md) +- 继续看对象运行时和更深对象能力:见 [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) 和 [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) diff --git a/docs/tsl/syntax/10_units_and_scope.md b/docs/tsl/syntax/10_units_and_scope.md new file mode 100644 index 00000000..2cbe559f --- /dev/null +++ b/docs/tsl/syntax/10_units_and_scope.md @@ -0,0 +1,409 @@ +# Units And Scope + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)(优先)、[03_core_model.md](03_core_model.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 10 篇,共 32 篇。上一篇:[09_objects_and_classes.md](09_objects_and_classes.md)。下一篇:[11_runtime_context_and_with.md](11_runtime_context_and_with.md)。 + +这一篇只讲“怎么写和怎么调用 `unit`”。`namespace`、查找路径、`unit` 生命周期、`tsl.conf` 与运行时入口统一放到 [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)。 + +## 这一篇解决什么问题 + +回答下面几类最常见的问题: + +- 什么时候该把一组函数写成 `unit` +- `uses` 到底能放在哪里 +- `interface uses` 和 `implementation uses` 的可见性差别是什么 +- 多个 `unit` 里有同名接口时,未限定调用到底命中谁 +- 怎样显式指定要调用哪个 `unit` 的接口 + +## 必须记住的规则 + +- `unit` 是完整的顶层主体;常见完整形态是 `unit Name; interface ... implementation ... end.`。 +- `unit` 也可以省略 `interface` / `implementation` 写成简写形态;当前解释器下,这种简写里定义的函数对外可调用。 +- 如果没有特殊需求,默认优先用完整形态;简写形态只在不需要显式区分 `interface` / `implementation` 时再用。 +- 顶层 `uses` 可以放在文件最前面,让后续整个文件直接看到被引入 `unit` 的接口。 +- 当前解释器允许连续多条顶层 `uses`;真正会失败的是前面已经出现普通语句后,再写顶层 `uses`。 +- 函数体里的 `uses` 必须是函数体第一条语句,而且一个函数体里只能写一次。 +- 类定义体里的 `uses` 必须是类定义体第一条语句,而且一个类定义体里只能写一次。 +- `interface uses` 对整个 `unit` 可见;`implementation uses` 只对实现段和在实现段里定义的方法体可见。 +- 只写在 `implementation` 里的函数,对 `unit` 外部不可见。 +- 出现重名接口时,未限定调用按 `uses` 从后往前解析;最后一个 `uses` 的同名接口优先。 +- 要显式指定某个 `unit` 的接口,可以用 `UnitA.Ping()`、`unit(UnitA).Ping()` 或 `call("UnitA.Ping")`。 +- `unit` 生命周期、接口状态、命名空间和查找路径细节,转去看 [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)。 + +## 已验证语法 + +### 最小 `unit` + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface +function Ping(); +implementation +function Ping(); +begin + return 1; +end; +end. +``` + +已验证结果: + +- 上面这就是当前解释器可通过的最小完整 `unit` 骨架。 +- `unit` 文件结尾要用 `end.`,不是普通函数或类的 `end;`。 + +### 简写 `unit` + +代码块身份:已验证可执行示例 + +```tsl +unit SpecialUnit; + +function Abcd(); +begin + return 10; +end; + +function Abcd2(); +begin + return 20; +end; + +initialization + Writeln("INIT"); + +finalization + Writeln("FINAL"); + +end. +``` + +已验证结果: + +- `unit SpecialUnit;` 后可以省略 `interface` / `implementation`。 +- 这种简写形态里定义的 `Abcd()`、`Abcd2()` 外部可以直接调用。 +- 简写 `unit` 里同样可以写 `initialization` 和 `finalization`。 + +### 顶层、函数体、类体里的 `uses` + +沿用同一个 `DemoUnit.tsf`,分别看顶层、函数体、类体三种 `uses` 位置: + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// DemoUnit.tsf +unit DemoUnit; +interface +function Ping(); +implementation +function Ping(); +begin + return 11; +end; +end. + +// main.tsl +program test; +uses DemoUnit; +function RunInFunction(); +begin + uses DemoUnit; + return Ping(); +end; +type Worker = class + uses DemoUnit; + function Run(); + begin + return Ping(); + end; +end; +begin + obj := new Worker(); + WriteLn(Ping()); + WriteLn(RunInFunction()); + WriteLn(obj.Run()); +end. + +// command +tsl .\main.tsl -LIBPATH "D:\path\to\dir\" +``` + +已验证结果: + +- 顶层 `uses DemoUnit;` 后,脚本主体可以直接调用 `Ping()`。 +- 函数体第一行写 `uses DemoUnit;` 后,`RunInFunction()` 输出 `11`。 +- 类定义体第一行写 `uses DemoUnit;` 后,`obj.Run()` 也输出 `11`。 +- 这一类多文件场景依赖真实查找路径;如果 `DemoUnit.tsf` 所在目录不在查找路径里,脚本仍会找不到对应接口。 + +### `uses` 的位置限制 + +代码块身份:反例 / 不可照写 + +```text +// 顶层前面已经有普通语句 +a := 1; +uses DemoUnit; + +// 函数里不是第一行 +function Run(); +begin + a := 1; + uses DemoUnit; + return Ping(); +end; + +// 函数里写两次 +function Run(); +begin + uses UnitA; + uses UnitB; + return Ping(); +end; + +// 类里不是第一行 +type Worker = class + value; + uses DemoUnit; +end; + +// 类里写两次 +type Worker = class + uses UnitA; + uses UnitB; +end; +``` + +已验证结果: + +- 顶层前面如果已经出现 `a := 1;` 这类普通语句,再写顶层 `uses` 会报 `invalid statement`。 +- 函数体里,`uses` 不是第一行或者重复出现,都会失败。 +- 类定义体里,`uses` 不是第一行或者重复出现,都会失败。 +- 当前解释器允许连续多条顶层 `uses`,所以“顶层只能写一条 `uses`”不是已验证事实。 + +### `interface uses` 和 `implementation uses` + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// UnitB.tsf +unit UnitB; +interface +function FB(); +implementation +function FB(); +begin + return 100; +end; +end. + +// UnitC.tsf +// 与 UnitB.tsf 同形,只把 FB / 100 改成 FC / 200 + +// UnitA.tsf +unit UnitA; +interface +uses UnitB; +type TBox = class + function FromInterface(); + begin + return FB(); + end; + function FromImplementation(); +end; +function CallB(); +function CallC(); +implementation +uses UnitC; +function TBox.FromImplementation(); +begin + return FC(); +end; +function CallB(); +begin + return FB(); +end; +function CallC(); +begin + return FC(); +end; +end. + +// main.tsl +program test; +uses UnitA; +begin + obj := new TBox(); + WriteLn(CallB()); + WriteLn(CallC()); + WriteLn(obj.FromInterface()); + WriteLn(obj.FromImplementation()); +end. +``` + +已验证结果: + +- `interface uses UnitB;` 后,`FB()` 对整个 `unit` 都可见,`CallB()` 输出 `100`。 +- `implementation uses UnitC;` 后,`FC()` 对实现段函数和在实现段定义的方法体可见,`CallC()` 与 `obj.FromImplementation()` 都输出 `200`。 +- 接口段里的内联方法 `FromInterface()` 能访问 `interface uses` 引入的接口,因此输出 `100`。 +- 当前解释器没有让接口段里的内联方法看到只在 `implementation uses` 引入的接口。 + +### 实现段私有函数 + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// PrivateDemo.tsf +unit PrivateDemo; +interface +function PublicFunc(); +implementation +function PublicFunc(); +begin + return PrivateFunc(); +end; +function PrivateFunc(); +begin + return 77; +end; +end. + +// main.tsl +program test; +uses PrivateDemo; +begin + WriteLn(PublicFunc()); + WriteLn(PrivateFunc()); +end. +``` + +已验证结果: + +- `PublicFunc()` 输出 `77`,说明接口函数可以调用实现段私有函数。 +- 外部直接调用 `PrivateFunc()` 时,会报 `function:PrivateFunc compile error or not found`。 + +### 重名解析与限定调用 + +重名函数最小对照: + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// UnitA.tsf +unit UnitA; +interface +function Ping(); +function Hello(); +implementation +function Ping(); +begin + return 101; +end; +function Hello(); +begin + return 111; +end; +end. + +// UnitB.tsf +// 与 UnitA.tsf 同形,只把 101 / 111 改成 202 / 222 + +// main.tsl +uses UnitA, UnitB; +WriteLn(Ping()); +WriteLn(UnitA.Hello()); +WriteLn(UnitB.Hello()); +WriteLn(unit(UnitA).Ping()); +WriteLn(call("UnitB.Ping")); +``` + +已验证结果: + +- 未限定的 `Ping()` 输出 `202`,说明当前解析顺序是 `uses` 从后往前。 +- `UnitA.Hello()` 输出 `111`,`UnitB.Hello()` 输出 `222`。 +- `unit(UnitA).Ping()` 输出 `101`。 +- `call("UnitB.Ping")` 输出 `202`。 + +重名类最小对照: + +代码块身份:配置片段 / 概念骨架 +代码块说明:已在多文件环境下验证;这里只用来展示结构和结果,不是可直接复制的单文件最小示例。 + +```text +// UnitA.tsf +unit UnitA; +interface +type Box = class + value; + function Create(); + begin + value := 101; + end; +end; +implementation +end. + +// UnitB.tsf +// 与 UnitA.tsf 同形,只把 Create() 里写入的 101 改成 202 + +// main.tsl +uses UnitA, UnitB; +obj := new Box(); +WriteLn(obj.value); +objA := CreateObject("UnitA.Box"); +WriteLn(objA.value); +objB := CreateObject("UnitB.Box"); +WriteLn(objB.value); +``` + +已验证结果: + +- 未限定的 `new Box()` 输出 `202`。 +- `CreateObject("UnitA.Box")` 输出 `101`。 +- `CreateObject("UnitB.Box")` 输出 `202`。 +- 重名类的未限定解析顺序和重名函数一致,也是按 `uses` 从后往前。 + +## 最小可编译示例 + +如果你只是要先写出一个最小、可被其他文件引用的 `unit`,从下面这个骨架起步: + +代码块身份:已验证可执行示例 + +```tsl +unit DemoUnit; +interface +function Ping(); +implementation +function Ping(); +begin + return 1; +end; +end. +``` + +后面的多文件片段只在需要 `uses`、可见性或重名解析时再回来看。 + +## 常见误写 + +- 把依赖外部 `unit` 的 `uses` 例子误当成单文件最小示例。 +- 在还没把目标 `unit` 放进查找路径前,就把“找不到接口”误判成 `uses` 语法错。 +- 把函数体或类定义体里的 `uses` 写在第一条语句之后。 +- 在同一个函数体或类定义体里重复写第二个 `uses`。 +- 把“顶层 `uses` 只能写一次”当成当前解释器规则。 +- 把重名接口的未限定解析顺序理解成“从前到后”。 +- 忘了显式指定 `UnitA.Ping()`、`unit(UnitA).Ping()` 或 `call("UnitA.Ping")`,结果误调用到最后一个 `uses` 的同名接口。 + +## 跳转指引 + +- 回看文件与顶层主体:见 [03_core_model.md](03_core_model.md) +- 查看 `unit` 生命周期、命名空间与查找路径:见 [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) +- 继续看对象运行时:见 [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) diff --git a/docs/tsl/syntax/11_runtime_context_and_with.md b/docs/tsl/syntax/11_runtime_context_and_with.md new file mode 100644 index 00000000..29c95bd4 --- /dev/null +++ b/docs/tsl/syntax/11_runtime_context_and_with.md @@ -0,0 +1,163 @@ +# Runtime Context And With + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[07_expressions_and_operators.md](07_expressions_and_operators.md)、[22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)、[../finance/market_data_context.md](../finance/market_data_context.md) + +手册位置:第 11 篇,共 32 篇。上一篇:[10_units_and_scope.md](10_units_and_scope.md)。下一篇:[12_pitfalls.md](12_pitfalls.md)。 + +这一篇只处理运行时环境参数和 `with` 后缀,不处理任何金融业务语义。 + +## 这一篇解决什么问题 + +回答“`SetSysParam` / `GetSysParam` 怎样用、`SysParams[...]` 是什么、`#Func() with array(...)` 这种后缀环境调用在当前解释器里怎样写”。 + +## 必须记住的规则 + +- TSL 有一组运行时系统参数;当前页只写已经实际验证过的通用写法。 +- 已验证:`SetSysParam(key, value)` 和 `GetSysParam(key)` 可以直接用字符串键。 +- 已验证:`SysParams[key]` 可以直接读写这些运行时参数。 +- 当前已验证的 `with` 形式,是写在函数文件调用后面:`#Func() with array(...)`。 +- 当前已做双文件运行验证:`with array(...)` 只在该次调用里临时覆盖对应键,调用结束后会恢复外部原值。 +- 当前已做双文件运行验证:如果外部原值本来不存在,`with array(...)` 调用结束后,对应键会恢复成 `nil`。 +- 不要把上面的后缀 `with` 直接泛化成“任何本地函数调用后面都能接 `with array(...)`”;这一点当前没有通过。 +- 当前页只收通用键的例子;像 `pn_stock()`、`pn_date()` 这类金融上下文参数,统一放到业务层文档里解释。 + +## 已验证语法 + +直接设置和读取系统参数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SetSysParam("a", 123); + SetSysParam("b", "XYZ"); + WriteLn(GetSysParam("a")); + WriteLn(GetSysParam("b")); +end. +``` + +已验证运行结果: + +- 依次输出 `123`、`XYZ` + +`SysParams[...]` 直接读写: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SysParams["a"] := 321; + SysParams["b"] := "QQ"; + WriteLn(SysParams["a"]); + WriteLn(SysParams["b"]); + WriteLn(GetSysParam("a")); +end. +``` + +已验证运行结果: + +- 依次输出 `321`、`QQ`、`321` +- 说明 `SysParams[...]` 和 `GetSysParam(...)` / `SetSysParam(...)` 指向的是同一组运行时环境参数 + +沿用同一个 `TestDo.tsf`,看 `with array(...)` 的覆盖边界: + +代码块身份:配置片段 / 概念骨架 + +```text +// TestDo.tsf +function TestDo(); +begin + return array(GetSysParam("a"), GetSysParam("b")); +end; + +// main.tsl +program test; +begin + SetSysParam("a", 7); + SetSysParam("b", 8); + r := #TestDo() with array("a": 101, "b": 202); + WriteLn(r[0]); + WriteLn(r[1]); + WriteLn(GetSysParam("a")); + WriteLn(GetSysParam("b")); +end. + +// command +tsl .\main.tsl -LIBPATH "D:\path\to\dir\" +``` + +已验证运行结果: + +- `r[0]` 输出 `101` +- `r[1]` 输出 `202` +- 调用结束后,外层 `GetSysParam("a")` 输出 `7` +- 调用结束后,外层 `GetSysParam("b")` 输出 `8` +- 说明 `with array(...)` 是“只在该次调用里临时覆盖,再恢复外部原值” + +沿用上一个 `TestDo.tsf`,只把 `main.tsl` 改成下面这样: + +代码块身份:配置片段 / 概念骨架 + +```text +// main.tsl +program test; +begin + r := #TestDo() with array("a": 101, "b": 202); + WriteLn(r[0]); + WriteLn(r[1]); + WriteLn(GetSysParam("a") = nil); + WriteLn(GetSysParam("b") = nil); +end. +``` + +已验证运行结果: + +- 依次输出 `101`、`202`、`1`、`1` +- 说明外层原值不存在时,调用后不是“泄露”成 `101` / `202`,而是恢复成 `nil` + +## 最小可编译示例 + +如果你只是想先记住最小的运行时环境入口,用这个: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SetSysParam("a", 1); + WriteLn(GetSysParam("a")); +end. +``` + +## 常见误写 + +- 把系统参数页直接写成金融函数页。 +- 把 `#Func() with array(...)` 误判成也能直接套在本地函数 `Demo()` 后面。 +- 以为 `with array(...)` 改的是全局永久值,不会恢复外层原环境。 + +代码块身份:反例 / 不可照写 + +```text +program test; +function Demo(); +begin + return GetSysParam("a"); +end; +begin + r := Demo() with array("a": 11); +end. +``` + +上面这种“本地函数后缀 `with`”写法在当前解释器里没有通过,会报 `Statement missing terminator`,随后出现 `function compile error`。 + +## 跳转指引 + +- 回看表达式与调用:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 涉及函数文件查找路径:见 [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) +- 业务层环境参数:见 [../finance/index.md](../finance/index.md) diff --git a/docs/tsl/syntax/12_pitfalls.md b/docs/tsl/syntax/12_pitfalls.md new file mode 100644 index 00000000..54af8021 --- /dev/null +++ b/docs/tsl/syntax/12_pitfalls.md @@ -0,0 +1,271 @@ +# Pitfalls + +文档类型:反例索引页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:是 +遇到不确定时跳转到:[03_core_model.md](03_core_model.md)、[06_functions_and_calls.md](06_functions_and_calls.md)、[09_objects_and_classes.md](09_objects_and_classes.md) + +手册位置:第 12 篇,共 32 篇。上一篇:[11_runtime_context_and_with.md](11_runtime_context_and_with.md)。下一篇:[13_matrix_and_collections.md](13_matrix_and_collections.md)。 + +这一篇不讲新知识,只做反例索引。 + +## 这一篇解决什么问题 + +回答“哪些写法最容易凭直觉写出来,但在 TSL 里会编译失败、运行出错,或语义并不可靠”。 + +## 这页怎么用 + +- 先按主题扫一遍,再回到对应正文看正确写法。 +- 这里不重复讲完整规则,只保留“错法 -> 正确页”的索引。 +- 只有已经单独验证过的误写,才会列在这里。 + +## 已验证反例索引 + +### 文件模型与基础值 + +#### 1. 把裸 `class Name` 当成顶层类声明 + +代码块身份:反例 / 不可照写 + +```text +class Person +end; +``` + +这会编译失败。正确页:见 [09_objects_and_classes.md](09_objects_and_classes.md) + +#### 2. 把 `=` 当成赋值 + +代码块身份:反例 / 不可照写 + +```text +a = 1; +``` + +这会编译失败。正确页:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) + +#### 3. 把字符串当成 0 基下标 + +代码块身份:反例 / 不可照写 + +```text +s := "ABC"; +WriteLn(s[0]); +``` + +这会在运行时报字符串下标越界。正确页:见 [04_values_and_literals.md](04_values_and_literals.md) + +#### 4. 把普通字符串里的 `"\uXXXX"` 直接当成和 `L"\uXXXX"` 一样的单字符宽串 + +代码块身份:反例 / 不可照写 + +```text +WriteLn(Length("\u0041")); +WriteLn(Length(L"\u0041")); +``` + +这不是同一件事。当前解释器里前者输出 `2`,后者输出 `1`。正确页:见 [04_values_and_literals.md](04_values_and_literals.md) + +#### 5. 把 `U""` 误当成和 `L""` 一样的宽串 + +代码块身份:反例 / 不可照写 + +```text +WriteLn(IfWString(U"\u5929\u8F6F")); +WriteLn(IfWString(L"\u5929\u8F6F")); +``` + +这不是同一回事。当前解释器里前者输出 `0`,后者输出 `1`。正确页:见 [04_values_and_literals.md](04_values_and_literals.md) + +#### 6. 把带 `#0` / `\0` 的字符串当成会自动截断的零结尾串 + +代码块身份:反例 / 不可照写 + +```text +s := "A"#0"B"; +WriteLn(Length(s)); +``` + +这不要按 C 风格字符串去理解。当前解释器里这里输出 `3`,说明 `#0` 仍是字符串内容的一部分。正确页:见 [04_values_and_literals.md](04_values_and_literals.md) + +#### 7. 把顶层函数定义和松散语句混写 + +代码块身份:反例 / 不可照写 + +```text +function Add(a, b); +begin + return a + b; +end; + +value := Add(1, 2); +``` + +这会编译失败。正确页:见 [03_core_model.md](03_core_model.md) + +#### 8. 顶层单独写 `const Name = value;` + +代码块身份:反例 / 不可照写 + +```text +const value = 1; +``` + +这在当前解释器里会编译失败。正确页:见 [05_variables_and_constants.md](05_variables_and_constants.md) + +### 函数与调用 + +#### 9. 把 `a = 1` 当成命名参数 + +代码块身份:反例 / 不可照写 + +```text +Pack(a = 1, b = 2) +``` + +这不要当成可靠的命名参数写法。它虽然可能编译通过,但实测返回结果不对。正确页:见 [06_functions_and_calls.md](06_functions_and_calls.md) + +#### 10. 把 `like` 当成 SQL `%` / `_` 通配 + +代码块身份:反例 / 不可照写 + +```text +WriteLn("abc" like "a%"); +``` + +这在当前解释器里输出 `0`,不要按 SQL `LIKE` 去理解。当前手册里,`like` 的右侧按正则模式解释。正确页:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) + +#### 11. 把普通函数默认参数规则直接套到 `unit interface` 的 `const` 默认参数 + +代码块身份:反例 / 不可照写 + +```text +unit UnitConst; +interface +const CS = 888; +function F(a, b = 100, c = CS); +``` + +这不要直接当成已经等价于普通函数默认参数规则的写法。在当前解释器里,对应的 `F(1)` 实测输出是 `101`,不是按 `CS = 888` 补值。正确页:见 [06_functions_and_calls.md](06_functions_and_calls.md) 和 [10_units_and_scope.md](10_units_and_scope.md) + +#### 12. 把 `external` 后面的 DLL 名直接写成字符串拼接表达式 + +代码块身份:反例 / 不可照写 + +```text +function TickFromExpr(): int64; stdcall; external "kernel32"$"."$"dll" name "GetTickCount64"; +``` + +这会编译失败,错误是 `dll filename const string not found after external`。正确页:见 [06_functions_and_calls.md](06_functions_and_calls.md) + +### Unit 与查找路径 + +#### 13. 把“文件就在当前目录”当成当前命令行解释器已经能找到对应 `unit` / `.tsf` + +代码块身份:反例 / 不可照写 + +```text +program test; +uses DemoUnit; +begin + WriteLn(Ping()); +end. +``` + +如果 `DemoUnit.tsf` 所在目录没有进入 `-LIBPATH`、`tsl.conf` 的 `Libpath=` 或运行时查找路径,上面这种写法虽然语法能过,但运行时仍然找不到 `Ping()`。正确页:见 [10_units_and_scope.md](10_units_and_scope.md) + +#### 14. 把函数体或类定义体里的 `uses` 写在第一条语句之后,或在同一作用域里重复写第二个 `uses` + +代码块身份:反例 / 不可照写 + +```text +function Run(); +begin + a := 1; + uses DemoUnit; + return Ping(); +end; + +type Worker = class + uses UnitA; + uses UnitB; +end; +``` + +上面这两类写法都没有通过。函数里的错法会报 `invalid statement`,类里的错法会报 `invalid class definition`。正确页:见 [10_units_and_scope.md](10_units_and_scope.md) + +#### 15. 把限定读取 `DemoUnit.VarName` 误当成也支持限定赋值 + +代码块身份:反例 / 不可照写 + +```text +DemoUnit.UnitCounter := 13; +``` + +这在当前解释器里会编译失败,错误是左值不可赋值。正确页:见 [10_units_and_scope.md](10_units_and_scope.md) + +### 类与对象 + +#### 16. 把裸类名当成 `class function` 或静态字段的直接访问入口 + +代码块身份:反例 / 不可照写 + +```text +MathBox.Add(1, 2); + +THuman.mCount := 7; +``` + +这两种写法在当前解释器里都没有通过。当前已验证可用的是先拿到类类型,再用 `class(MathBox).Add(...)` / `FindClass("MathBox").Add(...)` 调类方法,以及 `class(THuman).mCount` 访问静态字段。正确页:见 [09_objects_and_classes.md](09_objects_and_classes.md) + +#### 17. 把 `private` / `protected create` 当成一定会执行的构造函数 + +代码块身份:反例 / 不可照写 + +```text +program test; +type A = class +public + value; +private + function create(v); + begin + self.value := v; + end; +end; +begin + a := new A(111); + WriteLn(a.value); +end. +``` + +这不会报“不能创建对象”,但 `create` 不会执行;上面的 `a.value` 实测输出 ``。正确页:见 [09_objects_and_classes.md](09_objects_and_classes.md) + +#### 18. 在子类里把父类 `private` 成员当成 `protected` 成员用 + +代码块身份:反例 / 不可照写 + +```text +program test; +type A = class +private + secret; +end; +type B = class(A) +public + function SetSecret(v); + begin + self.secret := v; + end; +end; +``` + +这会在执行时报对象成员访问错误。正确页:见 [09_objects_and_classes.md](09_objects_and_classes.md) + +## 跳转指引 + +- 整体读法:见 [01_introduction.md](01_introduction.md) +- 函数写法:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- unit / uses:见 [10_units_and_scope.md](10_units_and_scope.md) +- 类写法:见 [09_objects_and_classes.md](09_objects_and_classes.md) diff --git a/docs/tsl/syntax/13_matrix_and_collections.md b/docs/tsl/syntax/13_matrix_and_collections.md new file mode 100644 index 00000000..90151530 --- /dev/null +++ b/docs/tsl/syntax/13_matrix_and_collections.md @@ -0,0 +1,101 @@ +# Matrix And Collections + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[14_resultset_and_filters.md](14_resultset_and_filters.md)、[26_matrix_deep_dive.md](26_matrix_deep_dive.md)、[27_fmarray.md](27_fmarray.md) + +手册位置:第 13 篇,共 32 篇。上一篇:[12_pitfalls.md](12_pitfalls.md)。下一篇:[14_resultset_and_filters.md](14_resultset_and_filters.md)。 + +这一篇收拢 `array(...)` 的扩展用法:顺序数组、字符串键表、嵌套数组,以及已经在当前解释器下单独验证过的矩阵样比较。 + +## 这一篇解决什么问题 + +回答“`array(...)` 在 TSL 里除了最普通的一维数组,还能怎样组织数据;哪些矩阵样写法已经稳定验证过”。 + +## 必须记住的规则 + +- `array(...)` 既可以写顺序数组,也可以写字符串键表。 +- 顺序数组下标从 `0` 开始;字符串仍然从 `1` 开始。 +- `array(...)` 可以继续嵌套,形成二维或矩阵样数据。 +- 当前解释器接受矩阵链式比较 `::>`、`::<`、`::<>`、`::==`、`::>=`、`::<=`。 +- 当前这篇只收已经单独验证过的数组 / 键表 / 矩阵样主干,不把结果集过滤和 TS-SQL 混进来。 + +## 已验证语法 + +顺序数组与字符串键表: + +代码块身份:已验证可执行示例 + +```tsl +arr := array(10, 20, 30); +hash := array("Code": "0001", "Price": 12.3); +WriteLn("ARR0=", arr[0]); +WriteLn("ARR1=", arr[1]); +WriteLn("HASH=", hash["Code"]); +``` + +已验证运行结果对应关系: + +- `arr[0] = 10` +- `arr[1] = 20` +- `hash["Code"] = "0001"` + +嵌套数组: + +代码块身份:已验证可执行示例 + +```tsl +[r1, r2] := array((1, 2), (3, 4)); +WriteLn(r1[0]); +WriteLn(r1[1]); +WriteLn(r2[0]); +WriteLn(r2[1]); +``` + +已验证运行结果: + +- 依次输出 `1`、`2`、`3`、`4` +- 说明 `array((1, 2), (3, 4))` 这种嵌套数组写法可以稳定通过,并可按普通数组继续读取 + +矩阵链式比较: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + r := array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1); + WriteLn(r[0]); + WriteLn(r[1]); + WriteLn(r[2]); + s := array(1, 2, -1) ::< 2 ::< array(3, 2, 1); + WriteLn(s[0]); + WriteLn(s[1]); + WriteLn(s[2]); +end. +``` + +已验证运行结果: + +- `array(1, 2, -1) ::< array(2, 1, 0) ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`1` +- `array(1, 2, -1) ::< 2 ::< array(3, 2, 1)` 的三个元素依次输出 `1`、`0`、`0` +- 说明矩阵链式比较会按元素位置分别得到结果数组,并且可以和标量混用 + +## 暂不在本页展开的部分 + +- 专门的结果集过滤函数 +- TS-SQL 查询与写回 +- 更大范围的矩阵函数族 + +这些内容会继续收拢到后面的进阶专题,而不是再外跳到旧目录。 + +## 跳转指引 + +- 回看基础值与索引:见 [04_values_and_literals.md](04_values_and_literals.md) +- 回看表达式层比较:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 进入结果集过滤:见 [14_resultset_and_filters.md](14_resultset_and_filters.md) +- 进入集合运算专题:见 [25_set_operations.md](25_set_operations.md) +- 进入矩阵深水专题:见 [26_matrix_deep_dive.md](26_matrix_deep_dive.md) +- 进入 `FMArray`:见 [27_fmarray.md](27_fmarray.md) diff --git a/docs/tsl/syntax/14_resultset_and_filters.md b/docs/tsl/syntax/14_resultset_and_filters.md new file mode 100644 index 00000000..ff2019c4 --- /dev/null +++ b/docs/tsl/syntax/14_resultset_and_filters.md @@ -0,0 +1,209 @@ +# Result Sets And Filters + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[13_matrix_and_collections.md](13_matrix_and_collections.md)、[15_ts_sql.md](15_ts_sql.md)、[25_set_operations.md](25_set_operations.md) + +手册位置:第 14 篇,共 32 篇。上一篇:[13_matrix_and_collections.md](13_matrix_and_collections.md)。下一篇:[15_ts_sql.md](15_ts_sql.md)。 + +这一篇只讲结果集过滤语法:怎样按某一列过滤、怎样按整行过滤、怎样只返回行下标,以及怎样按字段列表过滤。它不负责 TS-SQL 查询语法,也不把集合运算和业务选股逻辑混进来。 + +## 这一篇解决什么问题 + +回答“我已经有一个数组或二维结果集,想按某个过滤集保留命中的行、排除命中的行,或者只拿到符合条件的行下标时,应该怎么写”。 + +## 必须记住的规则 + +- 结果集过滤主函数是 `FilterIn(...)` 和 `FilterNotIn(...)`。 +- `FilterIn(R, FilterArray, Field)` 返回命中的子结果集;`FilterNotIn(...)` 返回未命中的子结果集。 +- 第四个参数写成 `false` 时,返回值不再是子结果集,而是符合条件的行下标数组。 +- `Field` 写成字符串时,表示按某一列过滤。 +- `Field` 写成 `nil` 时,表示按整行过滤;一维数组也走这个入口。 +- `Field` 写成 `array("A", "B")` 这类字段名数组时,表示只按这些列做匹配。 +- 过滤运算不会自动去重;原结果集里有重复行时,命中的重复行会原样保留下来。 +- 去重型的并、交、差运算不放在这一篇,见 [25_set_operations.md](25_set_operations.md)。 + +## 已验证语法 + +### 按单列过滤 + +按 `"Code"` 列做包含与排除: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + R := array( + ("Code": "0001", "V1": 8.9, "V2": 12), + ("Code": "0002", "V1": 9, "V2": 10), + ("Code": "0003", "V1": 8, "V2": 8), + ("Code": "0004", "V1": 1, "V2": 2) + ); + CodeArr := array("0001", "0003"); + KeepRows := FilterIn(R, CodeArr, "Code"); + DropRows := FilterNotIn(R, CodeArr, "Code"); +end. +``` + +已验证运行结果: + +- `FilterIn(R, CodeArr, "Code")` 返回两行:`0001`、`0003` +- `FilterNotIn(R, CodeArr, "Code")` 返回两行:`0002`、`0004` + +### 返回行下标 + +第四个参数写成 `false` 时,返回行下标而不是子结果集: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + R := array( + ("Code": "0001", "V1": 8.9, "V2": 12), + ("Code": "0002", "V1": 9, "V2": 10), + ("Code": "0003", "V1": 8, "V2": 8), + ("Code": "0004", "V1": 1, "V2": 2) + ); + CodeArr := array("0001", "0003"); + KeepIndex := FilterIn(R, CodeArr, "Code", false); + DropIndex := FilterNotIn(R, CodeArr, "Code", false); +end. +``` + +已验证运行结果: + +- `FilterIn(R, CodeArr, "Code", false)` 返回 `array(0, 2)` +- `FilterNotIn(R, CodeArr, "Code", false)` 返回 `array(1, 3)` + +这些下标可以直接继续拿去切子结果集: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + R := array( + ("Code": "0001", "V1": 8.9, "V2": 12), + ("Code": "0002", "V1": 9, "V2": 10), + ("Code": "0003", "V1": 8, "V2": 8), + ("Code": "0004", "V1": 1, "V2": 2) + ); + CodeArr := array("0001", "0003"); + KeepIndex := FilterIn(R, CodeArr, "Code", false); + Picked := R[KeepIndex, array("Code", "V1")]; +end. +``` + +### `Field = nil` 时按整行过滤 + +整行过滤与一维数组过滤都走 `Field = nil`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + R := array( + ("A": 1, "B": 2, "C": 3), + ("A": 2, "B": 3, "C": 4), + ("A": 1, "B": 2, "C": 3), + ("A": 4, "B": 5, "C": 6), + ("A": 4, "B": 5, "C": 6) + ); + R1 := array( + ("A": 1, "B": 2, "C": 3), + ("A": 2, "B": 3, "C": 4) + ); + KeepRows := FilterIn(R, R1, nil); + LeftOnly := FilterNotIn(array(1, 2, 3, 4, 5, 5, 6, 7), array(1, 2, 3, 4), nil); +end. +``` + +已验证运行结果: + +- `FilterIn(R, R1, nil)` 返回三行:`(1,2,3)`、`(2,3,4)`、`(1,2,3)` +- 这里第一行和第三行都被保留下来,说明过滤不会自动去重 +- `FilterNotIn(array(1, 2, 3, 4, 5, 5, 6, 7), array(1, 2, 3, 4), nil)` 返回 `array(5, 5, 6, 7)` + +### 按字段列表过滤 + +如果只想按部分列判断是否命中,把 `Field` 写成字段名数组: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + R := array( + ("A": 1, "B": 2, "C": 3), + ("A": 2, "B": 3, "C": 4), + ("A": 1, "B": 2, "C": 5), + ("A": 4, "B": 5, "C": 6) + ); + R1 := array( + ("A": 1, "B": 2), + ("A": 2, "B": 3) + ); + KeepRows := FilterIn(R, R1, array("A", "B")); + KeepIndex := FilterIn(R, R1, array("A", "B"), false); + SubResult := R[KeepIndex, array("A", "C")]; +end. +``` + +已验证运行结果: + +- `FilterIn(R, R1, array("A", "B"))` 返回三行:`(1,2,3)`、`(2,3,4)`、`(1,2,5)` +- `FilterIn(R, R1, array("A", "B"), false)` 返回 `array(0, 1, 2)` +- `R[KeepIndex, array("A", "C")]` 返回三行:`(1,3)`、`(2,4)`、`(1,5)` + +## 和集合运算的区别 + +- 过滤运算按“原结果集中的每一行是否命中”来决定保留或排除。 +- 集合运算按“行集合”来做并、交、差;结果默认会折叠重复行。 +- 需要保留重复记录时,优先看这一篇。 +- 需要去重后的并集、交集、差集时,优先看 [25_set_operations.md](25_set_operations.md)。 + +## 最小可编译示例 + +如果你只想先记住最短写法,从这个骨架开始: + +代码块身份:已验证可执行示例 + +```tsl +KeepRows := FilterIn(R, CodeArr, "Code"); +``` + +## 常见误写 + +- 把 `FilterIn(...)` 当成去重工具。 +- 过滤整行时忘了把 `Field` 写成 `nil`。 +- 需要返回下标时漏掉第四个参数 `false`。 +- 已经只按部分列过滤,却仍然把 `Field` 写成单个字符串。 +- 把过滤运算和 `Union2` / `Intersect` 这类集合运算混为一谈。 + +代码块身份:反例 / 不可照写 + +```text +KeepRows := FilterIn(R, R1, "A"); +``` + +上面这种写法只会按单列 `"A"` 判断,不会同时比较 `A` 和 `B`;如果需求是“按多个字段联合过滤”,应改成 `array("A", "B")`。 + +代码块身份:反例 / 不可照写 + +```text +KeepRows := FilterIn(R, R1); +``` + +不要把 `Field` 省略当成“默认按整行过滤”。当前手册只把显式写出 `nil` 作为可靠规则。 + +## 跳转指引 + +- 回看数组和子矩阵:见 [13_matrix_and_collections.md](13_matrix_and_collections.md) +- 看表达式层 `in` / `sqlin`:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 看去重型集合运算:见 [25_set_operations.md](25_set_operations.md) +- 进入 TS-SQL:见 [15_ts_sql.md](15_ts_sql.md) diff --git a/docs/tsl/syntax/15_ts_sql.md b/docs/tsl/syntax/15_ts_sql.md new file mode 100644 index 00000000..058d1791 --- /dev/null +++ b/docs/tsl/syntax/15_ts_sql.md @@ -0,0 +1,120 @@ +# TS-SQL + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[28_ts_sql_core.md](28_ts_sql_core.md)、[29_ts_sql_advanced.md](29_ts_sql_advanced.md)、[14_resultset_and_filters.md](14_resultset_and_filters.md) + +手册位置:第 15 篇,共 32 篇。上一篇:[14_resultset_and_filters.md](14_resultset_and_filters.md)。下一篇:[16_debug_and_profiler.md](16_debug_and_profiler.md)。 + +这一篇不再只是跳转页。它负责把 TS-SQL 放回整个语言阅读主线里:先知道它是什么、最短骨架怎么写、什么时候继续进入 `28` 和 `29` 两篇专题。 + +## 这一篇解决什么问题 + +回答“第一次进入 TS-SQL 时,应该先记住哪些固定骨架,怎样区分基础查询和高级查询,以及哪些内容属于语法、哪些已经属于业务层数据访问”。 + +## 必须记住的规则 + +- TS-SQL 是 TSL 自带的类 SQL 查询语法,不是金融业务函数库。 +- 基础查询当前的稳定骨架是:以 `select` / `sselect` / `vselect` / `mselect` 开始,以 `end` 收尾。 +- 在内存二维结果集上,当前稳定字段访问写法是 `["字段名"]`。 +- 在一维数组上做 TS-SQL 时,当前应优先使用 `ThisRow` 和 `ThisRowIndex`。 +- `select` 返回二维结果,`sselect` 返回一维结果,`vselect` 返回单值,`mselect` 返回 `Matrix`。 +- `join`、`ThisGroup`、`RefMaxOf` / `RefMinOf` 这类更深查询,已经进入进阶页,不要和入门骨架混写。 +- 访问金融表、时间序列或业务数据源时,语法和业务语义要分开看;本页只讲语言层查询骨架。 + +## 已验证语法 + +### 最小查询骨架 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1) + ); + R := select * from T end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `2` +- 两行依次是 `(1,3)`、`(2,1)` +- 说明 TS-SQL 的最短可靠入口就是“准备结果集,然后 `select ... from T end`” + +### 四个查询入口怎样分工 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + S := sselect ["A"] from T end; + V := vselect sumof(["B"]) from T end; + M := mselect * from T end; + C := MCols(M, 1); +end. +``` + +已验证运行结果: + +- `sselect ["A"] from T end` 返回一维数组 `array(1, 2, 1)` +- `vselect sumof(["B"]) from T end` 返回单值 `6` +- `mselect * from T end` 的行数是 `3`、列数是 `2` +- `MCols(M, 1)` 返回列索引 `array("A", "B")` + +### 什么时候进入进阶页 + +当查询开始出现多表字段、联接条件或组内子查询时,就不要继续停留在本页: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + A := array( + ("ID": 1, "V1": 10), + ("ID": 2, "V1": 20) + ); + B := array( + ("ID": 1, "V2": 100), + ("ID": 3, "V2": 300) + ); + R := select [1].["ID"], [1].["V1"], [2].["V2"] + from A join B on [1].["ID"] = [2].["ID"] + end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `1` +- 唯一一行是 `(1,10,100)` +- 说明一旦开始写 `[1].["字段"]`、`join`、`on` 这类结构,就已经进入 [29_ts_sql_advanced.md](29_ts_sql_advanced.md) 的责任范围 + +## 暂不在本页展开的部分 + +- `with on` +- `insert` / `update` / `delete` +- 面向 SQL 表或业务表的数据写回 +- 时间序列查询选项 +- 更深的缓存、对象化接口和写回类 + +这些内容不是不能写,而是应先去对应专题页或业务文档,不要在这篇入门页提前固化成默认模板。 + +## 跳转指引 + +- 如果你其实要先做结果集过滤:去 [14_resultset_and_filters.md](14_resultset_and_filters.md) +- 如果你刚开始写 TS-SQL:先去 [28_ts_sql_core.md](28_ts_sql_core.md) +- 如果你已经需要 `join` / `ThisGroup` / `RefMaxOf`:去 [29_ts_sql_advanced.md](29_ts_sql_advanced.md) +- 如果你其实是在做业务查询任务:去 [../finance/index.md](../finance/index.md) diff --git a/docs/tsl/syntax/16_debug_and_profiler.md b/docs/tsl/syntax/16_debug_and_profiler.md new file mode 100644 index 00000000..fe50ae88 --- /dev/null +++ b/docs/tsl/syntax/16_debug_and_profiler.md @@ -0,0 +1,277 @@ +# Debug And Profiler + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[08_control_flow.md](08_control_flow.md)、[30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 16 篇,共 32 篇。上一篇:[15_ts_sql.md](15_ts_sql.md)。下一篇:[18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md)。 + +这一篇收拢当前已经验证过的调试、计时、profiler 和调用栈相关入口。 + +## 这一篇解决什么问题 + +回答“`goto`、`DebugReturn`、`DebugRunEnv`、`MTIC` / `MTOC`、`SetProfiler`、`__line__` 和 `__stack_frame` 在当前解释器里怎样写、会怎样表现”。 + +## 必须记住的规则 + +- `goto label_name;` 当前已验证可用,但目标位置当前以 `label label_name; statement` 这种内联形式最稳。 +- 当前正向验证只覆盖“跳到同一函数 / 同一脚本体后面的位置”,不要先把更复杂的跨层跳转边界写成事实。 +- `DebugReturn value;` 在当前解释器里会直接结束整段脚本,后面的语句不会继续执行。 +- `DebugRunEnv(0)` 和 `DebugRunEnv(1)` 当前都可直接调用;它们面向调试客户端的副作用,在 CLI 里不直接可见。 +- `DebugRunEnvDo Func(...)` 当前已验证可直接写,并且会返回被调用函数的结果。 +- `MTIC` 会生成一个计时起点;`MTOC` 和 `MTOC(tick)` 当前都会返回秒数。 +- `SetProfiler(7)` 配合 `GetProfilerInfo(1)`,当前可以在不弹窗的情况下拿到 profiler 信息。 +- `__line__` 当前会返回所在代码行号。 +- `__stack_frame` 当前会返回调用栈帧数组;最小 `ToSTN(...)` 观察结果里,每一项是 `(line, "function")` 这一类二元组。 + +## 已验证语法 + +### `goto` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + data := array((1, 2), (3, 4)); + target := 3; + found := 0; + for i := 0 to Length(data) - 1 do + begin + for j := 0 to Length(data[i]) - 1 do + begin + if data[i][j] = target then + goto found_label; + end; + end; + WriteLn(0); + goto done_label; + label found_label; found := 1; + WriteLn(found); + label done_label; WriteLn(9); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`9` +- 说明 `goto found_label;` 当前可以跳到后面的 `label found_label; ...` +- 也说明当前最稳的目标写法是把 `label` 和第一条目标语句放在同一行 + +跨函数跳转当前没有通过: + +代码块身份:反例 / 不可照写 + +```text +program test; +function Inner(); +begin + goto out_label; +end; +begin + Inner(); + label out_label; WriteLn(1); +end. +``` + +已验证结果: + +- 上面这段会运行报错,核心信息是 `Goto label can not found!` +- 当前正向验证只覆盖“同一函数 / 同一脚本体后面的位置” +- 不要把 `goto` 泛化成能跨函数跳到外层 `label` + +目标 `label` 单独成行当前也没有通过: + +代码块身份:反例 / 不可照写 + +```text +program test; +begin + goto done_label; + label done_label; + WriteLn("after"); +end. +``` + +已验证结果: + +- 上面这种把 `label` 单独放一行、下一行再写目标语句的最小例子,在当前解释器里会报 `Statement missing terminator` +- 因此当前手册只把 `label name; statement` 这种内联形式写成已验证事实 + +### `DEBUGRETURN` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Inner(bb); +begin + DebugReturn bb; +end; +begin + WriteLn("before"); + a := Inner(3); + WriteLn("after"); +end. +``` + +已验证运行结果: + +- 只输出 `before` +- 说明 `DebugReturn bb;` 不只是结束 `Inner(...)`,而是直接让整段脚本提前返回 +- 因此 `Inner(3)` 后面的 `WriteLn("after")` 当前不会执行 + +### `DebugRunEnv` 与 `DebugRunEnvDo` + +`DebugRunEnv(0)` / `DebugRunEnv(1)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := 1; + DebugRunEnv(0); + DebugRunEnv(1); + WriteLn(1); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明这两个调用在当前 CLI 环境里至少能正常执行,不会中断后续语句 +- 但它们把变量 / 系统参数送到调试窗口的效果,在 CLI 中不能直接观察到 + +`DebugRunEnvDo Func(...)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Demo(x); +begin + y := x + 1; + return y; +end; +begin + r := DebugRunEnvDo Demo(2); + WriteLn(r); +end. +``` + +已验证运行结果: + +- 输出 `3` +- 说明 `DebugRunEnvDo Demo(2)` 当前可以直接写 +- 也说明它当前会把被调用函数的结果继续返回给外层 + +### `MTIC` 与 `MTOC` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + t1 := MTIC; + s := 0; + for i := 0 to 9999 do + s := s + i; + te1 := MTOC(t1); + t2 := MTIC; + for j := 0 to 9999 do + s := s + j; + te2 := MTOC; + WriteLn(te1 >= 0); + WriteLn(te2 >= 0); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 说明 `MTOC(t1)` 和无参 `MTOC` 当前都能返回可用的秒数结果 + +### `SetProfiler` 与 `GetProfilerInfo` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SetProfiler(7); + a := 99; + b := IntToStr(a); + c := rand(10, 1); + info := GetProfilerInfo(1); + WriteLn(IfArray(info)); + WriteLn(Length(info) > 0); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 说明 `SetProfiler(7)` 当前可以开启 profiler 统计 +- 说明 `GetProfilerInfo(1)` 当前会直接返回 profiler 信息,而且结果是非空数组 + +### `__line__` 与 `__stack_frame` + +`__line__`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := __line__; + WriteLn(a); +end. +``` + +已验证运行结果: + +- 输出 `3` +- 说明 `__line__` 当前直接返回所在代码行号 + +`__stack_frame`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Inner(); +begin + return __stack_frame; +end; +function Outer(); +begin + return Inner(); +end; +begin + s := Outer(); + WriteLn(ToSTN(s)); +end. +``` + +已验证运行结果: + +代码块身份:已验证输出片段 + +```text +array( +(11,"__main__"), +(8,"Outer")) +``` + +- 说明 `__stack_frame` 当前返回的是调用栈帧数组 +- 在这个最小例子里,可以直接看到调用位置行号和调用者函数名 + +## 跳转指引 + +- 回看主线流程控制:见 [08_control_flow.md](08_control_flow.md) +- 运行时环境参数:见 [11_runtime_context_and_with.md](11_runtime_context_and_with.md) +- 回看语法主入口:见 [index.md](index.md) +- 看运行时服务和全局缓存:见 [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) diff --git a/docs/tsl/syntax/18_lexical_structure_and_compile_options.md b/docs/tsl/syntax/18_lexical_structure_and_compile_options.md new file mode 100644 index 00000000..1477ce27 --- /dev/null +++ b/docs/tsl/syntax/18_lexical_structure_and_compile_options.md @@ -0,0 +1,235 @@ +# Lexical Structure And Compile Options + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[19_types_and_conversions.md](19_types_and_conversions.md)、[12_pitfalls.md](12_pitfalls.md)、[01_introduction.md](01_introduction.md) + +手册位置:第 18 篇,共 32 篇。上一篇:[16_debug_and_profiler.md](16_debug_and_profiler.md)。下一篇:[19_types_and_conversions.md](19_types_and_conversions.md)。 + +这一篇吸收语法手册里“词法层”和“编译期开关”相关内容:保留字、标识符、注释、条件编译、文件包含、依赖编译选项。 + +## 这一篇解决什么问题 + +回答“TSL 的词法层规则和编译期开关应该去哪里查,而不是把这些边界混进值、函数、类的正文里”。 + +## 必须记住的规则 + +- 标识符大小写无关;当前最小运行验证里,下划线也可以出现在标识符中。 +- 当前解释器接受 `//` 行注释、首行 `#!` CGI 风格注释、`{ ... }` 块注释,以及 `(* ... *)` 块注释。 +- 当前解释器接受 `{$DEFINE}`、`{$UNDEF}`、`{$IFDEF}`、`{$IFNDEF}`、`{$ELSE}`、`{$ENDIF}` 这组条件编译指令。 +- 条件编译当前已验证只会编译命中的分支;未命中的分支里即使放坏代码,也不会阻止脚本通过。 +- 当前解释器接受 `{$Explicit+}`;一旦开启,后续变量必须先用 `var` 声明,否则会报 `variable not defined`。 +- 当前解释器也接受 `{$Explicit-}`;它可以在同一源文件里把“先声明后使用”的要求重新关掉。 +- 当前解释器接受 `{$VarByRef-}` 与 `{$VarByRef+}`;它们会切换“未修饰形参”的默认传递方式,细节见 [06_functions_and_calls.md](06_functions_and_calls.md)。 +- 当前命令行解释器里,`{$I}` / `{$INCLUDE}` 的最小相对路径和绝对路径样例都没有跑通;错误信息是 `include file ... not found or include feature not implemented`。 +- `{$dependency ...}` 这类编辑器辅助编译选项,本轮还没有拿到正向最小验证,不先写成正文事实。 + +## 已验证语法 + +大小写无关与下划线标识符: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + My_Var := 7; + WriteLn(my_var); + WriteLn(MY_VAR); +end. +``` + +已验证运行结果: + +- 依次输出 `7`、`7` +- 说明当前解释器下标识符大小写无关 +- 也说明下划线可以出现在标识符中 + +注释与条件编译: + +代码块身份:已验证可执行示例 + +```tsl +#! shebang style comment +program test; +begin + a := 1; // line comment + { + (* nested comment marker *) + } + WriteLn(a); +{$DEFINE FLAG} +{$IFDEF FLAG} + WriteLn(10); +{$ELSE} + WriteLn(20); +{$ENDIF} +{$UNDEF FLAG} +{$IFNDEF FLAG} + WriteLn(30); +{$ELSE} + WriteLn(40); +{$ENDIF} +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`10`、`30` +- 说明首行 `#!`、`//`、`{ ... }`、`(* ... *)` 在当前解释器里都能通过 +- 也说明 `DEFINE` / `UNDEF` / `IFDEF` / `IFNDEF` / `ELSE` / `ENDIF` 这一组条件编译指令在当前解释器里可以正常生效 + +`{$Explicit+}` 的正向最小例子: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$Explicit+} + var a; + a := 1; + WriteLn(a); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `{$Explicit+}` 开启后,配合 `var` 声明可以正常通过 + +`{$Explicit-}` 可以在同一源文件里关掉显式声明要求: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$Explicit+} + var a; + a := 1; +{$Explicit-} + b := 2; + WriteLn(a + b); +end. +``` + +已验证运行结果: + +- 输出 `3` +- 说明 `{$Explicit-}` 会从出现位置开始取消“变量必须先声明”的限制 + +条件编译不会去编译未命中的坏代码分支: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$UNDEF NEVER} +{$IFDEF NEVER} + { 未命中分支里的坏代码示意见下方反例块 } +{$ELSE} + WriteLn(1); +{$ENDIF} +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明未命中的条件编译分支不会参与当前脚本编译 + +未命中分支里拿来做验证的坏代码外形: + +代码块身份:反例 / 不可照写 + +```text +this is bad code +``` + +上面这类内容只用于说明“坏代码”长什么样,不要直接写进正向示例块。 + +`{$VarByRef-}` 与 `{$VarByRef+}`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TouchDefault(a); +begin + a := 9; +end; +{$VarByRef-} +function TouchValue(a); +begin + a := 8; +end; +function TouchForcedVar(var a); +begin + a := 7; +end; +{$VarByRef+} +function TouchRestored(a); +begin + a := 6; +end; +begin + x := 1; + TouchDefault(x); + WriteLn(x); + y := 1; + TouchValue(y); + WriteLn(y); + z := 1; + TouchForcedVar(z); + WriteLn(z); + r := 1; + TouchRestored(r); + WriteLn(r); +end. +``` + +已验证运行结果: + +- 依次输出 `9`、`1`、`7`、`6` +- 说明默认模式下,未修饰参数仍会写回调用方 +- 说明 `{$VarByRef-}` 下,未修饰参数会改成按值传递 +- 说明 `var` 形参在 `{$VarByRef-}` 下仍保持引用语义 +- 也说明 `{$VarByRef+}` 可以把默认语义重新切回可写回模式 + +## 当前已验证的反向边界 + +代码块身份:反例 / 不可照写 + +```text +program test; +begin +{$Explicit+} + a := 1; +end. +``` + +上面这段最小样例已实测编译失败,报错主因是 `variable not defined`。 + +代码块身份:反例 / 不可照写 + +```text +program test; +{$I "common.inc"} +begin + WriteLn(1); +end. +``` + +无论把 `common.inc` 写成相对路径还是绝对路径,当前命令行解释器都没有跑通,错误信息都是 `include file ... not found or include feature not implemented`。 + +## 跳转指引 + +- 回看文件模型与顶层主体:见 [03_core_model.md](03_core_model.md) +- 回看值、字面量与字符串:见 [04_values_and_literals.md](04_values_and_literals.md) +- 回看变量、常量与显式声明:见 [05_variables_and_constants.md](05_variables_and_constants.md) +- 看类型与转换:见 [19_types_and_conversions.md](19_types_and_conversions.md) +- 看字符串与编码:见 [20_strings_and_text.md](20_strings_and_text.md) diff --git a/docs/tsl/syntax/19_types_and_conversions.md b/docs/tsl/syntax/19_types_and_conversions.md new file mode 100644 index 00000000..eb48c262 --- /dev/null +++ b/docs/tsl/syntax/19_types_and_conversions.md @@ -0,0 +1,246 @@ +# Types And Conversions + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[04_values_and_literals.md](04_values_and_literals.md)、[20_strings_and_text.md](20_strings_and_text.md)、[05_variables_and_constants.md](05_variables_and_constants.md) + +手册位置:第 19 篇,共 32 篇。上一篇:[18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md)。下一篇:[20_strings_and_text.md](20_strings_and_text.md)。 + +这一篇吸收语言基础里“数据类型、初始值、弱类型行为、类型转换、显式声明边界”这一层。 + +## 这一篇解决什么问题 + +回答“当问题不再是怎么写字面量,而是变量在运行时会变成什么类型、怎样转换、怎样受编译选项影响时,应该看哪里”。 + +## 必须记住的规则 + +- 当前解释器接受十进制、`0x` 十六进制、`0b` 二进制、`0o` 八进制整数常量。 +- 当前解释器接受 `100L` 这类 `Int64` 常量写法。 +- 当前最小验证里,超过 32 位整数范围的十进制整数字面量 `2147483648` 会按 `Int64`,不按实数处理。 +- 当前解释器接受 `1.5`、`1.0E2`、`1E2` 这类实数写法;其中 `1E2` 在当前解释器里按实数,不按整数处理。 +- 当前解释器接受 `20111231T`、`20101231.0931T` 这类日期时间字面量。 +- `TRUE` 和 `FALSE` 当前可以直接使用;打印结果分别是 `1` 和 `0`。 +- 条件判断里,当前已验证 `0` 按假值处理,非 `0` 数值按真值处理。 +- 当前解释器接受 `INF` 和 `NAN` 这两个特殊实数常量,并且 `IfReal(INF)`、`IfReal(NAN)` 都返回 `1`。 +- 当前已验证 `INF > 1000` 为真,而 `NAN = NAN` 为假。 +- 未初始化的普通变量当前会得到整数 `0`。 +- 新建对象的普通成员变量,默认值当前是 `nil`。 +- 对空数组读取一个尚未赋值的下标时,当前得到的是 `nil`。 +- 当前解释器接受 `IfNil(nil)` 这种显式空值判定。 +- 空字符串、空数组和 `nil` 在当前解释器里都按假值处理。 +- 当前解释器接受 `nil` 参与加法;`nil + 1` 和 `1 + nil` 都返回 `1`,`nil + nil` 仍然是 `nil`。 +- `IfNumber(...)` 当前已验证会把整数、`Int64`、实数都视为数值;普通字符串不算数值。 +- TSL 不是“完全禁止混合类型表达式”;像 `b + a` 这种“整数 + 字符串”会通过编译,但在运行时会报 `operand type error`。 +- 因此,类型转换要显式写出来,例如 `StrToInt(...)`,不要把运行时失败留给解释器。 + +## 已验证语法 + +基础数字字面量与类型判定: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(ifInt(100)); + WriteLn(ifInt(0x10)); + WriteLn(ifInt(0b10)); + WriteLn(ifInt(0o10)); + WriteLn(ifInt64(100L)); + WriteLn(ifReal(1.5)); + WriteLn(ifReal(1.0E2)); + WriteLn(ifInt(1E2)); + WriteLn(ifReal(1E2)); +end. +``` + +已验证运行结果: + +- 前七行都输出 `1` +- `ifInt(1E2)` 输出 `0` +- `ifReal(1E2)` 输出 `1` +- 说明 `100`、`0x10`、`0b10`、`0o10` 在当前解释器里都按整数处理 +- 说明 `100L` 在当前解释器里按 `Int64` 处理 +- 也说明 `1E2` 当前按实数,不按整数处理 + +超 32 位整数与日期时间字面量: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(ifInt64(2147483648)); + WriteLn(ifReal(2147483648)); + d1 := 20111231T; + d2 := 20101231.0931T; + WriteLn(DateToStr(d1)); + WriteLn(DateToStr(d2)); + WriteLn(TimeToStr(d2)); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`0`、`2011-12-31`、`2010-12-31`、`09:31:00` +- 说明 `2147483648` 在当前解释器里按 `Int64`,不按实数处理 +- 也说明 `20111231T`、`20101231.0931T` 这类日期时间字面量当前可以直接使用 + +布尔常量、数值真值和特殊实数: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(True); + WriteLn(False); + if 2 then WriteLn(1) else WriteLn(0); + if 0 then WriteLn(1) else WriteLn(0); + if -1 then WriteLn(1) else WriteLn(0); + WriteLn(IfReal(INF)); + WriteLn(IfReal(NAN)); + WriteLn(INF > 1000); + WriteLn(NAN = NAN); +end. +``` + +已验证运行结果: + +- 前两行分别输出 `1`、`0` +- `if 2` 输出 `1`,`if 0` 输出 `0`,`if -1` 输出 `1` +- `IfReal(INF)` 和 `IfReal(NAN)` 都输出 `1` +- `INF > 1000` 输出 `1` +- `NAN = NAN` 输出 `0` +- 说明当前解释器接受 `TRUE` / `FALSE` / `INF` / `NAN` +- 也说明数值条件判断里,`0` 为假,非 `0` 为真 + +变量初始值与缺失值: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Holder = class + value; +end; +begin + WriteLn(a); + h := new Holder(); + WriteLn(h.value = nil); + arr := array(); + WriteLn(arr[0] = nil); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`1`、`1` +- 说明未初始化普通变量默认是整数 `0` +- 说明类成员默认值是 `nil` +- 也说明空数组读取尚未赋值的下标时,当前得到的是 `nil` + +`nil` 的显式判定与加法边界: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(IfNil(nil)); + WriteLn(nil + 1); + WriteLn(1 + nil); + WriteLn(nil + nil = nil); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1`、`1` +- 说明 `IfNil(nil)` 是当前可用的显式空值判定 +- 说明当前解释器允许 `nil` 直接参与加法 +- 其中 `nil + 1` 和 `1 + nil` 都得到 `1` +- `nil + nil` 仍保持为 `nil` + +空值条件判断: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + if "" then WriteLn(0) else WriteLn(1); + if array() then WriteLn(0) else WriteLn(1); + if nil then WriteLn(0) else WriteLn(1); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1` +- 说明空字符串、空数组和 `nil` 在当前解释器里都按假值处理 + +`IfNumber(...)` 的最小边界: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(IfNumber(100)); + WriteLn(IfNumber(100L)); + WriteLn(IfNumber(1.5)); + WriteLn(IfNumber("100")); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1`、`0` +- 说明 `IfNumber(...)` 当前接受整数、`Int64`、实数 +- 也说明普通数字字符串不会被 `IfNumber(...)` 直接当成数值 + +显式类型转换的正向例子: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := "1234"; + b := 1; + c := b + StrToInt(a); + WriteLn(c); +end. +``` + +已验证运行结果: + +- 输出 `1235` +- 说明显式转换后,字符串数值与整数可以按预期参与加法 + +## 当前已验证的反向边界 + +代码块身份:反例 / 不可照写 + +```text +program test; +begin + a := "1234"; + b := 1; + WriteLn(b + a); +end. +``` + +上面这段在当前解释器里可以通过编译,但运行时会报 `Addition instruction error, operand type error`。因此不要把“能编译”误解成“会自动按你期望的类型转换”。 + +## 跳转指引 + +- 回看值和字面量:见 [04_values_and_literals.md](04_values_and_literals.md) +- 回看变量与常量:见 [05_variables_and_constants.md](05_variables_and_constants.md) +- 回看表达式与运算:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 回看函数值和类值:见 [06_functions_and_calls.md](06_functions_and_calls.md) 与 [09_objects_and_classes.md](09_objects_and_classes.md) +- 看字符串专题:见 [20_strings_and_text.md](20_strings_and_text.md) +- 看数组与矩阵样数据:见 [13_matrix_and_collections.md](13_matrix_and_collections.md) diff --git a/docs/tsl/syntax/20_strings_and_text.md b/docs/tsl/syntax/20_strings_and_text.md new file mode 100644 index 00000000..b559f87a --- /dev/null +++ b/docs/tsl/syntax/20_strings_and_text.md @@ -0,0 +1,221 @@ +# Strings And Text + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[04_values_and_literals.md](04_values_and_literals.md)、[19_types_and_conversions.md](19_types_and_conversions.md)、[07_expressions_and_operators.md](07_expressions_and_operators.md) + +手册位置:第 20 篇,共 32 篇。上一篇:[19_types_and_conversions.md](19_types_and_conversions.md)。下一篇:[21_external_calls_and_threads.md](21_external_calls_and_threads.md)。 + +这一篇吸收字符串专题里较深的部分:字符串表达、编码边界、转义、非转义表达、字符串拼装和子串操作。 + +## 这一篇解决什么问题 + +回答“当任务进入字符串和编码细节,而不是只写普通字面量时,应该进入哪一篇”。 + +## 必须记住的规则 + +- 普通字符串、`L""` 宽串、`U""` UTF8 前缀串,以及 `%%` 原始字符串,当前解释器都接受。 +- `%%` 原始字符串开头后必须先跟一个空白分隔符;可以带标识符,也支持多行。 +- `L%% ...%%` 与 `U%% ...%%` 这两种带前缀的原始字符串当前也可用。 +- 普通字符串里的 `\uXXXX` 不要直接按“单字符宽串”理解;当前 `Length("\u0041") = 2`,而 `Length(L"\u0041") = 1`、`Length(U"\u0041") = 1`。 +- `U""` 不是宽串;需要在 UTF8、宽串、普通串之间显式转换时,继续用 `UTF8ToUnicode(...)`、`UTF8ToAnsi(...)`、`AnsiToUTF8(...)`、`UnicodetoUTF8(...)`、`String(...)`、`WideString(...)`。 +- `#number` 可以直接把字符码拼进字符串。 +- `\0` 和 `#0` 都能把 ASCII `0` 放进字符串,并且不会把字符串截断。 +- 字符串下标当前已验证从 `1` 开始,不从 `0` 开始;访问 `s[0]` 会运行报 `String index out of bounds`。 +- 字符串切片 `s[start:end]`、替换 `s[start:end] := sub`、删除 `s[start:end] := ""`、插入 `s[index:0] := sub` 当前都可用。 +- 基础字符串索引、切片、插入、删除和替换规则,阅读主线仍以 [04_values_and_literals.md](04_values_and_literals.md) 为准;这一篇只补已经单独实测过的深水边界。 + +## 已验证语法 + +原始字符串 `%%` 的空白分隔、标识符和多行: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s1 := %% ABC%%; + s2 := %%tag A"B'C%%tag; + s3 := %%m +A +B%%m; + WriteLn(s1); + WriteLn(s2); + WriteLn(s3); +end. +``` + +已验证运行结果: + +- `s1` 输出 `ABC` +- `s2` 输出 `A"B'C` +- `s3` 输出两行 `A`、`B` +- 说明 `%%` 开头后的第一个空白只是分隔符,不属于正文 +- 说明 `%%tag ...%%tag` 可以用标识符配对 +- 也说明 `%%` 原始字符串支持直接跨行 + +带前缀的原始字符串: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(L%% ABC%% = L"ABC"); + WriteLn(U%% ABC%% = "ABC"); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 说明 `L%% ...%%` 和 `U%% ...%%` 在当前解释器里都可用 + +`\uXXXX` 在普通串、宽串和 `U` 串里的边界: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(Length("\u0041")); + WriteLn(Length(L"\u0041")); + WriteLn(Length(U"\u0041")); +end. +``` + +已验证运行结果: + +- 依次输出 `2`、`1`、`1` +- 因此不要把普通字符串里的 `"\u0041"` 直接理解成和 `L"\u0041"` 一样的“单字符”写法 + +字符串显式编码转换: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + utf8_s := U"\u5929\u8F6F"; + utf8_s2 := UnicodetoUTF8(L"\u5929\u8F6F"); + wide_s := UTF8ToUnicode(utf8_s); + ansi_s := UTF8ToAnsi(utf8_s); + WriteLn(IfWString(utf8_s)); + WriteLn(utf8_s = utf8_s2); + WriteLn(wide_s = L"\u5929\u8F6F"); + WriteLn(ansi_s = String(L"\u5929\u8F6F")); +end. +``` + +已验证运行结果: + +- 依次输出 `0`、`1`、`1`、`1` +- 说明 `U""` 在当前解释器里不是宽串 +- 说明 UTF8、宽串、普通串之间的显式转换链已经拿到正向最小结果 + +ASCII `0` 字符不会截断字符串: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s1 := "A\0B"; + s2 := "A"#0"B"; + WriteLn(Length(s1)); + WriteLn(Length(s2)); + WriteLn(s1 = s2); + WriteLn(s1[2] = #0); +end. +``` + +已验证运行结果: + +- 依次输出 `3`、`3`、`1`、`1` +- 说明 `\0` 和 `#0` 都可以把 ASCII `0` 放进字符串 +- 也说明当前字符串不是遇到 `#0` 就自动截断的 C 风格零结尾串 + +字符码拼接: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn("A"#48"B"); + WriteLn("A"#13#10"B"); +end. +``` + +已验证运行结果: + +- 第一行输出 `A0B` +- 第二组输出会分成两行 `A`、`B` +- 说明 `#48` 这类写法会按字符码直接参与字符串拼接,`#13#10` 可以直接表示换行 + +字符串下标、切片和区间改写: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s := "ABCD"; + WriteLn(s[1]); + WriteLn(s[2]); + s := "AAABBB"; + WriteLn(s[3:4]); +end. +``` + +已验证运行结果: + +- 依次输出 `A`、`B`、`AB` +- 说明字符串下标当前从 `1` 开始 +- 也说明 `s[3:4]` 会取到起止位置都包含在内的子串 + +替换、删除和插入: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s1 := "AAABBB"; + s1[3:4] := "111"; + WriteLn(s1); + s2 := "AAABBB"; + s2[3:4] := ""; + WriteLn(s2); + s3 := "AAABBB"; + s3[4:0] := "111"; + WriteLn(s3); +end. +``` + +已验证运行结果: + +- 三行依次输出 `AA111BB`、`AABB`、`AAA111BBB` +- 说明 `s[start:end] := sub` 可以直接替换区间 +- 说明右值设为空串时,会删除该区间 +- 说明 `s[index:0] := sub` 会在指定位置前插入子串 + +当前还额外验证到: + +代码块身份:反例 / 不可照写 + +```text +s := "ABCD"; +WriteLn(s[0]); +``` + +上面这种写法会运行报错,错误信息包含 `String index out of bounds`。不要把字符串下标按数组的 `0` 起始规则来写。 + +## 跳转指引 + +- 回看最常用字符串字面量:见 [04_values_and_literals.md](04_values_and_literals.md) +- 回看字符串上的表达式行为:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 看类型与转换:见 [19_types_and_conversions.md](19_types_and_conversions.md) +- 看值与字面量:见 [04_values_and_literals.md](04_values_and_literals.md) diff --git a/docs/tsl/syntax/21_external_calls_and_threads.md b/docs/tsl/syntax/21_external_calls_and_threads.md new file mode 100644 index 00000000..7548d5a8 --- /dev/null +++ b/docs/tsl/syntax/21_external_calls_and_threads.md @@ -0,0 +1,250 @@ +# External Calls And Threads + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[06_functions_and_calls.md](06_functions_and_calls.md)、[22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 21 篇,共 32 篇。上一篇:[20_strings_and_text.md](20_strings_and_text.md)。下一篇:[22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)。 + +这一篇吸收函数专题里和外部系统交互有关的部分:`external`、动态库调用、函数指针包装、线程调用。 + +## 这一篇解决什么问题 + +回答“普通函数怎么写已经清楚后,外部 DLL、函数指针、多线程这些系统交互能力应该去哪里查”。 + +## 必须记住的规则 + +- 当前解释器接受 `function Name(...): Type; stdcall|cdecl; external "dll" [name "symbol"];` 这类外部函数声明。 +- 当 TSL 函数名和 DLL 导出名一致时,`name "symbol"` 可以省略。 +- 在当前 `Win64` 解释器上,同一个 `GetTickCount64` 例子里,`stdcall`、`cdecl`、省略调用约定都已跑通;手册示例仍默认把调用约定显式写出来。 +- `procedure Name(...); ... external ...;` 当前也已验证可用。 +- `function(...): ...; external fp;` 当前可以把原生函数指针重新包装成 TSL 可调用对象。 +- 当前已验证的 DLL 名写法包括字面量字符串和类常量字符串;不要把字符串拼接表达式直接当成稳定写法。 +- `MakeInstance(ThisFunction(Func), "cdecl", 0)` 当前可以把 TSL 函数包装成 C 调用约定函数指针。 +- `MakeInstance(..., "cdecl", 1)` 当前在 `Win64` 下已经拿到最小线程正例,可以直接交给 `CreateThread`。 +- 当前页的线程示例是 Windows 专题,用到了 `kernel32.dll`。 + +## 已验证语法 + +### 最小 `external` 声明 + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Tick64Alias(): int64; stdcall; external "kernel32.dll" name "GetTickCount64"; +begin + WriteLn(Tick64Alias() > 0); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明当前解释器接受 `stdcall` + `external "dll" name "symbol"` 这类外部函数声明骨架 +- 也说明 TSL 里的函数名可以和 DLL 导出名不同,再通过 `name "ExportName"` 绑定 + +当本地函数名和 DLL 导出名一致时,`name` 可以省略: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function GetTickCount64(): int64; stdcall; external "kernel32.dll"; +begin + WriteLn(GetTickCount64() > 0); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `name "symbol"` 不是当前解释器下的强制写法 + +当前 `Win64` 基线下,省略调用约定与显式 `cdecl` 也通过了同一 API 的最小验证: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function TickNoConv(): int64; external "kernel32.dll" name "GetTickCount64"; +function TickCdecl(): int64; cdecl; external "kernel32.dll" name "GetTickCount64"; +begin + WriteLn(TickNoConv() > 0); + WriteLn(TickCdecl() > 0); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1` +- 这只说明当前 `Win64` 解释器下,这两种写法都能跑通这个例子 +- 不要把这个结果直接泛化成“所有平台、所有架构下调用约定都等价” + +### `procedure external` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Tick64(): int64; stdcall; external "kernel32.dll" name "GetTickCount64"; +procedure SleepMs(ms: integer); stdcall; external "kernel32.dll" name "Sleep"; +begin + t1 := Tick64(); + SleepMs(20); + t2 := Tick64(); + WriteLn(t2 >= t1); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明无返回值的外部过程可以直接声明为 `procedure` + +### 原生函数指针包装 + +代码块身份:已验证可执行示例 + +```tsl +program test; +function LoadLibraryA(s: string): pointer; stdcall; external "kernel32.dll" name "LoadLibraryA"; +function GetProcAddress(hModule: pointer; lpProcName: string): pointer; stdcall; external "kernel32.dll" name "GetProcAddress"; +begin + h := LoadLibraryA("kernel32.dll"); + fp := GetProcAddress(h, "GetTickCount64"); + f := function(): int64; stdcall; external fp; + WriteLn(h <> nil); + WriteLn(fp <> nil); + WriteLn(##f() > 0); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1` +- 说明 `function(...); ... external fp;` 不只适用于 `MakeInstance(...)` 的结果,也适用于 `GetProcAddress(...)` 返回的原生函数指针 + +### DLL 名的已验证边界 + +类常量字符串: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Demo = class + const KRNL = "kernel32.dll"; +public + function Run(); + begin + return TickConst() > 0; + end; + function TickConst(): int64; stdcall; external KRNL name "GetTickCount64"; +end; +begin + d := new Demo(); + WriteLn(d.Run()); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明当前解释器接受“类常量字符串 -> `external KRNL`”这条最小路径 + +当前已验证的反向边界: + +代码块身份:反例 / 不可照写 + +```text +function TickFromExpr(): int64; stdcall; external "kernel32"$"."$"dll" name "GetTickCount64"; +``` + +上面这种 DLL 名字符串拼接表达式在当前解释器里会报 `dll filename const string not found after external`。因此当前手册只把字面量字符串和已单独验证过的类常量字符串写成可靠规则。 + +### `MakeInstance` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Add(a: integer; b: integer): integer; +begin + return a + b; +end; +begin + fp := MakeInstance(ThisFunction(Add), "cdecl", 0); + f := function(a: integer; b: integer): integer; external fp; + WriteLn(fp <> nil); + WriteLn(##f(3, 4)); +end. +``` + +已验证运行结果: + +- `fp <> nil` 输出 `1` +- `##f(3, 4)` 输出 `7` +- 说明当前解释器里,`MakeInstance(...)` 生成的函数指针可以再通过 `function(...); external fp;` 包装回 TSL 侧调用 + +### 线程模式最小正例 + +代码块身份:已验证可执行示例 + +```tsl +program test; +function CreateThread(attr: pointer; size: pointer; addr: pointer; p: pointer; flag: Integer; var thread_id: Integer): pointer; stdcall; external "kernel32.dll" name "CreateThread"; +function WaitForSingleObject(h: pointer; timeout: Integer): Integer; stdcall; external "kernel32.dll" name "WaitForSingleObject"; +function CloseHandle(h: pointer): Integer; stdcall; external "kernel32.dll" name "CloseHandle"; +function Worker(p: pointer): integer; +begin + SetGlobalCache("THREAD_TEST_KEY", 1); + return 1; +end; +begin + SetGlobalCache("THREAD_TEST_KEY", 0); + fp := MakeInstance(ThisFunction(Worker), "cdecl", 1); + h := CreateThread(nil, nil, fp, nil, 0, tid); + WriteLn(fp <> nil); + WriteLn(h <> nil); + WriteLn(WaitForSingleObject(h, 5000) >= 0); + GetGlobalCache("THREAD_TEST_KEY", v); + WriteLn(v); + CloseHandle(h); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`1`、`1`、`1` +- 说明 `MakeInstance(..., "cdecl", 1)` 当前可以生成可用于 `CreateThread` 的回调指针 +- 也说明线程体里的 `SetGlobalCache(...)` 当前能够跑通这个最小闭环 + +## 最小可编译示例 + +如果你只是要先记住最小的 DLL 引入骨架,用这个: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function Tick64Alias(): int64; stdcall; external "kernel32.dll" name "GetTickCount64"; +begin + WriteLn(Tick64Alias() > 0); +end. +``` + +## 常见误写 + +- 把 `external` 的 DLL 名直接写成字符串拼接表达式。 +- 省略了外部函数的参数类型或返回类型。 +- 把 `MakeInstance(...)` 生成的结果默认写成普通函数名直调,而不是先包装或用 `##`. +- 直接把 Windows 线程示例当成跨平台事实。 + +## 跳转指引 + +- 回看函数主线:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- 回看运行时边界:见 [16_debug_and_profiler.md](16_debug_and_profiler.md) +- 看 unit / namespace / 查找路径:见 [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) diff --git a/docs/tsl/syntax/22_namespace_libpath_and_unit_runtime.md b/docs/tsl/syntax/22_namespace_libpath_and_unit_runtime.md new file mode 100644 index 00000000..c579a45b --- /dev/null +++ b/docs/tsl/syntax/22_namespace_libpath_and_unit_runtime.md @@ -0,0 +1,425 @@ +# Namespace Libpath And Unit Runtime + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[10_units_and_scope.md](10_units_and_scope.md)、[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 22 篇,共 32 篇。上一篇:[21_external_calls_and_threads.md](21_external_calls_and_threads.md)。下一篇:[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)。 + +这一篇收拢 `unit` 的运行时行为,以及 `.tsf` / `namespace` / `libpath` 的查找规则。`unit` 的基础写法、`uses` 位置和重名解析,统一放在 [10_units_and_scope.md](10_units_and_scope.md)。 + +## 这一篇解决什么问题 + +回答下面这些“写法已经会了,但运行起来为什么这样”的问题: + +- `unit` 什么时候进入 `initialization` +- `finalization` 在什么时候触发 +- `unit` 里的常量、变量和 `findfunction("UnitName")` 到底暴露哪些成员 +- `tslfilename()` 返回什么 +- `NameSpace "..."`、`tsl.conf` 和 `-LIBPATH` 怎样影响 `.tsf` 查找 +- `syssettsllibpath()` / `sysgettsllibpath()` 怎样在运行时改查找路径 + +## 必须记住的规则 + +- 完整 `unit` 形态可以包含 `interface`、`implementation`、`initialization`、`finalization`,并以 `end.` 结束。 +- `initialization` 在 `unit` 第一次被实际使用时触发,不是只因为顶层写了 `uses` 就立刻执行。 +- `finalization` 会在脚本结束前触发。 +- 直接写 `DemoUnit.Member` 时,当前解释器能读到 `interface` 和 `implementation` 里的常量、变量。 +- `findfunction("DemoUnit")` 拿到的是 `unit` 对象入口,但当前只验证到它稳定暴露 `interface` 成员;`implementation` 变量和常量没有从这个对象读出来。 +- `DemoUnit.VarName := value` 这种限定赋值当前会编译失败;如果要改 `unit` 状态,应导出函数或方法来改。 +- `tslfilename()` 在命令行解释器里返回当前执行脚本的完整路径。 +- `NameSpace "DemoNS";` 会选择 `Hello@DemoNS.tsf` 这类命名空间函数文件。 +- `tsl.conf` 的 `[system] Namespace=...` 可以设置默认命名空间;脚本里的 `NameSpace "..."` 会覆盖配置值。 +- 当全局 `Hello.tsf` 和 `Hello@StmtNS.tsf` 同时存在时,启用 `StmtNS` 后会优先命中命名空间版本。 +- `-LIBPATH` 必须跟在脚本文件名后面;目录项必须以 `/` 或 `\` 结尾;多路径分隔符当前实测是分号 `;`。 +- 当多个 `-LIBPATH` 目录都存在同名 `.tsf` 时,解释器按路径从前到后查找,先命中的目录优先。 +- `tsl.conf` 里的绝对 `Libpath=` 可以生效;`Libpath={$P}...` 在当前解释器下没有拿到正向结果。 +- `syssettsllibpath()` / `sysgettsllibpath()` 可以在运行时修改和读取查找路径,路径规则与 `-LIBPATH` 相同。 +- `InheritParent=1` 目前没有拿到稳定正例,因此不写成正式规则。 + +## 已验证语法与行为 + +### `unit` 生命周期 + +代码块身份:配置片段 / 概念骨架 + +```text +// DemoUnit.tsf +unit DemoUnit; +interface +const UnitValue = 7; +var UnitCounter; +function Ping(); +implementation +var PrivateCounter; +function Ping(); +begin + PrivateCounter := PrivateCounter + 1; + UnitCounter := UnitCounter + 10; + return PrivateCounter; +end; +initialization + WriteLn("INIT"); + UnitCounter := 1; + PrivateCounter := 100; +finalization + WriteLn("FINAL"); +end. + +// main.tsl +program test; +uses DemoUnit; +begin + WriteLn("BEFORE"); + WriteLn(DemoUnit.UnitValue); + WriteLn(DemoUnit.UnitCounter); + WriteLn(Ping()); + WriteLn(DemoUnit.UnitCounter); +end. +``` + +已验证运行结果: + +- 输出顺序是 `BEFORE`、`INIT`、`7`、`1`、`101`、`11`、`FINAL`。 +- 这说明顶层写了 `uses DemoUnit;` 之后,`initialization` 不是立刻执行,而是在第一次真正读 `DemoUnit` 成员时触发。 +- `finalization` 在脚本主体输出结束后触发。 + +### `unit` 成员的读取边界 + +直接限定读取: + +代码块身份:配置片段 / 概念骨架 + +```text +// DemoUnit.tsf +unit DemoUnit; +interface +const PublicConst = 1; +var PublicVar; +function PublicFunc(); +implementation +const ImplConst = 2; +var ImplVar; +function PublicFunc(); +begin + return 10; +end; +function ImplFunc(); +begin + return 20; +end; +initialization + PublicVar := 3; + ImplVar := 4; +end. + +// main.tsl +uses DemoUnit; +WriteLn(DemoUnit.PublicConst); +WriteLn(DemoUnit.PublicVar); +WriteLn(DemoUnit.ImplConst); +WriteLn(DemoUnit.ImplVar); +WriteLn(PublicFunc()); +WriteLn(ImplFunc()); +``` + +已验证运行结果: + +- `DemoUnit.PublicConst` 输出 `1`。 +- `DemoUnit.PublicVar` 输出 `3`。 +- `DemoUnit.ImplConst` 输出 `2`。 +- `DemoUnit.ImplVar` 输出 `4`。 +- `PublicFunc()` 输出 `10`。 +- `ImplFunc()` 仍然报 `compile error or not found`。 +- 当前解释器的真实边界是:实现段函数仍私有,但实现段常量和变量可以通过 `DemoUnit.Member` 直接读取。 + +`findfunction("UnitName")` 拿到的 `unit` 对象: + +代码块身份:配置片段 / 概念骨架 + +```text +// DemoUnit.tsf +unit DemoUnit; +interface +const PublicConst = 1; +var PublicVar; +function Ping(); +implementation +const ImplConst = 2; +var ImplVar; +function Ping(); +begin + return 11; +end; +initialization + PublicVar := 3; + ImplVar := 4; +end. + +// main.tsl +uses DemoUnit; +u := findfunction("DemoUnit"); +WriteLn(u.PublicConst); +WriteLn(u.PublicVar); +WriteLn(u.Ping()); +WriteLn(u.ImplConst); +``` + +已验证运行结果: + +- `u.PublicConst` 输出 `1`。 +- `u.PublicVar` 输出 `3`。 +- `u.Ping()` 输出 `11`。 +- `u.ImplConst` 报对象属性或方法不存在。 +- 当前解释器下,`findfunction("DemoUnit")` 拿到的对象入口只稳定暴露 `interface` 成员。 + +限定赋值失败: + +代码块身份:反例 / 不可照写 + +```text +uses DemoUnit; +DemoUnit.UnitCounter := 13; +``` + +已验证结果: + +- 上面这段会编译失败,报错核心是 `left side can not be assign to`。 + +### `TslFileName` + +代码块身份:已验证可执行示例 + +```tsl +WriteLn(tslfilename()); +``` + +已验证结果: + +- 在命令行解释器里,这一行会输出当前执行 `.tsl` 文件的完整路径。 +- 当前已验证的是“主脚本路径”;不要把 `.tsf` 被调用场景的返回值提前写成已验证事实。 + +### `NameSpace` 与默认命名空间 + +把默认命名空间、脚本覆盖、以及“全局函数与命名空间函数同名”的三组结论压成同一套最小实验: + +代码块身份:配置片段 / 概念骨架 + +```text +// tsl.conf +[system] +Namespace=ConfNS +Libpath=D:\path\to\lib\ + +// 同一目录下准备三份函数文件 +// Hello.tsf +function Hello(); +begin + return 10; +end; + +// Hello@ConfNS.tsf +function Hello(); +begin + return 20; +end; + +// Hello@StmtNS.tsf +function Hello(); +begin + return 30; +end; + +// main_conf.tsl +program test; +begin + WriteLn(Hello()); +end. + +// main_stmt.tsl +program test; +begin + NameSpace "StmtNS"; + WriteLn(Hello()); +end. +``` + +已验证运行结果: + +- `main_conf.tsl` 输出 `20`,说明 `tsl.conf` 里的 `Namespace=ConfNS` 会默认命中 `Hello@ConfNS.tsf`。 +- `main_stmt.tsl` 输出 `30`,说明脚本里的 `NameSpace "StmtNS";` 会覆盖 `tsl.conf` 里的 `Namespace=ConfNS`。 +- 在同一目录保留 `Hello.tsf` 后,不写 `NameSpace` 且不设置 `Namespace` 时,`Hello()` 输出 `10`。 +- 如果只保留 `Hello@StmtNS.tsf` 而没有全局 `Hello.tsf`,又没有启用命名空间,`Hello()` 会报找不到函数。 + +### `-LIBPATH` + +查找顺序: + +代码块身份:配置片段 / 概念骨架 + +```text +// libA/Hello.tsf +function Hello(); +begin + return 101; +end; + +// libB/Hello.tsf +function Hello(); +begin + return 202; +end; + +// main.tsl +program test; +begin + WriteLn(Hello()); +end. + +// command A +tsl .\main.tsl -LIBPATH "D:\libA\;D:\libB\" + +// command B +tsl .\main.tsl -LIBPATH "D:\libB\;D:\libA\" +``` + +已验证运行结果: + +- 命令 A 输出 `101`。 +- 命令 B 输出 `202`。 +- 当前解释器按 `-LIBPATH` 从前到后查找,先命中的目录优先。 + +位置与分隔符边界: + +代码块身份:配置片段 / 概念骨架 + +```text +tsl -LIBPATH "D:\libA\" .\main.tsl +tsl .\main.tsl -LIBPATH "D:\libA" +tsl .\main.tsl -LIBPATH "D:\libA\,D:\libB\" +``` + +已验证结果: + +- 把 `-LIBPATH` 放在脚本文件名前面时,解释器不会执行脚本,而是回到 usage 提示。 +- 路径项不带结尾 `/` 或 `\` 时,函数找不到。 +- 逗号分隔多路径没有跑通;当前实测有效的是分号 `;`。 + +### `syssettsllibpath()` 与 `sysgettsllibpath()` + +代码块身份:配置片段 / 概念骨架 + +```text +program test; +begin + WriteLn(syssettsllibpath("C:/path/to/libA/;C:/path/to/libB/")); + WriteLn(sysgettsllibpath()); + WriteLn(call("FnA")); + WriteLn(call("FnB")); +end. +``` + +已验证运行结果: + +- `syssettsllibpath(".../libA/;.../libB/")` 之后,`call("FnA")` 和 `call("FnB")` 都能找到对应函数。 +- `sysgettsllibpath()` 返回设置后的完整路径串。 +- 当前实测里,逗号分隔没有跑通;路径项不带结尾 `/` 也没有跑通。 + +### `tsl.conf` 的 `Libpath=` + +代码块身份:配置片段 / 概念骨架 + +```text +[system] +Libpath=D:\path\to\funcext\ +``` + +已验证结果: + +- 当前目录 `tsl.conf` 设为绝对 `Libpath=` 时,脚本可以找到该目录下的 `.tsf`。 +- 当前解释器下,`Libpath={$P}funcext/` 没有拿到正向结果。 +- 当前解释器下,也没有拿到 `InheritParent=1` 的稳定正例,因此不要把这两条当成可依赖规则。 + +`Libpath=` 的正向与负向对照: + +代码块身份:配置片段 / 概念骨架 + +```text +// case A: 绝对 Libpath +// tsl.conf +[system] +Libpath=D:/abs/path/to/funcext/ + +// funcext/Hello.tsf +function Hello(); +begin + return 123; +end; + +// main.tsl +program test; +begin + WriteLn(Hello()); +end. + +// case B: {$P} Libpath +// tsl.conf +[system] +Libpath={$P}funcext/ + +// case B 的 main.tsl 与 case A 相同 +// case B 的 funcext/Hello.tsf 只把返回值改成 456 +``` + +已验证结果: + +- case A 输出 `123` +- case B 仍报 `function:Hello compile error or not found` +- 因此当前解释器下,不能把 `{$P}` 替换写法当成已经稳定可依赖的规则 + +`InheritParent=1` 的最小负例: + +代码块身份:反例 / 不可照写 + +```text +// parent/tsl.conf +[system] +Namespace=ParentNS +InheritParent=1 + +// parent/sub/Hello@ParentNS.tsf +function Hello(); +begin + return 314; +end; + +// parent/sub/main.tsl +program test; +begin + WriteLn(Hello()); +end. +``` + +已验证结果: + +- 在当前解释器里,这组父目录配置 + 子目录脚本的最小样例仍报 `function:Hello compile error or not found` +- 因此 `InheritParent=1` 现在还不能升级成正式正向结论 + +## 常见误写 + +- 把 `DemoUnit.VarName := value` 当成可用的限定赋值。 +- 以为 `implementation` 里的常量和变量一定都不能从 `DemoUnit.Member` 读到。 +- 以为 `findfunction("DemoUnit")` 暴露的成员范围和 `DemoUnit.Member` 完全相同。 +- 把脚本内的 `NameSpace "..."` 当成和 `tsl.conf` 里的 `Namespace=...` 叠加,而不是覆盖。 +- 把 `-LIBPATH` 放在脚本文件名前面。 +- 用逗号分隔 `-LIBPATH` 或 `syssettsllibpath()` 的多路径。 +- 忘了给 `-LIBPATH` 或 `syssettsllibpath()` 的目录项补结尾 `/` 或 `\`。 +- 把 `Libpath={$P}...` 和 `InheritParent=1` 直接当成当前解释器已经稳定可依赖的规则。 + +## 跳转指引 + +- 回看 `unit` / `uses` 主线:见 [10_units_and_scope.md](10_units_and_scope.md) +- 查看对象反射与运行时对象:见 [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) +- 回看函数文件与顶层主体:见 [03_core_model.md](03_core_model.md) diff --git a/docs/tsl/syntax/23_object_runtime_and_introspection.md b/docs/tsl/syntax/23_object_runtime_and_introspection.md new file mode 100644 index 00000000..76519f9e --- /dev/null +++ b/docs/tsl/syntax/23_object_runtime_and_introspection.md @@ -0,0 +1,399 @@ +# Object Runtime And Introspection + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[09_objects_and_classes.md](09_objects_and_classes.md)、[24_builtin_runtime_objects.md](24_builtin_runtime_objects.md)、[32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) + +手册位置:第 23 篇,共 32 篇。上一篇:[22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md)。下一篇:[24_builtin_runtime_objects.md](24_builtin_runtime_objects.md)。 + +这一篇收拢对象模型里不适合继续堆在基础类主线里的运行时内容:类信息、函数句柄、对象状态、引用计数、运行时对象枚举。 + +## 这一篇解决什么问题 + +回答“类已经会声明、继承、构造之后,怎样检查类信息、函数信息和对象运行时状态”。 + +## 必须记住的规则 + +- 对象值当前可以用 `ifObj(...)` 做显式判定。 +- `class(Name)` 和 `FindClass("Name")` 当前都可以拿到类类型。 +- `obj is classType` 当前已验证可直接拿类类型变量来做实例判定。 +- `FindClass("ParentName", obj)` 当前已验证可以把实例对象降成指定父类视图。 +- `obj.ClassInfo(1)` 当前已验证会返回类类型,并且这个类类型可以继续交给 `CreateObject(...)`。 +- `obj.ClassInfo()` 当前至少已验证可以直接读出 `["classname"]`。 +- `objectstate(self)` 在构造函数内部的最小已验证结果是 `1`;构造结束后对实例再取 `objectstate(obj)` 的最小已验证结果是 `2`。 +- `tslassigning` 在属性写入函数里输出 `1`,在属性读取函数里输出 `0`。 +- `FindFunction("MethodName", obj)` 当前已验证可以拿到实例方法句柄。 +- `FindFunction("MethodName", class(A))` 当前已验证可以拿到类方法句柄。 +- `ThisFunction(obj.Method)` 和 `ThisFunction(class(A).Method)` 当前也已验证可用。 +- 当前最稳的句柄调用方式是 `f.do(...)`。 +- `FindOverLoad(argc, "Name", obj)` 当前已验证可以按参数个数取到对应重载方法。 +- `FunctionInfo` 当前至少已验证可以读出 `functionname`、`returntype`、`classname` 这几个字段。 +- `TSLObjects(1)` 当前已验证会按类名分组返回对象信息,并且分组项里的 `"obj"` 字段可以重新拿到可调用对象。 +- 对象赋值会延长对象存活;当前最小样例里,只有最后一个引用清空后才会触发 `destroy()`。 + +## 已验证语法 + +对象值的最小显式判定: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + obj := CreateObject("TStringList"); + WriteLn(ifObj(obj)); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `CreateObject(...)` 得到的对象值当前可以用 `ifObj(...)` 判定 + +`FindClass(...)` 与类类型变量: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + class function FucA(); + begin + return "ClassA"; + end; +end; +begin + classA := FindClass("A"); + obj := new A(); + WriteLn(classA.FucA()); + WriteLn(obj is classA); +end. +``` + +已验证运行结果: + +- 依次输出 `ClassA`、`1` +- 说明 `FindClass("A")` 当前可以拿到类类型 +- 说明类类型变量可以直接调用类方法 +- 也说明 `obj is classA` 这种“实例对类类型变量做判定”的写法当前可用 + +`FindClass("Parent", obj)` 的父类视图: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type ClassA = class + function Fuc(); virtual; + begin + return "ClassA"; + end; +end; +type ClassB = class(ClassA) + function Fuc(); override; + begin + return "ClassB"; + end; +end; +begin + objb := new ClassB(); + obj := FindClass("ClassA", objb); + WriteLn(obj.Fuc()); +end. +``` + +已验证运行结果: + +- 输出 `ClassA` +- 说明 `FindClass("ClassA", objb)` 当前可以把子类实例降成父类视图 +- 也说明之后的方法分派会按父类视图执行 + +`ClassInfo(1)` 返回类类型: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + value; +end; +begin + obj := new A(); + cls := obj.ClassInfo(1); + obj2 := CreateObject(cls); + WriteLn(obj2 is class(A)); +end. +``` + +已验证运行结果: + +- 输出 `1` +- 说明 `obj.ClassInfo(1)` 当前可以返回类类型 +- 也说明这个类类型可以继续交给 `CreateObject(...)` + +`ClassInfo()` 返回的映射字段: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class +end; +begin + obj := new A(); + info := obj.ClassInfo(); + WriteLn(info["classname"]); +end. +``` + +已验证运行结果: + +- 输出 `a` +- 说明 `ClassInfo()` 当前至少可以直接读出 `["classname"]` +- 当前这个最小例子里,类名表现为小写标识符 + +`objectstate(...)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type ca = class + static sca; + function create(n); + begin + sca := self; + WriteLn(objectstate(self)); + end; +end; +begin + oa := new ca("abc"); + WriteLn(objectstate(oa)); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`2` +- 说明当前最小样例里,构造函数内部对象状态是 `1` +- 构造结束后,再对实例取 `objectstate(...)` 会得到 `2` + +`tslassigning`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type ca = class + value; + property c read getc write setc; + function setc(v); + begin + WriteLn(tslassigning); + value := v; + end; + function getc(); + begin + WriteLn(tslassigning); + return value; + end; +end; +begin + o := new ca(); + o.c := 3; + WriteLn(o.c); +end. +``` + +已验证运行结果: + +- 依次输出 `1`、`0`、`3` +- 说明属性写入函数里 `tslassigning` 为 `1` +- 属性读取函数里 `tslassigning` 为 `0` + +`FindFunction(...)` 查找实例方法和类方法: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Add(x, y); + begin + return x + y; + end; + class function AddClass(x, y); + begin + return x + y; + end; +end; +begin + obj := new A(); + f1 := FindFunction("Add", obj); + f2 := FindFunction("AddClass", class(A)); + WriteLn(f1.do(3, 4)); + WriteLn(f2.do(5, 6)); +end. +``` + +已验证运行结果: + +- 依次输出 `7`、`11` +- 说明 `FindFunction(..., obj)` 当前能拿到实例方法句柄 +- 说明 `FindFunction(..., class(A))` 当前能拿到类方法句柄 +- 也说明句柄调用方式 `f.do(...)` 当前稳定可用 + +`ThisFunction(...)` 也可以直接拿方法句柄: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + function Add(x, y); + begin + return x + y; + end; + class function AddClass(x, y); + begin + return x + y; + end; +end; +begin + obj := new A(); + f1 := ThisFunction(obj.Add); + f2 := ThisFunction(class(A).AddClass); + WriteLn(f1.do(3, 4)); + WriteLn(f2.do(5, 6)); +end. +``` + +已验证运行结果: + +- 依次输出 `7`、`11` +- 说明 `ThisFunction(...)` 当前也可以稳定得到实例方法和类方法句柄 + +`FindOverLoad(...)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TestClass = class + function fun(p1, p2); overload; + begin + return p1 + p2; + end; + function fun(p1); overload; + begin + return p1 + 10; + end; +end; +begin + t := FindOverLoad(2, "fun", CreateObject("TestClass")); + WriteLn(t.do(1, 2)); +end. +``` + +已验证运行结果: + +- 输出 `3` +- 说明 `FindOverLoad(2, "fun", obj)` 当前可以按参数个数拿到对应重载方法 + +`FunctionInfo` 的最小已验证字段: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type A = class + class function Add(a: lhs; b: rhs): sum_t; + begin + return a + b; + end; +end; +begin + f := ThisFunction(class(A).Add); + info := f.FunctionInfo; + WriteLn(info["functionname"]); + WriteLn(info["returntype"]); + WriteLn(info["classname"]); +end. +``` + +已验证运行结果: + +- 依次输出 `add`、`sum_t`、`a` +- 说明 `FunctionInfo["functionname"]`、`["returntype"]`、`["classname"]` 当前都可直接读取 +- 当前这个最小例子里,返回的函数名和类名表现为小写标识符 + +`TSLObjects(1)`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TestClass01 = class + value; + function create(_value); + begin + value := _value; + end; + class function add(x, y); + begin + return x + y; + end; +end; +begin + objA := new TestClass01(100); + objB := new TestClass01(101); + objsInfo := TSLObjects(1); + WriteLn(length(objsInfo["TestClass01"])); + newObjA := objsInfo["TestClass01"][0, "obj"]; + WriteLn(newObjA is class(TestClass01)); + WriteLn(newObjA.add(1, 2)); +end. +``` + +已验证运行结果: + +- 依次输出 `2`、`1`、`3` +- 说明 `TSLObjects(1)` 当前可以按类名拿到对象分组 +- 分组项里的 `"obj"` 字段当前可以重新拿到可调用对象 + +引用计数的最小行为: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type T1 = class + function destroy(); + begin + WriteLn("destroy"); + end; +end; +begin + o1 := new T1(); + o2 := o1; + o1 := 0; + WriteLn("O1 to Zero"); + o2 := 0; + WriteLn("O2 to Zero"); +end. +``` + +已验证运行结果: + +- 依次输出 `O1 to Zero`、`destroy`、`O2 to Zero` +- 说明只清空第一个别名时对象还不会释放 +- 最后一个引用清空后才会触发 `destroy()` + +## 跳转指引 + +- 回看类的基础语法:见 [09_objects_and_classes.md](09_objects_and_classes.md) +- 回看函数值与基础调用:见 [06_functions_and_calls.md](06_functions_and_calls.md) +- 看运行时内置对象:见 [24_builtin_runtime_objects.md](24_builtin_runtime_objects.md) +- 看对象算符重载:见 [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) diff --git a/docs/tsl/syntax/24_builtin_runtime_objects.md b/docs/tsl/syntax/24_builtin_runtime_objects.md new file mode 100644 index 00000000..46d33223 --- /dev/null +++ b/docs/tsl/syntax/24_builtin_runtime_objects.md @@ -0,0 +1,166 @@ +# Builtin Runtime Objects + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)、[30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 24 篇,共 32 篇。上一篇:[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)。下一篇:[25_set_operations.md](25_set_operations.md)。 + +这一篇只收当前解释器下已经实际跑通的运行时内置对象最小模型。这里讲的是语言运行时对象,不是金融业务 API。 + +## 这一篇解决什么问题 + +回答“写普通 TSL/TSF 脚本时,哪些内置对象可以直接创建,最小可用接口是什么,哪些对象其实依赖特定运行上下文”。 + +## 必须记住的规则 + +- 当前 CLI 里,`TStringList` 已验证可以直接 `CreateObject("TStringList")` 创建。 +- `TStringList` 当前已验证支持数字下标、字符串键下标、`Count` 和 `Add(...)`。 +- 流对象应先按 `TStream` 家族理解;当前 CLI 里最小可靠入口是 `TMemoryStream` 这种具体类型。 +- 当前 CLI 里,直接 `CreateObject("TStream")` 会失败,错误信息包含 `function:tstream compile error or not found`。 +- `TMemoryStream` 当前已验证支持 `Write(...)`、`Read(...)`、`Position`、`Size`。 +- `TCipher` 当前不是“无参即可创建”的对象;`CreateObject("TCipher")` 会失败。 +- `TCipher` 当前已验证可用的最小写法是 `CreateObject("TCipher", 2)`,然后设置 `Password` 再做 `Encrypt(...)` / `Decrypt(...)`。 +- `TWebRequest` 和 `TWebResponse` 在当前 CLI 环境里没有通过直接 `CreateObject(...)` 的最小样例。 +- 因此,WEB 请求 / 响应对象不要直接写进普通命令行脚本模板;它们应视为特定运行上下文对象。 + +## 已验证语法 + +### `TStringList` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + obj := CreateObject("TStringList"); + obj.CommaText := "A=aaa,B=bbb,C=222"; + WriteLn(obj[1]); + WriteLn(obj["B"]); + WriteLn(obj.Count); + obj.Add("D=444"); + WriteLn(obj.Count); +end. +``` + +已验证运行结果: + +- 依次输出 `B=bbb`、`bbb`、`3`、`4` +- 说明当前既可以按数字下标取整行,也可以按键名取 `Name=Value` 里的值 + +### `TStream` 家族的最小可靠入口:`TMemoryStream` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + mem := CreateObject("TMemoryStream"); + buffer := "ABC"; + mem.Write(buffer, 3); + mem.Position := 0; + outbuf := "xxx"; + mem.Read(outbuf, 3); + WriteLn(outbuf); + WriteLn(mem.Size); + try + base := CreateObject("TStream"); + WriteLn(ifObj(base)); + except + WriteLn("TStreamError"); + WriteLn(ExceptObject.ErrInfo); + end; +end. +``` + +已验证运行结果: + +- 前两行输出 `ABC`、`3` +- 后两行输出 `TStreamError`,以及包含 `function:tstream compile error or not found` 的错误信息 +- 说明当前 CLI 里应优先使用 `TMemoryStream` 这类具体流对象,不要把裸 `TStream` 当成可直接创建对象 + +### `TCipher` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + try + bad := CreateObject("TCipher"); + WriteLn("NoArg"); + WriteLn(ifObj(bad)); + except + WriteLn("NoArgError"); + WriteLn(ExceptObject.ErrInfo); + end; + + cipher := CreateObject("TCipher", 2); + cipher.Password := "Tinysoft"; + enc := cipher.Encrypt("abc"); + WriteLn(enc <> "abc"); + WriteLn(cipher.Decrypt(enc)); +end. +``` + +已验证运行结果: + +- 前两行输出 `NoArgError`,以及包含 `New Class tcipher Error.` 的错误信息 +- 后两行输出 `1`、`abc` +- 说明 `TCipher` 当前必须按“带模式参数创建”来写,随后可稳定走 `Password -> Encrypt -> Decrypt` + +### `TWebRequest` / `TWebResponse` 的 CLI 边界 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + try + req := CreateObject("TWebRequest"); + WriteLn("ReqOk"); + WriteLn(ifObj(req)); + except + WriteLn("ReqError"); + WriteLn(ExceptObject.ErrInfo); + end; + + try + resp := CreateObject("TWebResponse"); + WriteLn("RespOk"); + WriteLn(ifObj(resp)); + except + WriteLn("RespError"); + WriteLn(ExceptObject.ErrInfo); + end; +end. +``` + +已验证运行结果: + +- 先输出 `ReqError`,随后错误信息包含 `function:twebrequest compile error or not found` +- 再输出 `RespError`,随后错误信息包含 `function:twebresponse compile error or not found` +- 说明当前 CLI 环境下,WEB 请求 / 响应对象不能直接按普通 `CreateObject(...)` 脚本对象来写 + +## 暂不在本页展开的对象 + +- `TFileStream` +- `TIniFile` +- `TMemIniFile` +- `THashedStringList` +- `TRSA` +- `FTP` / `SMTP` / `POP3` +- `MailMsg` / `MessagePart` +- `TCookie` / `TCookieCollection` +- `TSessionMan` / `TSession` + +这些对象旧资料里都出现过,但当前这一篇先只保留“新 session 最容易直接用到”的最小主干。需要把其中某个对象升级进主线正文时,应先补最小脚本再写结论。 + +## 跳转指引 + +- 回看对象主线:见 [09_objects_and_classes.md](09_objects_and_classes.md) +- 看对象运行时反射:见 [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) +- 看运行时服务与缓存:见 [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) +- 看对象重载与遍历:见 [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) diff --git a/docs/tsl/syntax/25_set_operations.md b/docs/tsl/syntax/25_set_operations.md new file mode 100644 index 00000000..c09a9618 --- /dev/null +++ b/docs/tsl/syntax/25_set_operations.md @@ -0,0 +1,167 @@ +# Set Operations + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[14_resultset_and_filters.md](14_resultset_and_filters.md)、[13_matrix_and_collections.md](13_matrix_and_collections.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 25 篇,共 32 篇。上一篇:[24_builtin_runtime_objects.md](24_builtin_runtime_objects.md)。下一篇:[26_matrix_deep_dive.md](26_matrix_deep_dive.md)。 + +这一篇只讲集合运算本身:`in`、`sqlin`、`union2`、`intersect`、`minus`、`outersect`。它和 [14_resultset_and_filters.md](14_resultset_and_filters.md) 的分工很明确: 这一篇讲“去重后的集合关系”,过滤页讲“按原结果集逐行保留或排除”。 + +## 这一篇解决什么问题 + +回答“某个元素是否在数组里、某组元素是否构成子集、某一行是否存在于结果集中,以及两个结果集如何做并集、交集、差集和对称差集”。 + +## 必须记住的规则 + +- `in` / `not in` 处理的是元素存在关系,以及左侧为数组时的子集关系。 +- `sqlin` / `not sqlin` 处理的是行存在关系;左侧要当成一整行去匹配右侧结果集。 +- `union2`、`intersect`、`minus`、`outersect` 都按“行”运算,而不是按单元格逐个运算。 +- 当前解释器支持 `not in` 和 `not sqlin` 这种否定写法。 +- 集合运算结果会折叠重复行;如果需求是保留重复记录,不要用这一篇的算符,改看 [14_resultset_and_filters.md](14_resultset_and_filters.md)。 +- 当数据本身就是一维数组时,按行集合运算和按元素集合运算是一致的。 + +## 已验证语法 + +### `in` 与 `not in` + +`in` 既可以判断单个元素是否存在,也可以判断左侧数组是否是右侧结果集的子集: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(1 in array(1, 2, 2)); + WriteLn(1 in array(0, 2)); + WriteLn(1 in array((1), (2))); + WriteLn(array(1, 2) in array(1, 2, 3, 4)); + WriteLn(array(1, 3) in array((1, 2), (3, 4))); + WriteLn(array(1, 2) in array(1)); + WriteLn(1 not in array(0, 2)); +end. +``` + +已验证运行结果: + +- `1 in array(1, 2, 2)` 输出 `1` +- `1 in array(0, 2)` 输出 `0` +- `1 in array((1), (2))` 输出 `1` +- `array(1, 2) in array(1, 2, 3, 4)` 输出 `1` +- `array(1, 3) in array((1, 2), (3, 4))` 输出 `1` +- `array(1, 2) in array(1)` 输出 `0` +- `1 not in array(0, 2)` 输出 `1` + +### `sqlin` 与 `not sqlin` + +`sqlin` 改成按整行判断左侧是否存在于右侧结果集中: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + WriteLn(1 sqlin array(1, 2)); + WriteLn(array(1, 2) sqlin array(1, 2, 3)); + WriteLn(array(1, 2) sqlin array((1, 2), (3, 4))); + WriteLn(array(5, 6) not sqlin array((1, 2), (3, 4))); +end. +``` + +已验证运行结果: + +- `1 sqlin array(1, 2)` 输出 `1` +- `array(1, 2) sqlin array(1, 2, 3)` 输出 `0` +- `array(1, 2) sqlin array((1, 2), (3, 4))` 输出 `1` +- `array(5, 6) not sqlin array((1, 2), (3, 4))` 输出 `1` + +可以把两者的差异直接记成一句话: + +- `in` 看元素或子集 +- `sqlin` 看整行 + +### 行集合的并、交、差、对称差 + +下面这组最小例子同时验证了“按行运算”和“结果会折叠重复行”: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + A := array((1, 2), (1, 2), (2, 3)); + B := array((1, 2), (3, 4)); + U := A union2 B; + I := A intersect B; + M := A minus B; + O := A outersect B; +end. +``` + +已验证运行结果: + +- `A union2 B` 共有三行:`(1,2)`、`(2,3)`、`(3,4)` +- `A intersect B` 只有一行:`(1,2)` +- `A minus B` 只有一行:`(2,3)` +- `A outersect B` 有两行:`(2,3)`、`(3,4)` +- `A` 原本有两行相同的 `(1,2)`,但 `union2` / `intersect` 的结果都只保留一份,说明集合运算会折叠重复行 + +如果你需要看更大的四列结果集例子,当前解释器下也已经实测过: + +- `array((1,2,3,4),(2,3,4,5),(1,1,1,1)) union2 array((1,2,3,4),(3,4,5,6),(2,2,2,2))` + 返回 `array((1,2,3,4),(2,3,4,5),(1,1,1,1),(3,4,5,6),(2,2,2,2))` +- 同一组输入下: + `intersect` 返回 `array((1,2,3,4))` +- 同一组输入下: + `minus` 返回 `array((2,3,4,5),(1,1,1,1))` +- 同一组输入下: + `outersect` 返回 `array((2,3,4,5),(1,1,1,1),(3,4,5,6),(2,2,2,2))` + +## 和过滤运算的区别 + +- 集合运算先把数据当成“行集合”来看,再做包含、并交差。 +- 过滤运算先保留“原结果集里的每一条命中记录”;因此重复行会保留下来。 +- 你要的是“集合关系”,看这一篇。 +- 你要的是“从原表里筛出哪些行”,看 [14_resultset_and_filters.md](14_resultset_and_filters.md)。 + +## 最小可编译示例 + +如果你只想先记住最短写法,从这里开始: + +代码块身份:已验证可执行示例 + +```tsl +Matched := 1 in array(1, 2, 3); +``` + +## 常见误写 + +- 把 `in` 和 `sqlin` 当成同一个概念。 +- 期待 `union2` 保留重复行。 +- 用集合运算去做“保留原始重复记录”的过滤任务。 +- 把二维结果集默认当成“按元素逐个比较”的集合运算。 + +代码块身份:反例 / 不可照写 + +```text +Matched := array(1, 2) in array((1, 2), (3, 4)); +``` + +上面这类写法不要直接理解成“左边这一整行是否存在于右边”。当前手册里,整行存在判断统一写成 `sqlin`,避免把 `in` 的子集语义和行匹配语义混在一起。 + +代码块身份:反例 / 不可照写 + +```text +OnlyLeft := A minus B; +``` + +如果你的任务要求保留 `A` 里重复出现的命中次数,上面这种集合差集就不是合适工具,因为它会把结果当成集合而不是原始记录流。 + +## 跳转指引 + +- 回看表达式和逻辑运算:见 [07_expressions_and_operators.md](07_expressions_and_operators.md) +- 看数组、嵌套数组和子矩阵:见 [13_matrix_and_collections.md](13_matrix_and_collections.md) +- 看结果集过滤:见 [14_resultset_and_filters.md](14_resultset_and_filters.md) +- 进入矩阵深水专题:见 [26_matrix_deep_dive.md](26_matrix_deep_dive.md) diff --git a/docs/tsl/syntax/26_matrix_deep_dive.md b/docs/tsl/syntax/26_matrix_deep_dive.md new file mode 100644 index 00000000..08d20a3c --- /dev/null +++ b/docs/tsl/syntax/26_matrix_deep_dive.md @@ -0,0 +1,175 @@ +# Matrix Deep Dive + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[13_matrix_and_collections.md](13_matrix_and_collections.md)、[27_fmarray.md](27_fmarray.md)、[25_set_operations.md](25_set_operations.md) + +手册位置:第 26 篇,共 32 篇。上一篇:[25_set_operations.md](25_set_operations.md)。下一篇:[27_fmarray.md](27_fmarray.md)。 + +这一篇开始讲真正的矩阵语法主干:矩阵初始化、数列构造,以及怎样读取矩阵的行列大小和索引。它和 [13_matrix_and_collections.md](13_matrix_and_collections.md) 的分工是:`13` 只讲数组与矩阵样数据,这一篇开始讲矩阵专用构造与大小接口。 + +## 这一篇解决什么问题 + +回答“怎样直接构造全零矩阵、全一矩阵、随机矩阵、单位矩阵、空矩阵和数列数组,以及怎样拿到矩阵的行数、列数、行索引和列索引”。 + +## 必须记住的规则 + +- `Zeros(...)`、`Ones(...)`、`Rand(...)`、`Nils(...)`、`Eye(...)` 都可以直接用于矩阵初始化。 +- `Zeros(3)`、`Ones(3)`、`Nils(2)` 这类单参数写法可以直接生成一维结果。 +- `Zeros(2, 3)`、`Rand(2, 3)` 这类双参数写法可以直接生成二维矩阵。 +- `Zeros(2, array("A", "B"))` 这种写法可以直接生成带列名的二维结果。 +- `Eye(3)` 生成的是 `3 x 3` 单位矩阵,不是一维数组。 +- `->` 用来生成数列;默认步长是 `1`,也可以显式传入步长和索引数组。 +- `MSize(A)` 返回 `array(行数, 列数)`。 +- `MSize(A, 1)` 返回行索引数组和列索引数组。 +- `MRows(A)` / `MCols(A)` 默认返回数量;第二个参数写成 `1` 时返回索引数组。 + +## 已验证语法 + +### 矩阵初始化 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + Z1 := Zeros(3); + Z2 := Zeros(2, 3); + O1 := Ones(3); + N1 := Nils(2); + E1 := Eye(3); + R1 := Rand(2, 3); + T1 := Zeros(2, array("A", "B")); +end. +``` + +已验证运行结果: + +- `Zeros(3)` 的长度是 `3`,前三个元素依次是 `0`、`0`、`0` +- `Zeros(2, 3)` 的行数是 `2`、列数是 `3`,第一行前三个元素是 `0`、`0`、`0` +- `Ones(3)` 的前三个元素依次是 `1`、`1`、`1` +- `Nils(2)` 已验证可直接生成长度为 `2` 的结果 +- `Eye(3)` 的行数是 `3`、列数是 `3`,并且 `(0,0)`、`(1,1)`、`(2,2)` 为 `1`,`(0,1)`、`(1,0)` 为 `0` +- `Rand(2, 3)` 的行数是 `2`、列数是 `3` +- `Zeros(2, array("A", "B"))` 的行数是 `2`、列数是 `2`,并且 `T1[0]["A"]`、`T1[0]["B"]`、`T1[1]["A"]`、`T1[1]["B"]` 都是 `0` + +### `->` 数列数组初始化 + +默认步长为 `1`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + S1 := 1 -> 5; +end. +``` + +已验证运行结果: + +- `S1` 是 `array(1, 2, 3, 4, 5)` + +显式指定步长: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + S2 := array(2.5, 0.5) -> 5; +end. +``` + +已验证运行结果: + +- `S2` 的长度是 `6` +- 六个元素依次是 `2.5`、`3`、`3.5`、`4`、`4.5`、`5` + +显式指定索引数组: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + S3 := array(0, 1, array("A", "B", "C", "D", "E", "F")) -> 5; +end. +``` + +已验证运行结果: + +- `S3` 的长度是 `6` +- `S3["A"]` 到 `S3["F"]` 依次是 `0`、`1`、`2`、`3`、`4`、`5` + +### `MSize`、`MRows`、`MCols` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + A := array( + ("A": 1, "B": 2), + ("A": 11, "B": 22), + ("A": 21, "B": 32) + ); + SizeInfo := MSize(A); + SizeIndex := MSize(A, 1); + RowCount := MRows(A); + RowIndex := MRows(A, 1); + ColCount := MCols(A); + ColIndex := MCols(A, 1); +end. +``` + +已验证运行结果: + +- `MSize(A)` 返回 `array(3, 2)` +- `MSize(A, 1)` 的第一项是 `array(0, 1, 2)`,第二项是 `array("A", "B")` +- `MRows(A)` 返回 `3` +- `MRows(A, 1)` 返回 `array(0, 1, 2)` +- `MCols(A)` 返回 `2` +- `MCols(A, 1)` 返回 `array("A", "B")` + +## 最小可编译示例 + +如果你只想先记住最短矩阵构造,从这个开始: + +代码块身份:已验证可执行示例 + +```tsl +M := Zeros(2, 3); +``` + +## 常见误写 + +- 把 `Eye(3)` 当成一维数组。 +- 以为 `MRows(A, 1)` 和 `MCols(A, 1)` 返回的还是数量。 +- 写带步长的 `->` 时,漏掉外层 `array(...)`。 +- 还在普通数组页里硬塞矩阵专用大小接口。 + +代码块身份:反例 / 不可照写 + +```text +S := 2.5, 0.5 -> 5; +``` + +上面这种写法不对。显式步长模式需要写成 `array(2.5, 0.5) -> 5`。 + +代码块身份:反例 / 不可照写 + +```text +Cols := MCols(A, 1); +``` + +不要把上面这一句的返回值当成数字 `2`。当前解释器下,`MCols(A, 1)` 返回的是列索引数组,例如 `array("A", "B")`。 + +## 跳转指引 + +- 回看数组与嵌套数组:见 [13_matrix_and_collections.md](13_matrix_and_collections.md) +- 看结果集过滤:见 [14_resultset_and_filters.md](14_resultset_and_filters.md) +- 看集合运算:见 [25_set_operations.md](25_set_operations.md) +- 进入 `FMArray`:见 [27_fmarray.md](27_fmarray.md) diff --git a/docs/tsl/syntax/27_fmarray.md b/docs/tsl/syntax/27_fmarray.md new file mode 100644 index 00000000..232a7f5d --- /dev/null +++ b/docs/tsl/syntax/27_fmarray.md @@ -0,0 +1,535 @@ +# FMArray + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[26_matrix_deep_dive.md](26_matrix_deep_dive.md)、[13_matrix_and_collections.md](13_matrix_and_collections.md)、[28_ts_sql_core.md](28_ts_sql_core.md) + +手册位置:第 27 篇,共 32 篇。上一篇:[26_matrix_deep_dive.md](26_matrix_deep_dive.md)。下一篇:[28_ts_sql_core.md](28_ts_sql_core.md)。 + +这一篇只讲当前解释器下已经实际跑通的 `FMArray` 主干能力:怎样构造 `FMArray`、怎样判断类型、怎样和 `Array` 互转、怎样读取尺寸、做基础运算、做多维转置与维度交换、做矩阵连接、参与 `select/mselect`,以及当前可用的 `insert/delete/update` 语法边界。 + +## 这一篇解决什么问题 + +回答“什么时候该用 `FMArray` 而不是普通 `array`,以及当前解释器里最可靠的 `FMArray` 写法到底有哪些”。 + +## 必须记住的规则 + +- `fmarray[...]` 可以直接构造 `FMArray` 常量。 +- `datatype(v)` 对 `FMArray` 返回 `27`。 +- `datatype(v, 1)` 可以读出 `FMArray` 单元格类型;当前已验证到 `0` 整型、`1` 浮点、`20` 64 位整型。 +- `ifFMArray(v)` 可直接判断值是否为 `FMArray`。 +- `MInit`、`MInitDiag`、`MRand` 都可直接生成 `FMArray`。 +- `ArrayToFM` 和 `MatrixToArray` 可在 `Array` / `FMArray` 间互转。 +- `MSize`、`MRows`、`MCols` 都支持 `FMArray`;对三维 `FMArray`,`MSize` 已验证会返回全部维度长度。 +- `FMArray` 已验证支持和标量、`FMArray`、`Array` 做基础算符运算。 +- `union2` 已验证支持 `FMArray` / `Array` 混合运算;结果类型跟随左值。 +- 对超过二维的 `FMArray`,反引号转置会把全部维度倒置;`mswap` 可只交换指定维度。 +- `union` 可做按行连接且不去重,但列结构必须兼容。 +- `|` 和 `:|` 都可做按列连接;当前已验证到行数不一致时会用 `0` 补齐,并且两者表现一致。 +- 对 `FMArray` 做普通 `select` 不会保留 `FMArray` 类型;`mselect` 也不会返回 `datatype=27`。 +- 当前实测里,`insert into a array(...)`、`delete from a where ...;`、`update a set ... where ... end;` 都能作用于 `FMArray`,但三者的收尾形式并不完全相同。 + +## 已验证语法 + +### 常量构造与类型判断 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f1 := fmarray[1, 2, 3]; + f2 := fmarray[[1, 2], [3, 4]]; + f3 := fmarray[1.0, 2.0, 3.5]; + WriteLn(datatype(f1)); + WriteLn(datatype(f1, 1)); + WriteLn(datatype(f3, 1)); + WriteLn(ifFMarray(f1)); + WriteLn(length(f1)); + WriteLn(f1[0], ',', f1[1], ',', f1[2]); + WriteLn(mrows(f2)); + WriteLn(mcols(f2)); + WriteLn(f2[0,0], ',', f2[0,1], ',', f2[1,0], ',', f2[1,1]); +end. +``` + +已验证运行结果: + +- `datatype(f1)` 返回 `27` +- `datatype(f1, 1)` 返回 `0` +- `datatype(f3, 1)` 返回 `1` +- `ifFMarray(f1)` 返回 `1` +- `length(f1)` 返回 `3` +- `f1` 的三个元素依次是 `1`、`2`、`3` +- `f2` 的行数是 `2`、列数是 `2` +- `f2` 四个单元依次是 `1`、`2`、`3`、`4` + +### `MInit`、`MInitDiag`、`MRand` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + fm1 := MInit(5, 3); + fm2 := MInit(array(3, 2), 1L); + fd1 := MInitDiag(3, 3, 1); + fr1 := MRand(2, 3); + WriteLn(datatype(fm1, 1)); + WriteLn(length(fm1)); + WriteLn(fm1[0], ',', fm1[1], ',', fm1[2], ',', fm1[3], ',', fm1[4]); + WriteLn(datatype(fm2, 1)); + WriteLn(mrows(fm2)); + WriteLn(mcols(fm2)); + WriteLn(fd1[0,0], ',', fd1[0,1], ',', fd1[1,0], ',', fd1[1,1], ',', fd1[2,2]); + WriteLn(mrows(fr1)); + WriteLn(mcols(fr1)); +end. +``` + +已验证运行结果: + +- `MInit(5, 3)` 生成长度为 `5` 的整型 `FMArray`,五个元素都是 `3` +- `datatype(fm1, 1)` 返回 `0` +- `MInit(array(3, 2), 1L)` 的单元格类型是 `20` +- `fm2` 的行数是 `3`、列数是 `2` +- `MInitDiag(3, 3, 1)` 的 `(0,0)`、`(1,1)`、`(2,2)` 为 `1`,而 `(0,1)`、`(1,0)` 为 `0` +- `MRand(2, 3)` 的行数是 `2`、列数是 `3` + +### `ArrayToFM`、`MatrixToArray` 与单元格类型转换 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a1 := array(1, 2, 3.5); + f1 := ArrayToFM(a1, 0); + f2 := ArrayToFM(a1, 0.0); + f3 := int64(fmarray[1, 2, 3]); + a2 := MatrixToArray(fmarray[[1, 2], [3, 8]]); + WriteLn(datatype(f1, 1)); + WriteLn(f1[0], ',', f1[1], ',', f1[2]); + WriteLn(datatype(f2, 1)); + WriteLn(f2[0], ',', f2[1], ',', f2[2]); + WriteLn(datatype(f3, 1)); + WriteLn(f3[0], ',', f3[1], ',', f3[2]); + WriteLn(mrows(a2)); + WriteLn(mcols(a2)); + WriteLn(a2[0][0], ',', a2[0][1], ',', a2[1][0], ',', a2[1][1]); +end. +``` + +已验证运行结果: + +- `ArrayToFM(a1, 0)` 的单元格类型是 `0`,结果是 `1,2,3` +- `ArrayToFM(a1, 0.0)` 的单元格类型是 `1`,结果是 `1,2,3.5` +- `int64(fmarray[1, 2, 3])` 的单元格类型是 `20` +- `MatrixToArray(fmarray[[1, 2], [3, 8]])` 返回一个 `2 x 2` 的 `Array`,内容是 `(1,2)`、`(3,8)` + +### 尺寸与重构 + +二维和三维尺寸: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f3 := fmarray[[[1, 1], [2, 2], [3, 3]], [[2, 2], [3, 3], [4, 4]]]; + s := MSize(f3); + WriteLn(length(s)); + WriteLn(s[0], ',', s[1], ',', s[2]); +end. +``` + +已验证运行结果: + +- `MSize(f3)` 的长度是 `3` +- 三个维度依次是 `2`、`3`、`2` + +`reshape` 会保持 `FMArray` 类型: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f1 := fmarray[[1, 2], [3, 4], [5, 5]]; + r1 := reshape(f1, 6); + WriteLn(datatype(r1)); + WriteLn(length(r1)); + WriteLn(r1[0], ',', r1[1], ',', r1[2], ',', r1[3], ',', r1[4], ',', r1[5]); +end. +``` + +已验证运行结果: + +- `datatype(r1)` 仍然是 `27` +- `r1` 的长度是 `6` +- 元素依次是 `1`、`2`、`3`、`4`、`5`、`5` + +### 标量运算与基础算符 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f1 := fmarray[1, 2, 3]; + f2 := fmarray[2, 3, 4]; + a1 := array(2, 3, 4); + s0 := f1 + 1; + s1 := f1 + f2; + s2 := f1 + a1; + WriteLn(datatype(s0)); + WriteLn(s0[0], ',', s0[1], ',', s0[2]); + WriteLn(datatype(s1)); + WriteLn(s1[0], ',', s1[1], ',', s1[2]); + WriteLn(datatype(s2)); + WriteLn(s2[0], ',', s2[1], ',', s2[2]); +end. +``` + +已验证运行结果: + +- `f1 + 1` 的 `datatype` 是 `27`,结果是 `2,3,4` +- `f1 + f2` 的 `datatype` 是 `27`,结果是 `3,5,7` +- `f1 + array(2, 3, 4)` 的 `datatype` 仍是 `27`,结果也是 `3,5,7` + +### `union2` 与左值类型 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f1 := fmarray[1, 2, 0, 4, 5]; + a1 := array(1, 0, 7.2); + u1 := f1 union2 a1; + u2 := a1 union2 f1; + WriteLn(datatype(u1)); + WriteLn(datatype(u1, 1)); + WriteLn(length(u1)); + WriteLn(u1[0], ',', u1[1], ',', u1[2], ',', u1[3], ',', u1[4], ',', u1[5]); + WriteLn(datatype(u2)); + WriteLn(length(u2)); + WriteLn(u2[0], ',', u2[1], ',', u2[2], ',', u2[3], ',', u2[4], ',', u2[5]); +end. +``` + +已验证运行结果: + +- `union2` 的结果 `datatype` 是 `27` +- `f1 union2 array(1, 0, 7.2)` 的单元格类型会提升为 `1` 浮点型 +- `f1 union2 array(1, 0, 7.2)` 的长度是 `6`,结果是 `1,2,0,4,5,7.2` +- `array(1, 0, 7.2) union2 f1` 的 `datatype` 是 `5` +- `array(1, 0, 7.2) union2 f1` 的长度也是 `6`,结果是 `1,0,7.2,2,4,5` + +### 多维转置与维度交换 + +三维 `FMArray` 上,反引号转置会把全部维度倒置: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f3 := fmarray[[[1], [2]], [[1], [0]], [[3], [-8]]]; + t := `f3; + s := MSize(t); + WriteLn(datatype(t)); + WriteLn(length(s)); + WriteLn(s[0], ',', s[1], ',', s[2]); + WriteLn(t[0,0,0], ',', t[0,0,1], ',', t[0,0,2], ';', t[0,1,0], ',', t[0,1,1], ',', t[0,1,2]); +end. +``` + +已验证运行结果: + +- 原矩阵尺寸是 `3,2,1`,转置后尺寸是 `1,2,3` +- 结果 `datatype` 仍是 `27` +- 转置后的内容是 `[[[1,1,3],[2,0,-8]]]` + +只交换指定维度时,使用 `mswap`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f3 := fmarray[[[1], [2]], [[1], [0]], [[3], [-8]]]; + t := mswap(f3, 0, 1); + s := MSize(t); + WriteLn(datatype(t)); + WriteLn(length(s)); + WriteLn(s[0], ',', s[1], ',', s[2]); + WriteLn(t[0,0,0], ',', t[0,1,0], ',', t[0,2,0], ';', t[1,0,0], ',', t[1,1,0], ',', t[1,2,0]); +end. +``` + +已验证运行结果: + +- `mswap(f3, 0, 1)` 后尺寸是 `2,3,1` +- 结果 `datatype` 仍是 `27` +- 结果内容是 `[[[1],[1],[3]],[[2],[0],[-8]]]` + +### 矩阵连接:`union`、`|`、`:|` + +`union` 会按行拼接,不做去重: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + t1 := fmarray[[1, 2], [3, 4], [5, 5]]; + t2 := fmarray[[7, 8]]; + u := t1 union t2; + WriteLn(datatype(u)); + WriteLn(mrows(u)); + WriteLn(mcols(u)); + WriteLn(u[0,0], ',', u[0,1], ';', u[1,0], ',', u[1,1], ';', u[2,0], ',', u[2,1], ';', u[3,0], ',', u[3,1]); +end. +``` + +已验证运行结果: + +- `union` 的结果 `datatype` 是 `27` +- `t1 union t2` 的行数是 `4`、列数是 `2` +- 拼接后四行依次是 `(1,2)`、`(3,4)`、`(5,5)`、`(7,8)` + +`|` 和 `:|` 会按列拼接: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + t1 := fmarray[[1, 2], [3, 4], [5, 5]]; + t2 := fmarray[[3, 4], [7, 8], [6, 9]]; + u1 := t1 | t2; + u2 := t1 :| t2; + WriteLn(datatype(u1)); + WriteLn(mrows(u1)); + WriteLn(mcols(u1)); + WriteLn(u1[0,0], ',', u1[0,1], ',', u1[0,2], ',', u1[0,3]); + WriteLn(u1[1,0], ',', u1[1,1], ',', u1[1,2], ',', u1[1,3]); + WriteLn(u1[2,0], ',', u1[2,1], ',', u1[2,2], ',', u1[2,3]); + WriteLn(u2[0,0], ',', u2[0,1], ',', u2[0,2], ',', u2[0,3]); + WriteLn(u2[1,0], ',', u2[1,1], ',', u2[1,2], ',', u2[1,3]); + WriteLn(u2[2,0], ',', u2[2,1], ',', u2[2,2], ',', u2[2,3]); +end. +``` + +已验证运行结果: + +- `|` 的结果 `datatype` 是 `27` +- `t1 | t2` 和 `t1 :| t2` 的行数都是 `3`、列数都是 `4` +- 两种写法的结果都依次是 `(1,2,3,4)`、`(3,4,7,8)`、`(5,5,6,9)` + +当前还额外验证到:行数不一致时,`|` 和 `:|` 在 `FMArray` 上表现一致,缺失行会用 `0` 补齐。 + +- `fmarray[[1, 2], [3, 4], [5, 5]] | fmarray[[3, 4]]` 的结果三行依次是 `(1,2,3,4)`、`(3,4,0,0)`、`(5,5,0,0)` +- `fmarray[[3, 4]] | fmarray[[1, 2], [3, 4], [5, 5]]` 的结果三行依次是 `(3,4,1,2)`、`(0,0,3,4)`、`(0,0,5,5)` +- 把上面两条里的 `|` 改成 `:|`,结果一致 + +### 排序 + +一维排序: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + s1 := fmarray[10, 2, -3, 8]; + sortarray(s1); + WriteLn(s1[0], ',', s1[1], ',', s1[2], ',', s1[3]); +end. +``` + +已验证运行结果: + +- 排序后结果是 `-3,2,8,10` + +二维按字段排序: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + f1 := fmarray[[11, 12], [31, 4], [5, 5]]; + SortTableByField(f1, 0, 1); + WriteLn(f1[0,0], ',', f1[0,1], ';', f1[1,0], ',', f1[1,1], ';', f1[2,0], ',', f1[2,1]); +end. +``` + +已验证运行结果: + +- 排序后依次是 `(5,5)`、`(11,12)`、`(31,4)` + +### TS-SQL 对 `FMArray` 的支持 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + q1 := select * from fmarray[[1, 2], [0, 4], [1, 2], [5, 6]] end; + q2 := mselect * from fmarray[[1, 2], [0, 4], [1, 2], [5, 6]] end; + WriteLn(datatype(q1)); + WriteLn(mrows(q1)); + WriteLn(datatype(q2)); + WriteLn(mrows(q2)); + WriteLn(mcols(q2)); +end. +``` + +已验证运行结果: + +- 普通 `select` 的返回 `datatype` 是 `5` +- `q1` 的行数是 `4` +- `mselect` 的返回 `datatype` 是 `17` +- `q2` 的行数是 `4`、列数是 `2` +- 说明当前解释器下,对 `FMArray` 做 TS-SQL 查询时,结果不会保留 `datatype=27` + +### `insert` / `delete` / `update` + +`insert`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := MInit(2, 3, 1.0); + insert into a array(9); + WriteLn(mrows(a)); + WriteLn(mcols(a)); + WriteLn(a[2,0], ',', a[2,1], ',', a[2,2]); +end. +``` + +已验证运行结果: + +- 插入后行数是 `3` +- 列数仍是 `3` +- 新插入的第三行是 `9,9,9` + +`delete`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + d := fmarray[[1, 2], [0, 4], [5, 6]]; + delete from d where [1] = 4; + WriteLn(mrows(d)); + WriteLn(d[0,0], ',', d[0,1], ';', d[1,0], ',', d[1,1]); +end. +``` + +已验证运行结果: + +- 删除后行数是 `2` +- 保留的两行是 `(1,2)`、`(5,6)` + +`update`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + u := fmarray[[1, 2], [0, 4], [5, 6]]; + update u set [0] = 100 where [1] = 4 end; + WriteLn(mrows(u)); + WriteLn(u[0,0], ',', u[0,1], ';', u[1,0], ',', u[1,1], ';', u[2,0], ',', u[2,1]); +end. +``` + +已验证运行结果: + +- 更新后行数仍是 `3` +- 结果三行依次是 `(1,2)`、`(100,4)`、`(5,6)` + +当前解释器下,这三种写法的收尾形式已验证为: + +- `insert into a array(9);` +- `delete from d where [1] = 4;` +- `update u set [0] = 100 where [1] = 4 end;` + +## 暂不在本页展开的部分 + +- `MInitDiag` 更高维行为 +- `MRand` 的随机分布参数变体 +- `union` / `|` / `:|` 与普通 `array` 的更多混合边界 +- `left join` / `right join` / 更复杂 SQL 写回 +- CopyOnWrite 的内存级行为 + +这些都要等单独补最小验证后,再进入主线正文。 + +## 最小可编译示例 + +如果你只想先记住最短 `FMArray` 骨架,从这个开始: + +代码块身份:已验证可执行示例 + +```tsl +f := fmarray[1, 2, 3]; +``` + +## 常见误写 + +- 在一个 `FMArray` 常量里混用不同单元格类型。 +- 把 `FMArray` 当成支持字符串下标的 `array`。 +- 以为对 `FMArray` 做普通 `select` 后,结果还是 `datatype=27`。 +- 把 `delete` 和 `update` 的结尾形式写成同一种。 +- 以为 `union` 可以忽略列结构差异。 +- 以为 `array union2 fmarray` 还会返回 `FMArray`。 + +代码块身份:反例 / 不可照写 + +```text +f := fmarray[1, 2.0, 3]; +``` + +上面这种写法在当前解释器里会编译失败,错误信息包含 `fmarray must be same type`。 + +代码块身份:反例 / 不可照写 + +```text +f := fmarray[1, 2, 3]; +WriteLn(f["A"]); +``` + +上面这种写法在当前解释器里会运行报错,错误信息包含 `fmarray index type error`。 + +代码块身份:反例 / 不可照写 + +```text +delete from d where [1] = 4 end; +``` + +这类写法不要直接当成当前默认模板。当前解释器下,我实测 `delete ... end;` 会报 `Statement missing terminator`;已验证可用的是 `delete ...;`。 + +代码块身份:反例 / 不可照写 + +```text +t1 := fmarray[[1, 2], [3, 4]]; +t2 := fmarray[[7, 8, 9]]; +u := t1 union t2; +``` + +上面这种写法会运行报错,错误信息包含 `union dim dismatch`。当前已验证的 `union` 只适用于列结构兼容的 `FMArray`。 + +## 跳转指引 + +- 回看矩阵基础:见 [26_matrix_deep_dive.md](26_matrix_deep_dive.md) +- 看 TS-SQL 基础:见 [28_ts_sql_core.md](28_ts_sql_core.md) +- 看 TS-SQL 进阶:见 [29_ts_sql_advanced.md](29_ts_sql_advanced.md) diff --git a/docs/tsl/syntax/28_ts_sql_core.md b/docs/tsl/syntax/28_ts_sql_core.md new file mode 100644 index 00000000..076ee31e --- /dev/null +++ b/docs/tsl/syntax/28_ts_sql_core.md @@ -0,0 +1,228 @@ +# TS-SQL Core + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[15_ts_sql.md](15_ts_sql.md)、[29_ts_sql_advanced.md](29_ts_sql_advanced.md)、[14_resultset_and_filters.md](14_resultset_and_filters.md) + +手册位置:第 28 篇,共 32 篇。上一篇:[27_fmarray.md](27_fmarray.md)。下一篇:[29_ts_sql_advanced.md](29_ts_sql_advanced.md)。 + +这一篇先收 TS-SQL 最基础、最稳定的一层:如何在内存数组上写 `select` 查询,怎样理解 `select` / `sselect` / `vselect` / `mselect` 的返回形态,以及 `where`、`group by`、`order by`、`ThisRow`、`ThisRowIndex` 这些查询骨架怎么写。 + +## 这一篇解决什么问题 + +回答“第一次写 TS-SQL 时,怎样在不碰 join、数据库表和对象化写回接口的前提下,稳定写出最小查询”。 + +## 必须记住的规则 + +- TS-SQL 查询以 `select`、`sselect`、`vselect` 或 `mselect` 开始,以 `end` 结束。 +- `from` 后面可以直接跟内存数组结果集。 +- 在二维结果集里访问字段,当前稳定写法是 `["字段名"]`。 +- 普通 `select` 默认返回二维数组结果。 +- `sselect` 返回一维数组。 +- `vselect` 直接返回单个值,最适合聚集结果。 +- `mselect` 返回 `Matrix`;当前这一篇只把“返回矩阵且可读取行列信息”提升为已验证规则。 +- `where`、`group by`、`order by` 可以直接接在 `from` 后面继续使用。 +- 对一维数组做 TS-SQL 查询时,优先使用 `ThisRow` 和 `ThisRowIndex`,不要默认把 `[0]` 当成可靠列访问写法。 + +## 已验证语法 + +### 最基础的 `select` + +`select` 在内存数组上可直接返回二维结果: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + R := select ["A"], ["B"] from T end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `3` +- 三行依次是 `(1,3)`、`(2,1)`、`(1,2)` +- 说明 `select ["A"], ["B"] from T end` 会按原顺序返回二维结果集 + +`select *` 也已验证可用: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1) + ); + R := select * from T end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `2` +- 两行依次是 `(1,3)`、`(2,1)` + +### `sselect`、`vselect`、`mselect` + +四种查询入口的差异可以先记这一组: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + S := sselect ["A"] from T end; + V := vselect sumof(["B"]) from T end; + M := mselect * from T end; + C := MCols(M, 1); +end. +``` + +已验证运行结果: + +- `sselect ["A"] from T end` 返回一维数组 `array(1, 2, 1)` +- `vselect sumof(["B"]) from T end` 返回单值 `6` +- `mselect * from T end` 的行数是 `3`、列数是 `2` +- `MCols(M, 1)` 返回列索引 `array("A", "B")` + +当前这篇只把 `mselect` 的“返回 Matrix 且保留行列信息”提升为已验证主干;直接单元格读取规则后续再单独补验证。 + +### `where` 和 `order by` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + R := select * from T where ["B"] > 1 order by ["B"] end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `2` +- 两行依次是 `(1,2)`、`(1,3)` +- 说明 `where ["B"] > 1` 会先筛选,再按 `order by ["B"]` 的升序返回 + +### `group by` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + G := select ["A"], sumof(["B"]) as "SumB" + from T + group by ["A"] + order by ["A"] + end; +end. +``` + +已验证运行结果: + +- `G` 的长度是 `2` +- 第一行是 `(1,5)` +- 第二行是 `(2,1)` +- 说明 `group by ["A"]` 后可以直接接聚集函数,并用 `as "SumB"` 指定返回列名 + +### 一维数组上的 `ThisRow` 与 `ThisRowIndex` + +处理一维数组时,当前最可靠的入口是 `ThisRow` 和 `ThisRowIndex`: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + X := array(10, 20, 30); + Y := sselect ThisRow from X end; + Z := sselect ThisRowIndex from X end; + R := select ThisRow as "Value", ThisRowIndex as "Idx" + from X + where ThisRow > 15 + order by ThisRow + end; +end. +``` + +已验证运行结果: + +- `sselect ThisRow from X end` 返回 `array(10, 20, 30)` +- `sselect ThisRowIndex from X end` 返回 `array(0, 1, 2)` +- 上面的 `select ... from X where ThisRow > 15 order by ThisRow end` 返回两行:`(1,20)`、`(2,30)` + +## 暂不在本页展开的部分 + +- `join` / `with on` +- `ThisGroup` +- `RefMaxOf` / `RefMinOf` +- `insert` / `update` / `delete` +- 面向 SQL 数据源的查询与写回 + +这些内容继续留给 [29_ts_sql_advanced.md](29_ts_sql_advanced.md) 或更深专题,不在这一篇提前写死。 + +## 最小可编译示例 + +如果你只想先记住最短 TS-SQL 骨架,从这个开始: + +代码块身份:已验证可执行示例 + +```tsl +R := select * from T end; +``` + +## 常见误写 + +- 把 `select` 当成普通函数调用,忘了以 `end` 收尾。 +- 在二维结果集里直接写 `A` 而不是 `["A"]`。 +- 需要一维结果时还在用普通 `select`。 +- 处理一维数组时直接把 `[0]` 当成稳定列访问。 +- 把 `vselect` 用在本来应该返回多行结果的场景里。 + +代码块身份:反例 / 不可照写 + +```text +R := select A from T end; +``` + +上面这种写法不要当成当前手册的可靠规则。二维结果集字段访问,当前只把 `["A"]` 这种写法提升为已验证主干。 + +代码块身份:反例 / 不可照写 + +```text +R := select [0] from X end; +``` + +我在 `2026-04-15` 的实测里,这种对一维数组直接用 `[0]` 的写法虽然返回了长度为 `3` 的结果,但取到的值是 `nil`,不能当成可靠入口。对一维数组应改用 `ThisRow` 和 `ThisRowIndex`。 + +## 跳转指引 + +- 回看结果集过滤:见 [14_resultset_and_filters.md](14_resultset_and_filters.md) +- 回看集合与矩阵页:见 [25_set_operations.md](25_set_operations.md) 和 [26_matrix_deep_dive.md](26_matrix_deep_dive.md) +- 进入 TS-SQL 进阶:见 [29_ts_sql_advanced.md](29_ts_sql_advanced.md) diff --git a/docs/tsl/syntax/29_ts_sql_advanced.md b/docs/tsl/syntax/29_ts_sql_advanced.md new file mode 100644 index 00000000..90a68995 --- /dev/null +++ b/docs/tsl/syntax/29_ts_sql_advanced.md @@ -0,0 +1,185 @@ +# TS-SQL Advanced + +文档类型:语法主线 +是否可直接用于生成代码:是 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[28_ts_sql_core.md](28_ts_sql_core.md)、[15_ts_sql.md](15_ts_sql.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 29 篇,共 32 篇。上一篇:[28_ts_sql_core.md](28_ts_sql_core.md)。下一篇:[30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)。 + +这一篇只收当前已经实测通过的 TS-SQL 进阶查询能力:多表 `join`、分组子查询 `ThisGroup`、排序后的原始行下标 `ThisRowIndex`,以及 `RefMaxOf` / `RefMinOf` 这类“取极值所在行的另一列”的写法。 + +## 这一篇解决什么问题 + +回答“基础 `select` 已经会写以后,怎样继续处理多表联接、分组后组内再查、以及极值对应行的引用值”。 + +## 必须记住的规则 + +- 多表 `join` 时,字段访问应写成 `[表序号].["字段名"]`。 +- `ThisGroup` 不是普通值,而是分组后的子结果集;要通过子 `select` / `vselect` 的 `from ThisGroup` 来访问。 +- `ThisRowIndex` 在 `order by` 之后仍可返回原始行位置,而不是排序后的序号。 +- `RefMaxOf(...)` 和 `RefMinOf(...)` 在当前最小例子里可与 `MaxOf(...)` / `MinOf(...)` 配合,取极值所在行的另一列值。 +- 这一篇当前只提升“高级查询”部分;对象化写回接口和更深的时间序列查询仍然暂缓。 + +## 已验证语法 + +### `join` + +最小内存表联接: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + A := array( + ("ID": 1, "V1": 10), + ("ID": 2, "V1": 20) + ); + B := array( + ("ID": 1, "V2": 100), + ("ID": 3, "V2": 300) + ); + R := select [1].["ID"], [1].["V1"], [2].["V2"] + from A join B on [1].["ID"] = [2].["ID"] + end; +end. +``` + +已验证运行结果: + +- `R` 的长度是 `1` +- 唯一一行是 `(1,10,100)` +- 说明当前解释器接受 `from A join B on ...`,并接受 `[1].["字段"]`、`[2].["字段"]` 这种多表字段访问 + +### `ThisGroup` + +分组后可在组内继续做子查询: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3, "Name": "x"), + ("A": 2, "B": 1, "Name": "y"), + ("A": 1, "B": 2, "Name": "z") + ); + G := select ["A"], maxb := maxof(["B"]) as "MaxB", + vselect ["Name"] from ThisGroup where ["B"] = maxb end as "TopName" + from T + group by ["A"] + order by ["A"] + end; +end. +``` + +已验证运行结果: + +- `G` 的长度是 `2` +- 第一行是 `(1,3,"x")` +- 第二行是 `(2,1,"y")` +- 说明 `ThisGroup` 可以在分组上下文里作为子结果集继续 `vselect` + +### `ThisRowIndex` 在排序后仍指向原始位置 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + T := array( + ("A": 1, "B": 3), + ("A": 2, "B": 1), + ("A": 1, "B": 2) + ); + R := select ThisRowIndex as "Idx", ["B"] + from T + order by ["B"] + end; +end. +``` + +已验证运行结果: + +- `R` 的三行依次是 `(1,1)`、`(2,2)`、`(0,3)` +- 说明 `order by ["B"]` 之后,`ThisRowIndex` 仍返回原表中的原始下标 + +### `RefMaxOf` 与 `RefMinOf` + +当前最小样例里,`RefMaxOf` / `RefMinOf` 可以和对应的极值聚集一起使用: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + A := array((6, 20), (5, 20), (9, 2), (2, 20), (7, 18)); + R1 := select maxof([0]) as "MaxA", refmaxof([1]) as "RefB" from A end; + R2 := select minof([0]) as "MinA", refminof([1]) as "RefB" from A end; +end. +``` + +已验证运行结果: + +- `R1` 只有一行,结果是 `(9,2)` +- `R2` 只有一行,结果是 `(2,20)` +- 说明在这个最小例子里,`refmaxof([1])` 取到了 `[0]` 最大值所在行的 `[1]`,`refminof([1])` 取到了 `[0]` 最小值所在行的 `[1]` + +## 暂不在本页展开的部分 + +- `with on` +- `left join` / `right join` / `full join` +- `RefsOf` +- `TSQLInsert` +- `TSQLSetValue` +- `TSQLBatchInsert` +- `TSQLEdit` / `TSQLPost` / `TSQLFinal` +- 更深的时间序列聚集与缓存选项 + +这些内容要等单独补最小验证后,再进入主线正文。 + +## 最小可编译示例 + +如果你只想先记住最短的高级查询骨架,从这个开始: + +代码块身份:已验证可执行示例 + +```tsl +R := select [1].["ID"], [2].["V2"] + from A join B on [1].["ID"] = [2].["ID"] + end; +``` + +## 常见误写 + +- 多表联接时继续写成 `["ID"]`,没有加表序号。 +- 把 `ThisGroup` 当成普通字段或普通变量。 +- 把排序后的 `ThisRowIndex` 误当成排序序号。 +- 在还没验证的情况下,把 `with on`、写回接口和时间序列缓存写进默认模板。 + +代码块身份:反例 / 不可照写 + +```text +R := select ["ID"], ["V1"], ["V2"] + from A join B on ["ID"] = ["ID"] + end; +``` + +上面这种写法不要当成当前手册的可靠规则。多表查询里,当前只把 `[1].["字段"]`、`[2].["字段"]` 这种带表序号的访问方式提升为已验证主干。 + +代码块身份:反例 / 不可照写 + +```text +Value := ThisGroup; +``` + +不要把 `ThisGroup` 当成普通值直接使用。当前可靠入口是 `select ... from ThisGroup end` 或 `vselect ... from ThisGroup end`。 + +## 跳转指引 + +- 回看 TS-SQL 基础:见 [28_ts_sql_core.md](28_ts_sql_core.md) +- 回看 TS-SQL 总入口:见 [15_ts_sql.md](15_ts_sql.md) +- 看运行时与全局缓存:见 [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) diff --git a/docs/tsl/syntax/30_runtime_services_and_global_cache.md b/docs/tsl/syntax/30_runtime_services_and_global_cache.md new file mode 100644 index 00000000..4a51f526 --- /dev/null +++ b/docs/tsl/syntax/30_runtime_services_and_global_cache.md @@ -0,0 +1,205 @@ +# Runtime Services And Global Cache + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[16_debug_and_profiler.md](16_debug_and_profiler.md)、[24_builtin_runtime_objects.md](24_builtin_runtime_objects.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 30 篇,共 32 篇。上一篇:[29_ts_sql_advanced.md](29_ts_sql_advanced.md)。下一篇:[31_complex_and_weakref.md](31_complex_and_weakref.md)。 + +这一篇只讲当前解释器下已经实际跑通的运行时服务主干:`#` 网格调用、`timeout` 后缀,以及全局缓存的最小可用函数组。 + +## 这一篇解决什么问题 + +回答“网格调用现在怎样写,全局缓存最稳的读写方式是什么,以及什么时候缓存值会失效或脱离缓存身份”。 + +## 必须记住的规则 + +- 网格调用的最小写法是 `r := #Func(args);`。 +- 网格调用返回的不是最终值;当前已验证可以用 `dupvalue(r)` 取回结果。 +- `timeout N` 后缀当前已验证可直接接在网格调用后面。 +- `SetGlobalCache(name, value)` 当前已验证返回 `1` 表示设置成功。 +- `GetGlobalCache(name, outVar)` 当前已验证返回 `1` 表示取出成功。 +- 从全局缓存取出的值,`ifcache(v)` 当前会返回 `1`。 +- 一旦对取出的缓存值做本地写入,它会立刻实例化;写入后 `ifcache(v)` 返回 `0`。 +- `CheckGlobalCacheExpired(v)` 对当前版本的缓存返回 `0`;同名缓存被重置后,旧引用会变成过期状态并返回 `1`。 +- 当前已验证:全局缓存取出的值可以直接参与 `select`。 + +## 已验证语法 + +### `#` 网格调用与 `dupvalue` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function AddOne(v); +begin + return v + 1; +end; +begin + WriteLn(dupvalue(#AddOne(5))); +end. +``` + +已验证运行结果: + +- `#AddOne(5)` 可以执行 +- `dupvalue(r)` 返回最终结果 `6` + +### 网格调用的 `timeout` + +代码块身份:已验证可执行示例 + +```tsl +program test; +function AddOne(v); +begin + return v + 1; +end; +begin + WriteLn(dupvalue(#AddOne(5) timeout 3000)); +end. +``` + +已验证运行结果: + +- `timeout 3000` 这种后缀写法可以通过并正常执行 +- 上例输出 `6` + +### `SetGlobalCache`、`GetGlobalCache` 与 `ifcache` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + v1 := array(1, 2, 3); + WriteLn(SetGlobalCache("PB_TEST_GC_BASIC", v1)); + WriteLn(GetGlobalCache("PB_TEST_GC_BASIC", v2)); + WriteLn(ifcache(v2)); + WriteLn(length(v2)); + WriteLn(v2[0], ',', v2[1], ',', v2[2]); +end. +``` + +已验证运行结果: + +- `SetGlobalCache("PB_TEST_GC_BASIC", v1)` 返回 `1` +- `GetGlobalCache("PB_TEST_GC_BASIC", v2)` 返回 `1` +- 取出的 `v2` 上 `ifcache(v2)` 返回 `1` +- `v2` 长度是 `3`,内容是 `1,2,3` + +### `CheckGlobalCacheExpired` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SetGlobalCache("PB_TEST_GC_EXPIRE", array(1, 2, 3)); + GetGlobalCache("PB_TEST_GC_EXPIRE", v); + WriteLn(CheckGlobalCacheExpired(v)); + SetGlobalCache("PB_TEST_GC_EXPIRE", array(1, 2, 3, 4)); + WriteLn(CheckGlobalCacheExpired(v)); +end. +``` + +已验证运行结果: + +- 刚取出的缓存引用上,`CheckGlobalCacheExpired(v)` 返回 `0` +- 同名缓存被重新设置后,旧引用上的 `CheckGlobalCacheExpired(v)` 返回 `1` + +### 写入后会实例化 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + SetGlobalCache("PB_TEST_GC_DETACH", array(1, 2, 3)); + GetGlobalCache("PB_TEST_GC_DETACH", v); + WriteLn(ifcache(v)); + v[0] := 100; + WriteLn(ifcache(v)); + WriteLn(v[0], ',', v[1], ',', v[2]); +end. +``` + +已验证运行结果: + +- 刚取出时 `ifcache(v)` 返回 `1` +- 对 `v[0]` 赋值后,`ifcache(v)` 立即返回 `0` +- 写入后的本地值内容是 `100,2,3` + +### 全局缓存参与 `select` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + src := array((1, 2), (3, 4), (2, 1)); + SetGlobalCache("PB_TEST_GC_SELECT", src); + GetGlobalCache("PB_TEST_GC_SELECT", v); + q := select * from v order by [0] desc end; + WriteLn(datatype(q)); + WriteLn(mrows(q)); + WriteLn(q[0][0], ',', q[0][1], ';', q[1][0], ',', q[1][1], ';', q[2][0], ',', q[2][1]); +end. +``` + +已验证运行结果: + +- 对缓存值做 `select` 可以正常执行 +- 返回结果的 `datatype` 是 `5` +- 行数是 `3` +- 排序后内容依次是 `(3,4)`、`(2,1)`、`(1,2)` + +## 暂不在本页展开的部分 + +- 网格调用里的 `with array(...)` 系统参数传递 +- 网格超时触发错误时的完整边界 +- `GetGlobalCacheInfo`、`ListGlobalCache`、`ListGlobalCacheRemoved` +- 初始化 TSL、监控线程、回收策略与兼容旧系统方案 + +## 最小可编译示例 + +如果你只想先记住最短骨架,从下面这个网格调用模板起步: + +代码块身份:已验证可执行示例 + +```tsl +program test; +function AddOne(v); +begin + return v + 1; +end; +begin + WriteLn(dupvalue(#AddOne(5))); +end. +``` + +需要缓存时,再从 `SetGlobalCache` / `GetGlobalCache` 那一节开始。 + +## 常见误写 + +- 把网格句柄直接当最终值用,而不做 `dupvalue(...)`。 +- 以为从全局缓存取出的值,本地写入后仍然保持缓存身份。 +- 以为旧缓存引用在同名缓存被重置后还会继续视为“未过期”。 + +代码块身份:反例 / 不可照写 + +```text +r := #AddOne(5); +WriteLn(r); +``` + +上面这种写法不要直接当成“已经拿到计算结果”。当前已验证的稳定取值方式是 `dupvalue(r)`。 + +## 跳转指引 + +- 回看调试与 profiler:见 [16_debug_and_profiler.md](16_debug_and_profiler.md) +- 回看运行时环境参数:见 [11_runtime_context_and_with.md](11_runtime_context_and_with.md) +- 回看语法主入口:见 [index.md](index.md) diff --git a/docs/tsl/syntax/31_complex_and_weakref.md b/docs/tsl/syntax/31_complex_and_weakref.md new file mode 100644 index 00000000..a797fa1b --- /dev/null +++ b/docs/tsl/syntax/31_complex_and_weakref.md @@ -0,0 +1,328 @@ +# Complex And WeakRef + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:是 +遇到不确定时跳转到:[09_objects_and_classes.md](09_objects_and_classes.md)、[32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md)、[12_pitfalls.md](12_pitfalls.md) + +手册位置:第 31 篇,共 32 篇。上一篇:[30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md)。下一篇:[32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md)。 + +这一篇只讲当前解释器下已经实际跑通的两组新一代语言能力:复数,以及弱引用 / 自动弱引用里当前真正可靠的最小写法。 + +## 这一篇解决什么问题 + +回答“复数现在到底怎样写,弱引用到底有哪些语法真的能用,哪些历史资料里的写法今天不能直接照抄”。 + +## 必须记住的规则 + +- 复数字面量可以直接写成 `a + bj`,也可以用 `complex(a, b)` 构造。 +- `datatype(z)` 对复数返回 `41`,`ifcomplex(z)` 对复数返回 `1`。 +- `real`、`imag`、`conj`、`abs` 当前都已验证可用。 +- 当前解释器里,实数 `x` 与复数 `x + 0j` 的相等比较结果为真。 +- `complex(array(...), imag)` 会返回 `Array`;`complex(fmarray..., imag)` 会返回 `FMArray`,并且其单元格类型是 `41`。 +- 弱引用能力的条件编译宏当前已验证是 `weakptr`;自动弱引用相关宏是 `AutoWeak`。 +- `weakref(obj)` 可以创建弱引用;对象仍存活时,`weakref_get(w)` 可以拿回强引用。 +- `checkweakref(w)` 当前已验证:对象仍存活时返回 `1`,对象已释放后返回 `-1`。 +- 对已经失效的弱引用直接调用 `weakref_get(w)`,当前解释器里会运行报错,不要把它当成“安全返回 nil”的接口。 +- 类成员上的 `[WeakRef] field;` 和 `[AutoRef] field;` 当前已验证可以通过。 +- `[WeakRef]` 成员不会阻止对象析构;强引用释放后,对象会正常销毁。 +- 历史资料里的类内段落式 `WeakRef;` / `AutoRef;` 在当前解释器里没有通过,错误信息包含 `invalid class definition`。 + +## 已验证语法 + +### 复数常量、类型与基础读取 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + z1 := 4 + 3j; + z2 := complex(5, -2); + WriteLn(datatype(z1)); + WriteLn(ifcomplex(z1)); + WriteLn(real(z1)); + WriteLn(imag(z1)); + WriteLn(z2); +end. +``` + +已验证运行结果: + +- `datatype(4 + 3j)` 返回 `41` +- `ifcomplex(4 + 3j)` 返回 `1` +- `real(4 + 3j)` 返回 `4` +- `imag(4 + 3j)` 返回 `3` +- `complex(5, -2)` 打印结果是 `5-2j` + +### 共轭、模与等值比较 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + z := 4 + 3j; + c := conj(z); + WriteLn(abs(z)); + WriteLn(real(c)); + WriteLn(imag(c)); + if 3.15 = 3.15 + 0j then + WriteLn(1); + else + WriteLn(0); +end. +``` + +已验证运行结果: + +- `abs(4 + 3j)` 返回 `5` +- `conj(4 + 3j)` 的实部是 `4`、虚部是 `-3` +- `3.15 = 3.15 + 0j` 当前比较结果为真 + +### 复数 `Array` 与复数 `FMArray` + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + a := complex(array(1, 2, 3), 5.5); + f := complex(fmarray[1, 2, 3], 5.5); + WriteLn(datatype(a)); + WriteLn(length(a)); + WriteLn(a[0], ',', a[1], ',', a[2]); + WriteLn(datatype(f)); + WriteLn(datatype(f, 1)); + WriteLn(length(f)); + WriteLn(f[0], ',', f[1], ',', f[2]); +end. +``` + +已验证运行结果: + +- `complex(array(1, 2, 3), 5.5)` 的 `datatype` 是 `5` +- 上述复数数组长度是 `3`,三个元素依次是 `1+5.5j`、`2+5.5j`、`3+5.5j` +- `complex(fmarray[1, 2, 3], 5.5)` 的 `datatype` 是 `27` +- 上述复数 `FMArray` 的单元格类型 `datatype(f, 1)` 是 `41` +- 该 `FMArray` 长度是 `3`,三个元素依次是 `1+5.5j`、`2+5.5j`、`3+5.5j` + +### 弱引用能力的条件编译判定 + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin +{$IFDEF weakptr} + WriteLn('weakptr'); +{$ELSE} + WriteLn('Noweakptr'); +{$ENDIF} +{$IFDEF AutoWeak} + WriteLn('AutoWeak'); +{$ELSE} + WriteLn('NoAutoWeak'); +{$ENDIF} +end. +``` + +已验证运行结果: + +- 当前解释器会输出 `weakptr` +- 当前解释器也会输出 `AutoWeak` +- 说明这代解释器里,弱引用能力的条件编译开关应写成 `weakptr`,自动弱引用能力的开关应写成 `AutoWeak` + +### `weakref`、`weakref_get` 与 `checkweakref` + +对象仍然存活时: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TNode = class + name; + function create(v); + begin + name := v; + end; +end; +begin + a := new TNode('A'); + w := weakref(a); + WriteLn(checkweakref(w)); + s := weakref_get(w); + WriteLn(s.name); +end. +``` + +已验证运行结果: + +- `checkweakref(w)` 返回 `1` +- `weakref_get(w)` 能拿回强引用 +- 通过拿回的强引用可继续访问对象成员,此处输出 `A` + +沿用同一个 `TNode`,只把主体改成下面这样: + +代码块身份:配置片段 / 概念骨架 + +```tsl +program test; +begin + a := new TNode('A'); + w := weakref(a); + WriteLn(checkweakref(w)); + a := nil; + WriteLn(checkweakref(w)); +end. +``` + +已验证运行结果: + +- 创建后 `checkweakref(w)` 返回 `1` +- 把最后一个强引用设为 `nil` 后,`checkweakref(w)` 返回 `-1` + +当前还额外验证到: + +代码块身份:反例 / 不可照写 + +```text +a := new TNode('A'); +w := weakref(a); +a := nil; +t := weakref_get(w); +``` + +上面这种写法在当前解释器里会运行报错,因此访问弱引用前应先做 `checkweakref(w)` 判定。 + +### `[WeakRef]` 与 `[AutoRef]` 成员标记 + +成员级标记当前可以直接写在类里: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TChild = class +public + [WeakRef] owner1; + [AutoRef] owner2; +end; +begin + WriteLn(1); +end. +``` + +已验证运行结果: + +- 上述写法可以正常执行,并输出 `1` +- 说明 `[WeakRef] field;` 和 `[AutoRef] field;` 当前都能通过 + +`[WeakRef]` 成员不会阻止对象析构: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TA = class +public + function destroy(); + begin + WriteLn('Destroy'); + end; +end; + +type TB = class +public + [WeakRef] owner; + function Bind(v); + begin + owner := v; + end; +end; +begin + a := new TA(); + b := new TB(); + b.Bind(a); + a := nil; + WriteLn('AfterNil'); +end. +``` + +已验证运行结果: + +- 输出顺序是 `Destroy`、`AfterNil` +- 说明 `TB.owner` 作为 `[WeakRef]` 成员,不会把 `TA` 实例继续强持有 + +## 暂不在本页展开的部分 + +- 复数统计函数、分解函数与更大函数族 +- `MakeWeakRef`、`MakeStrongRef`、`weakref_check` 等别名接口 +- `property write` 传播自动弱引用的更复杂规则 +- 循环引用场景里的完整模式化写法 + +## 最小可编译示例 + +复数最短骨架: + +代码块身份:已验证可执行示例 + +```tsl +program test; +begin + z := 4 + 3j; + WriteLn(real(z)); + WriteLn(imag(z)); +end. +``` + +弱引用最短骨架: + +代码块身份:已验证可执行示例 + +```tsl +program test; +type TNode = class + name; + function create(v); + begin + name := v; + end; +end; +begin + a := new TNode('A'); + w := weakref(a); + WriteLn(checkweakref(w)); +end. +``` + +## 常见误写 + +- 把弱引用能力的条件编译宏写成 `WeakRef`。 +- 以为 `weakref_get(deadWeakRef)` 会像普通可空访问那样安全返回 `nil`。 +- 以为历史资料里的类内段落式 `WeakRef;` / `AutoRef;` 现在也能直接通过。 +- 以为 `[WeakRef]` 成员会继续强持有对象。 + +代码块身份:反例 / 不可照写 + +```text +type TChild = class +public + owner0; + [WeakRef] owner1; + WeakRef; + owner2; + AutoRef; + owner3; +end; +``` + +上面这种把 `WeakRef;` / `AutoRef;` 当作类内段落切换的写法,在当前解释器里会编译失败,错误信息包含 `invalid class definition`。 + +## 跳转指引 + +- 回看语法主入口:见 [index.md](index.md) +- 回看对象主线:见 [09_objects_and_classes.md](09_objects_and_classes.md) +- 看对象重载:见 [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) diff --git a/docs/tsl/syntax/32_object_overloads_and_iteration.md b/docs/tsl/syntax/32_object_overloads_and_iteration.md new file mode 100644 index 00000000..2bd1b58c --- /dev/null +++ b/docs/tsl/syntax/32_object_overloads_and_iteration.md @@ -0,0 +1,303 @@ +# Object Overloads And Iteration + +文档类型:语法主线 +是否可直接用于生成代码:仅部分 +是否含已验证可执行示例:是 +是否含已验证反例:否 +遇到不确定时跳转到:[09_objects_and_classes.md](09_objects_and_classes.md)、[23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md)、[31_complex_and_weakref.md](31_complex_and_weakref.md) + +手册位置:第 32 篇,共 32 篇。上一篇:[31_complex_and_weakref.md](31_complex_and_weakref.md)。这一篇是当前 syntax 深水专题的最后一篇。 + +这一篇收拢“对象像数组、像容器、像可遍历值”这一组新一代能力:基础算符重载、`[]` 重载、`for in` 重载,以及 `mrows` / `mcols` / `msize` 这类矩阵关键字重载。 + +## 这一篇解决什么问题 + +回答“当类不只是普通对象,而要直接参与 `obj + x`、`obj[index]`、`for v in obj`、`mrows(obj)` 这类语言级操作时,当前解释器到底支持哪些真实写法”。 + +## 必须记住的规则 + +- 对象二元算符重载当前最小可靠形态是成员方法 `function operator + (data);` 这一类写法。 +- 比较算符当前已验证可写成 `function operator < (data, isLeft);`,用 `isLeft` 区分对象在左边还是右边。 +- 对象 `[]` 读取当前已验证两种写法:`function operator[](index);` 和 `function operator[0](index, s1);`。 +- 对象 `[]` 写入当前已验证写法是 `function operator[1](index, v);`。 +- `function operator for(flag);` 当前已验证可以重载 `for in`。 +- 在 `operator for(flag)` 里,`flag .& 2` 可用来区分“一个循环变量”还是“两个循环变量”,`flag .& 1` 可用来区分“第一次进入”还是“继续迭代”。 +- `mrows` / `mcols` / `msize` 当前已验证可以在类里先声明 `function operator mrows(n);` 这类签名,再在类外实现 `function operator ClassName.mrows(n);`。 +- 当前已验证可用的是 `mrows(obj)`、`mcols(obj)`、`msize(obj)` 这类关键字调用,以及 `obj.mcols(1)` 这类对象方法式调用。 +- `function operator++(v);` 和 `function operator += (v);` 当前也已验证可用。 +- 不要把历史资料里的裸 `function operator;` / `function operator1;` 或尚未验证的 `mcell` / `mrow` / `mcol` / `::` / `:.` 重载,直接当成当前解释器事实。 + +## 已验证语法 + +### 二元算符重载 + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Tcomplex = class + vReal; + vImaginary; + function operator + (data); + begin + r := new Tcomplex(); + if ifnumber(data) then + r.vReal := vReal + data + else + begin + r.vReal := vReal + data.vReal; + r.vImaginary := vImaginary + data.vImaginary; + end; + return r; + end; + function operator < (data, isLeft); + begin + if ifnumber(data) then + v := vReal < data + else + v := (vReal ^ 2 + vImaginary ^ 2) < data.vReal ^ 2 + data.vImaginary ^ 2; + if not isLeft then v := not v; + return v; + end; +end; +begin + t1 := new TComplex(); + t1.vReal := 10; + t1.vImaginary := 100; + t2 := t1 + 10; + WriteLn(t2.vReal); + WriteLn(t1 < 5); + WriteLn(t1 < 300); + WriteLn(5 < t1); +end. +``` + +已验证运行结果: + +- 依次输出 `20`、`0`、`1`、`1` +- 说明 `obj + value` 当前可以通过成员 `operator +` 接管 +- 说明带 `isLeft` 的比较算符当前可以同时处理 `obj < value` 和 `value < obj` + +### `[]` 重载:`operator[]` / `operator[1]` + +代码块身份:已验证可执行示例 + +```tsl +program test; +type bb = class + data; + function create(v); + begin + data := v; + end; + function operator[](index); + begin + return data[index]; + end; + function operator[1](index, v); + begin + data[index] := v; + end; +end; +begin + t := array(1, 2, 3, 4, 5); + b := new bb(t); + WriteLn(b[2]); + b[3] := 999; + WriteLn(b.data[3]); +end. +``` + +已验证运行结果: + +- 依次输出 `3`、`999` +- 说明当前解释器下,`operator[]` 和 `operator[1]` 可以完成单层下标读取和写入 + +### `[]` 重载:`operator[0]` / `operator[1]` + +沿用上一段的 `bb` 类与测试主体,只把读取签名从 `function operator[](index);` 改成 `function operator[0](index, s1);`: + +代码块身份:配置片段 / 概念骨架 + +```tsl +type bb = class + // 其余字段、Create()、operator[1] 和测试主体同上一段 + function operator[0](index, s1); + begin + return data[index]; + end; +end; +``` + +已验证运行结果: + +- 依次输出 `3`、`999` +- 说明 `operator[0]` / `operator[1]` 这组写法在单层下标场景同样可用 + +### `for in` 重载 + +代码块身份:已验证可执行示例 + +```tsl +program test; +type Box = class + data; + findex; + function create(v); + begin + data := v; + end; + function operator for(flag); + begin + use_pair := flag .& 2; + again := flag .& 1; + if not again then + findex := 0 + else if findex < length(data) - 1 then + findex++ + else + return nil; + + if use_pair then + return array(findex, data[findex]); + return data[findex]; + end; +end; +begin + box := new Box(array("A", "B", "C")); + for v in box do + WriteLn(v); + for i, v in box do + WriteLn(i$":"$v); +end. +``` + +已验证运行结果: + +- 单变量循环依次输出 `A`、`B`、`C` +- 双变量循环依次输出 `0:A`、`1:B`、`2:C` +- 说明 `operator for(flag)` 当前确实可以重载 `for in` +- 也说明同一个对象可以按返回值形态同时支持“单变量遍历”和“索引 + 值遍历” + +### `mrows` / `mcols` / `msize` 重载 + +代码块身份:已验证可执行示例 + +```tsl +program test; +type GridWrap = class + data; + function create(); + begin + data := array( + ("A": 1, "B": 2, "C": 3), + ("A": 4, "B": 5, "C": 6) + ); + end; + function operator mrows(n); + function operator mcols(n); + function operator msize(n); +end; + +function operator GridWrap.mrows(n); +begin + _n := ifnil(n) ? 0 : n; + return mrows(data, _n); +end; + +function operator GridWrap.mcols(n); +begin + _n := ifnil(n) ? 0 : n; + return mcols(data, _n); +end; + +function operator GridWrap.msize(n); +begin + _n := ifnil(n) ? 0 : n; + return msize(data, _n); +end; + +begin + g := new GridWrap(); + WriteLn(mrows(g)); + WriteLn(mcols(g)); + sz := msize(g); + WriteLn(sz[0]); + WriteLn(sz[1]); + cols := g.mcols(1); + WriteLn(cols[0]); + WriteLn(cols[1]); + WriteLn(cols[2]); +end. +``` + +已验证运行结果: + +- 依次输出 `2`、`3`、`2`、`3`、`A`、`B`、`C` +- 说明 `mrows(obj)`、`mcols(obj)`、`msize(obj)` 当前都可由对象重载接管 +- 说明对象方法式调用 `obj.mcols(1)` 也可继续取得列下标列表 + +### `++` 与 `+=` + +代码块身份:已验证可执行示例 + +```tsl +program test; +type bb = class + data; + function create(v); + begin + data := v; + end; + function operator++(v); + begin + if v = 0 then + begin + r := new bb(); + r.data := data; + r.data++; + return r; + end + else + data++; + end; + function operator += (v); + begin + data += v; + end; +end; +begin + b := new bb(10); + ++b; + WriteLn(b.data); + c := b++; + WriteLn(c.data); + WriteLn(b.data); + b += 5; + WriteLn(b.data); +end. +``` + +已验证运行结果: + +- 依次输出 `11`、`11`、`12`、`17` +- 说明前置 `++` 会直接修改对象状态 +- 说明这个最小样例里,后置 `b++` 返回的是递增前快照 +- 说明 `operator += (v)` 当前可以接管 `b += 5` + +## 暂不在本页展开的部分 + +- `::` / `:.` 遍历重载 +- `mcell` / `mrow` / `mcol` / `mIndexCount` / `mIndex` +- 多级 `[]` 下标重载 +- 右侧算术如 `value + obj` +- 对基础二进制函数的大规模重载族 + +这些旧资料里都有更深示例,但当前这一篇先只保留已经单独跑通的容器化主干。 + +## 跳转指引 + +- 回看对象模型:见 [09_objects_and_classes.md](09_objects_and_classes.md) +- 回看语法主入口:见 [index.md](index.md) +- 回看对象运行时反射:见 [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) +- 回看复数与弱引用:见 [31_complex_and_weakref.md](31_complex_and_weakref.md) diff --git a/docs/tsl/syntax/coverage_map.md b/docs/tsl/syntax/coverage_map.md new file mode 100644 index 00000000..83a9199f --- /dev/null +++ b/docs/tsl/syntax/coverage_map.md @@ -0,0 +1,39 @@ +# Coverage Map + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[index.md](index.md)(优先)、[02_quickstart.md](02_quickstart.md)、[12_pitfalls.md](12_pitfalls.md) + +这一页只回答一个问题:旧 8 章语法手册里的语言章节,现在在新的正式语法手册里分别落到哪里。 + +## 怎么使用这页 + +- 想系统读手册,先按 `01` 到 `16` 主线走。 +- 想补齐深水专题,再按需进入 `18` 到 `32`。 +- 想知道旧书某一章今天应该拆到哪里看,直接查下面的映射表。 + +## 8 章吸收总表 + +| 旧章节 | 主线页 | 专题页 | 说明 | +| --- | --- | --- | --- | +| `01_language_basics.md` | [01_introduction.md](01_introduction.md), [03_core_model.md](03_core_model.md), [04_values_and_literals.md](04_values_and_literals.md), [05_variables_and_constants.md](05_variables_and_constants.md), [07_expressions_and_operators.md](07_expressions_and_operators.md), [11_runtime_context_and_with.md](11_runtime_context_and_with.md), [13_matrix_and_collections.md](13_matrix_and_collections.md) | [18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md), [19_types_and_conversions.md](19_types_and_conversions.md), [20_strings_and_text.md](20_strings_and_text.md) | 语言基础主干在主线,词法 / 类型 / 字符串边界放进深水专题 | +| `02_control_flow.md` | [08_control_flow.md](08_control_flow.md) | [16_debug_and_profiler.md](16_debug_and_profiler.md) | 控制流在主线,调试与 profiler 单列专题 | +| `03_functions.md` | [06_functions_and_calls.md](06_functions_and_calls.md) | [21_external_calls_and_threads.md](21_external_calls_and_threads.md) | 普通函数在主线,`external` / 动态库 / 线程放进专题 | +| `04_modules_and_namespace.md` | [10_units_and_scope.md](10_units_and_scope.md) | [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) | `unit` / `uses` 在主线,运行时查找路径与 `Libpath` 放进专题 | +| `05_object_model.md` | [09_objects_and_classes.md](09_objects_and_classes.md) | [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md), [24_builtin_runtime_objects.md](24_builtin_runtime_objects.md), [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) | 类基础语法在主线,运行时 / 内置对象 / 重载能力拆到专题 | +| `06_extended_syntax.md` | [13_matrix_and_collections.md](13_matrix_and_collections.md), [14_resultset_and_filters.md](14_resultset_and_filters.md), [15_ts_sql.md](15_ts_sql.md) | [25_set_operations.md](25_set_operations.md), [26_matrix_deep_dive.md](26_matrix_deep_dive.md), [27_fmarray.md](27_fmarray.md), [28_ts_sql_core.md](28_ts_sql_core.md), [29_ts_sql_advanced.md](29_ts_sql_advanced.md) | 主线先建立数组 / 结果集 / TS-SQL 入口,集合 / 矩阵 / FMArray / TS-SQL 深水内容进入专题 | +| `07_debug_and_profiler.md` | [16_debug_and_profiler.md](16_debug_and_profiler.md) | [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) | 调试入口在主线,运行时服务与全局缓存单列专题 | +| `08_new_generation.md` | [07_expressions_and_operators.md](07_expressions_and_operators.md), [09_objects_and_classes.md](09_objects_and_classes.md) | [31_complex_and_weakref.md](31_complex_and_weakref.md), [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) | 较新语法相关内容已分散吸收到表达式 / 对象主线,复数 / 弱引用 / 对象重载保留在专题 | + +## 读取原则 + +- 新 session 不需要再回旧 8 章语法手册建立语言主干。 +- `01` 到 `16` 负责从介绍到进阶的顺序阅读。 +- `18` 到 `32` 负责把旧 8 章里剩余的深水内容补齐。 +- 当前正式手册没有 `17_xxx.md`;主线是 `01-16`,深水专题是 `18-32`。 + +## 跳转 + +- 回到语法入口:见 [index.md](index.md) diff --git a/docs/tsl/syntax/index.md b/docs/tsl/syntax/index.md new file mode 100644 index 00000000..d369be85 --- /dev/null +++ b/docs/tsl/syntax/index.md @@ -0,0 +1,138 @@ +# Syntax Index + +文档类型:检索页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:[02_quickstart.md](02_quickstart.md)(优先)、[03_core_model.md](03_core_model.md)、[07_expressions_and_operators.md](07_expressions_and_operators.md)、[09_objects_and_classes.md](09_objects_and_classes.md)、[12_pitfalls.md](12_pitfalls.md) + +这里是 TSL 语法手册入口。只处理“语言怎么写”,不处理金融业务语义。 + +## 元数据读法 + +- 页头里的 `是否可直接用于生成代码` 是页面级粗判断;真正落代码时,优先看每个代码块自己的 `代码块身份`。 +- `是否可直接用于生成代码` 有三种值:`是`、`否`、`仅部分`;其中 `仅部分` 表示这一页同时含有可直接参考的代码块,以及依赖多文件、查找路径或运行时环境的代码块。 +- `是否含已验证可执行示例` 只表示这一页存在已跑通的正向代码示例。 +- `是否含已验证反例` 只表示这一页存在已经确认不能照写的负例。 +- `代码块身份` 固定只用四种值:`已验证可执行示例`、`已验证输出片段`、`反例 / 不可照写`、`配置片段 / 概念骨架`。 +- 如果代码块后面还有用途或限制说明,会单独写成 `代码块说明`,不继续混进 `代码块身份`。 +- 如果页头里的 `遇到不确定时跳转到` 给出多个目标,默认第一项是优先入口,后面的目标用于分流或补证。 + +## 这本手册怎么读 + +- 默认先走“按任务跳转”,不要先顺序读完整套。 +- 只有刻意系统学习时,才按下面的“推荐读法”顺序进入。 +- 当前这套正式语法手册不再只覆盖主线入门,而是负责完整吸收旧 8 个语言章节。 + +## 如果你马上要写 TSL + +1. [02_quickstart.md](02_quickstart.md)(先看语言核心事实速查和最短骨架) +2. [03_core_model.md](03_core_model.md) +3. [06_functions_and_calls.md](06_functions_and_calls.md) +4. [12_pitfalls.md](12_pitfalls.md) +5. 涉及较新写法时,按主题跳到对应专题页 + +## 推荐读法 + +1. [01_introduction.md](01_introduction.md) +2. [02_quickstart.md](02_quickstart.md) +3. [03_core_model.md](03_core_model.md) +4. [04_values_and_literals.md](04_values_and_literals.md) +5. [05_variables_and_constants.md](05_variables_and_constants.md) +6. [06_functions_and_calls.md](06_functions_and_calls.md) +7. [07_expressions_and_operators.md](07_expressions_and_operators.md) +8. [08_control_flow.md](08_control_flow.md) +9. [09_objects_and_classes.md](09_objects_and_classes.md) +10. [10_units_and_scope.md](10_units_and_scope.md) +11. [11_runtime_context_and_with.md](11_runtime_context_and_with.md) +12. [12_pitfalls.md](12_pitfalls.md) +13. [13_matrix_and_collections.md](13_matrix_and_collections.md) +14. [14_resultset_and_filters.md](14_resultset_and_filters.md) +15. [15_ts_sql.md](15_ts_sql.md) +16. [16_debug_and_profiler.md](16_debug_and_profiler.md) +这条顺序对应“先建立整体读法,再写值、变量、函数、表达式、流程,随后进入类、unit、运行时边界,再按需进入进阶专题”。 + +编号说明:主线 `01-16`,深水 `18-32`,无 `17` 号正文页;历史 `17` 号位保留为空。 + +## 深水专题 + +以下专题默认不要预读。只有主线页不够、或者任务已经明确命中对应场景时,再进入。 + +| 专题 | 什么时候进入 | +| --- | --- | +| [18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md) | 只有涉及注释规则、条件编译、编译选项或词法边界时才读 | +| [19_types_and_conversions.md](19_types_and_conversions.md) | 只有涉及显式类型、转换规则或类型兼容问题时才读 | +| [20_strings_and_text.md](20_strings_and_text.md) | 只有涉及字符串处理、编码或文本细节时才读 | +| [21_external_calls_and_threads.md](21_external_calls_and_threads.md) | 只有涉及 `external`、DLL、线程或外部调用时才读 | +| [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) | 只有涉及 `namespace`、`Libpath`、unit 运行时或查找路径时才读 | +| [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) | 只有涉及对象运行时、自省或反射能力时才读 | +| [24_builtin_runtime_objects.md](24_builtin_runtime_objects.md) | 只有涉及内置运行时对象时才读 | +| [25_set_operations.md](25_set_operations.md) | 只有涉及集合运算专题时才读 | +| [26_matrix_deep_dive.md](26_matrix_deep_dive.md) | 只有涉及矩阵运算且 [13_matrix_and_collections.md](13_matrix_and_collections.md) 不够用时才读 | +| [27_fmarray.md](27_fmarray.md) | 只有涉及 `FMArray` 专题时才读 | +| [28_ts_sql_core.md](28_ts_sql_core.md) | 只有开始写 TS-SQL 核心语法时才读 | +| [29_ts_sql_advanced.md](29_ts_sql_advanced.md) | 只有 TS-SQL 基础页不够、问题进入进阶能力时才读 | +| [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) | 只有涉及网格计算、运行时服务或全局缓存时才读 | +| [31_complex_and_weakref.md](31_complex_and_weakref.md) | 只有涉及复数或弱引用时才读 | +| [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) | 只有涉及对象算符重载或遍历重载时才读 | + +这组页面承担旧 8 章里没有被主线正文完整吃掉的深水内容,目标是让新 session 只靠 `docs/tsl/syntax/` 就能覆盖旧语法章节,但默认首跳仍应先走主线页。 + +## 按任务跳转 + +| 当前任务 | 先读哪里 | +| --- | --- | +| 先建立整体读法 | [01_introduction.md](01_introduction.md) | +| 写最短骨架 | [02_quickstart.md](02_quickstart.md) | +| 判断顶层模型 / 文件模型 | [03_core_model.md](03_core_model.md) | +| 写值、数组、字符串 | [04_values_and_literals.md](04_values_and_literals.md) | +| 写变量、常量、显式声明 | [05_variables_and_constants.md](05_variables_and_constants.md) | +| 写 `function` / `procedure`、参数修饰、默认参数、命名参数、变参、`external` | [06_functions_and_calls.md](06_functions_and_calls.md) | +| 写赋值、比较、`if` 表达式 | [07_expressions_and_operators.md](07_expressions_and_operators.md) | +| 写 `?.` 等较新表达式 | [07_expressions_and_operators.md](07_expressions_and_operators.md) | +| 写条件、循环、异常控制 | [08_control_flow.md](08_control_flow.md) | +| 写类、继承、property、静态字段 | [09_objects_and_classes.md](09_objects_and_classes.md) | +| 写 `unit` / `uses` | [10_units_and_scope.md](10_units_and_scope.md) | +| 写运行时环境参数、`SysParams[...]`、`#Func() with array(...)` | [11_runtime_context_and_with.md](11_runtime_context_and_with.md) | +| 先避开高频误写 | [12_pitfalls.md](12_pitfalls.md) | +| 写数组扩展、键表、矩阵样数据 | [13_matrix_and_collections.md](13_matrix_and_collections.md) | +| 写结果集过滤专题 | [14_resultset_and_filters.md](14_resultset_and_filters.md) | +| 写 TS-SQL 专题 | [15_ts_sql.md](15_ts_sql.md) | +| 看调试与 profiler 专题 | [16_debug_and_profiler.md](16_debug_and_profiler.md) | +| 看词法、注释、编译选项 | [18_lexical_structure_and_compile_options.md](18_lexical_structure_and_compile_options.md) | +| 看类型与转换 | [19_types_and_conversions.md](19_types_and_conversions.md) | +| 看字符串与编码专题 | [20_strings_and_text.md](20_strings_and_text.md) | +| 看 `external`、DLL 与多线程 | [21_external_calls_and_threads.md](21_external_calls_and_threads.md) | +| 看 `namespace`、单元运行时、`Libpath`、查找路径 | [22_namespace_libpath_and_unit_runtime.md](22_namespace_libpath_and_unit_runtime.md) | +| 看对象运行时和反射 | [23_object_runtime_and_introspection.md](23_object_runtime_and_introspection.md) | +| 看运行时内置对象 | [24_builtin_runtime_objects.md](24_builtin_runtime_objects.md) | +| 看集合运算 | [25_set_operations.md](25_set_operations.md) | +| 看矩阵深水专题 | [26_matrix_deep_dive.md](26_matrix_deep_dive.md) | +| 看 `FMArray` | [27_fmarray.md](27_fmarray.md) | +| 看 TS-SQL 基础 | [28_ts_sql_core.md](28_ts_sql_core.md) | +| 看 TS-SQL 进阶 | [29_ts_sql_advanced.md](29_ts_sql_advanced.md) | +| 看网格计算与全局缓存 | [30_runtime_services_and_global_cache.md](30_runtime_services_and_global_cache.md) | +| 看复数与弱引用 | [31_complex_and_weakref.md](31_complex_and_weakref.md) | +| 看对象算符与遍历重载 | [32_object_overloads_and_iteration.md](32_object_overloads_and_iteration.md) | +| 看较新表达式或表达式边界 | [07_expressions_and_operators.md](07_expressions_and_operators.md) | +| 看较新对象能力或类边界 | [09_objects_and_classes.md](09_objects_and_classes.md) | +| 看资料冲突 / 解释器差异 | 先留在当前页,对照上面的主线与深水进入条件后,再按主题进入相应页面 | +| 看高频误写 / 反例 / 负向边界 | [12_pitfalls.md](12_pitfalls.md) | +| 看正式语法手册当前覆盖范围与成熟度 | [coverage_map.md](coverage_map.md) | + +## 旧 8 章在正式手册中的落点 + +- `01_language_basics.md`:主线落在 `01` `03` `04` `05` `07` `11` `13`,深水落在 `18` `19` `20` +- `02_control_flow.md`:主线落在 `08`,调试与性能补充落在 `16` +- `03_functions.md`:主线落在 `06`,系统交互补充落在 `21` +- `04_modules_and_namespace.md`:主线落在 `10`,单元运行时与查找路径补充落在 `22` +- `05_object_model.md`:主线落在 `09`,运行时 / 内置对象 / 重载补充落在 `23` `24` `32` +- `06_extended_syntax.md`:主线入口在 `13` `14` `15`,深水落在 `25` `26` `27` `28` `29` +- `07_debug_and_profiler.md`:入口在 `16`,服务层运行时补充落在 `30` +- `08_new_generation.md`:表达式与对象主线落在 `07` `09`,复数 / 弱引用 / 对象重载落在 `31` `32` + +## 切换到别的层 + +- 业务问题:见 [../finance/index.md](../finance/index.md) +- 模块 / 集成 / 互操作:见 [../modules/index.md](../modules/index.md) +- 函数库查找:见 [../reference/index.md](../reference/index.md) diff --git a/docs/tsl/toolchain.md b/docs/tsl/toolchain.md index fe6c3c2d..e4315dc9 100644 --- a/docs/tsl/toolchain.md +++ b/docs/tsl/toolchain.md @@ -1,76 +1,132 @@ -# TSL 工具链与验证命令(模板) +# TSL 工具链与验证命令 -本文件提供一份**通用占位模板**,用于在不同 TSL 项目中快速补齐“工具链与如何验证”的关键上下文。 +文档类型:模板页 +是否可直接用于生成代码:否 +是否含已验证可执行示例:否 +是否含已验证反例:否 +遇到不确定时跳转到:项目自身文档、`scripts/*` 入口脚本、CI 配置 -最小必填清单(落地到具体项目时必须补齐,否则文档不可用): +这里处理项目执行类问题,不处理通用 TSL 语法事实。 -- 工具名称、可执行命令、安装方式(版本要求可选) -- 至少一个可运行的“最小冒烟”命令(或脚本入口) -- 失败处理约定(含:无法执行时的替代验证方式) +如果问题在问执行命令、脚本入口、CI、验证方式、环境变量或部署流程,这不是语法问题,而是项目执行类问题;应先回项目自身文档、`scripts/*` 入口脚本和 CI 配置。默认检索 TSL 语法、代码写法或真实执行命令时,应忽略本页。本页只是一份待补齐模板,不提供真实可执行命令。 -使用方式: +## 模板说明 -- 在具体项目中复制本模板并把占位符替换为真实信息; -- 或在项目文档中引用本模板,并在项目内提供对应的 `scripts/*` 统一入口脚本。 +- 本文件提供一份通用占位模板,不是通用执行手册。 +- 只有在当前项目已经把工具链、执行入口和验证命令补齐后,才可以把它当成执行依据。 +- 如果这页里仍然出现 `<...>` 形式的占位符,说明当前项目还没有补齐真实信息,应回到项目自身文档或脚本入口。 +- 以下命令片段全部属于模板占位,不是真实 CLI 示例,也不应被 AI 直接复制执行。 -## 1. TSL 工具链 +## 为什么不可直接执行 -### 1.1 解释器/编译器(必填) +- 占位符没有绑定到当前项目的真实解释器、路径、环境变量和脚本入口。 +- 同一条模板命令在不同项目里可能对应不同的安装方式、权限模型和验证流程。 +- 如果直接照抄本页内容,最常见的错误是路径不存在、可执行入口错误、凭证缺失或验证层级不匹配。 + +## 项目补齐项 + +### 解释器/编译器(必填) - 工具名称:`` -- 可执行命令(统一用 `` 表示 TSL 可执行入口): - - macOS/Linux:``(例:`tsl` / `sh scripts/tsl.sh`) - - Windows:``(例:`tsl.exe` / `powershell -File scripts/tsl.ps1`) -- 基本执行方式:` `(TSL 通常直接执行脚本文件) -- 版本要求(可选):`<固定版本或范围,例如:= 3.2.1 / >=3.2,<4.0>`(未知可留空或写 - `N/A`) - 安装方式:`<内部安装包/路径/IDE 自带/CI 镜像等>` -- 推荐统一入口脚本:`scripts/tsl.{sh,ps1}`(封装参数与环境变量,避免每个任务重复猜测) +- 版本要求:`<固定版本或范围;未知可写 N/A>` +- 推荐统一入口脚本:`scripts/tsl.{sh,ps1}` -### 1.2 运行环境(按需) +可执行入口模板: -- 必要环境变量:` ...` -- 外部依赖:`<数据库/服务/共享目录/网络权限/账户权限>` -- 运行约束: - - 是否允许联网:`` - - 是否需要许可证/凭证:`<说明如何在本地与 CI 提供;禁止写入仓库>` - - 约定:凭证/许可证等敏感信息通过环境变量或 CI - secrets 注入;文档只写变量名/获取方式,不写明文值。 +代码块身份:配置片段 / 概念骨架 -## 2. 验证命令 +```text + + +``` -> 要求:改动完成后至少能跑通“最小冒烟”;若项目存在测试体系,尽量补到对应层级。 +平台命令模板: -### 2.1 最小冒烟(必须能跑) +代码块身份:配置片段 / 概念骨架 -- macOS/Linux:` ` -- Windows:` ` -- 或统一入口: - - `sh scripts/smoke.sh` - - `powershell -File scripts/smoke.ps1` -- Success - signal(建议写清):退出码为 0;并给出“成功时的关键输出/产物路径”(例如输出包含某行、或生成某文件)。 +```text +macOS/Linux: +Windows: +``` -### 2.2 单元测试(如有) +### 运行环境(按需) -- `sh scripts/test.sh` -- 或:` ` -- Success signal:退出码为 0;失败时能定位到具体用例/输入。 +- 必要环境变量模板: -### 2.3 静态检查/格式化(如有) +代码块身份:配置片段 / 概念骨架 -- `sh scripts/lint.sh` -- `sh scripts/format.sh` -- Success - signal:退出码为 0;formatter 二次运行无新增 diff(若项目提供 formatter)。 +```text + + + +``` -### 2.4 构建/打包(如有) +- 外部依赖模板: -- `sh scripts/build.sh` -- Success signal:退出码为 0;产物路径明确且可复现(例如输出目录/包名)。 +代码块身份:配置片段 / 概念骨架 -### 2.5 失败处理约定(必填) +```text +<数据库/服务/共享目录/网络权限/账户权限> +``` + +- 运行约束模板: + +代码块身份:配置片段 / 概念骨架 + +```text +是否允许联网: +是否需要许可证/凭证:<说明如何在本地与 CI 提供;禁止写入仓库> +``` + +- 凭证、许可证等敏感信息应通过环境变量或 CI secrets 注入;文档只写变量名或获取方式,不写明文值。 + +### 验证命令(必须补齐) + +- 至少补齐一个最小冒烟命令。 +- 如果项目存在测试体系,应继续补齐单元测试、静态检查和构建命令。 +- 所有命令都应替换成当前项目的真实入口,不要保留模板占位。 + +最小冒烟模板: + +代码块身份:配置片段 / 概念骨架 + +```text + +sh scripts/smoke.sh +powershell -File scripts/smoke.ps1 +``` + +单元测试模板: + +代码块身份:配置片段 / 概念骨架 + +```text +sh scripts/test.sh + +``` + +静态检查 / 格式化模板: + +代码块身份:配置片段 / 概念骨架 + +```text +sh scripts/lint.sh +sh scripts/format.sh +``` + +构建 / 打包模板: + +代码块身份:配置片段 / 概念骨架 + +```text +sh scripts/build.sh +``` + +成功信号也必须补齐为真实规则,例如退出码、关键输出或产物路径。 + +### 失败处理约定(必填) - 只修复与本次改动直接相关的失败;无关失败在输出中说明并隔离。 -- 若某验证步骤无法执行(缺环境/缺凭证),必须明确写出原因与替代验证手段(例如最小复现脚本/手动检查清单)。 -- 建议在输出中记录:执行的命令、退出码、以及关键日志片段(便于 review 与复现)。 +- 若某验证步骤无法执行,必须明确写出原因与替代验证手段,例如最小复现脚本或手动检查清单。 +- 建议记录:执行的命令、退出码、关键日志片段和产物位置,便于 review 与复现。 diff --git a/playbook.toml.example b/playbook.toml.example index 6771f284..c1cfe8e4 100644 --- a/playbook.toml.example +++ b/playbook.toml.example @@ -2,19 +2,20 @@ # 配置文件所在目录默认作为 project_root。 [playbook] -# project_root = "." # 可选:覆盖目标项目根目录 -# verbose = false # 可选:输出更详细日志 -# dry_run = false # 可选:仅预览,不写入 +# project_root = "." # 可选:目标项目根目录 +# deploy_root = "docs/standards/playbook" # 项目内已部署时可省略;从外部 clone 执行时必填;值始终是相对于 project_root 的项目内路径,不是外部 clone 的 playbook 路径 [vendor] -# 将 playbook 裁剪快照写入 /docs/standards/playbook +# 当从外部 clone 的 playbook 向项目内部署快照时启用 +# 外部 clone 路径只用于执行脚本;快照仍会写入 / # langs = ["tsl"] # 可选:默认仅 tsl -# target_dir = "docs/standards/playbook" [sync_rules] # 同步 AGENT_RULES.md(配置节存在即启用) # force = false # 可选:覆盖已有文件 # no_backup = false # 可选:跳过备份 +# date = "2026-04-22" # 可选:替换 {{DATE}} +# main_language = "tsl" # 可选:覆盖 {{MAIN_LANGUAGE}} [sync_memory_bank] # 同步 memory-bank/(配置节存在即启用) @@ -23,12 +24,16 @@ # project_name = "MyProject" # 可选:替换 {{PROJECT_NAME}} # force = false # 可选:覆盖已有文件(会先备份) # no_backup = false # 可选:跳过备份 +# date = "2026-04-22" # 可选:替换 {{DATE}} +# main_language = "tsl" # 可选:覆盖 {{MAIN_LANGUAGE}} [sync_prompts] # 同步 docs/prompts/(配置节存在即启用) # 只更新框架提供的文件,项目新增的文件不会被删除 # force = false # 可选:覆盖已有文件(会先备份) # no_backup = false # 可选:跳过备份 +# date = "2026-04-22" # 可选:替换 {{DATE}} +# main_language = "tsl" # 可选:覆盖 {{MAIN_LANGUAGE}} [sync_standards] # langs = ["tsl", "cpp", "typescript"] # 必填:要同步的语言 diff --git a/scripts/build_tsl_reference_catalog.ps1 b/scripts/build_tsl_reference_catalog.ps1 new file mode 100644 index 00000000..bee6cc1f --- /dev/null +++ b/scripts/build_tsl_reference_catalog.ps1 @@ -0,0 +1,285 @@ +param( + [string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +) + +$ErrorActionPreference = "Stop" + +$sourceDir = Join-Path $RepoRoot "data/tsl_reference_catalog_source" +$outputDir = Join-Path $RepoRoot "docs/tsl/reference/catalog" + +$moduleOrder = @( + [pscustomobject]@{ File = "base"; Summary = "字符串、数组、日期时间、类型转换与常用基础能力" } + [pscustomobject]@{ File = "math"; Summary = "数值计算、统计分析、矩阵处理与数学算法" } + [pscustomobject]@{ File = "system"; Summary = "数据类型、表达式调用、性能与运行时能力" } + [pscustomobject]@{ File = "resource"; Summary = "文件、数据库、网络与外部资源访问" } + [pscustomobject]@{ File = "platform"; Summary = "平台相关功能与系统接口" } + [pscustomobject]@{ File = "client"; Summary = "客户端交互、界面控制与前端协作能力" } + [pscustomobject]@{ File = "graphics"; Summary = "图表、绘图与可视化相关函数" } + [pscustomobject]@{ File = "compression"; Summary = "压缩、解压与归档能力" } + [pscustomobject]@{ File = "digest_encoding"; Summary = "哈希、摘要、编码与转换能力" } + [pscustomobject]@{ File = "third_party"; Summary = "第三方库与外部程序交互能力" } +) + +function Get-HeadingSections { + param([string[]]$Lines) + + $sections = @() + + for ($i = 0; $i -lt $Lines.Count; $i++) { + if ($Lines[$i] -match '^(#{4,7})\s+(.+?)\s*$') { + $sections += [pscustomobject]@{ + Level = $Matches[1].Length + Title = $Matches[2].Trim() + Start = $i + } + } + } + + for ($i = 0; $i -lt $sections.Count; $i++) { + $nextStart = if ($i + 1 -lt $sections.Count) { $sections[$i + 1].Start } else { $Lines.Count } + $sections[$i] | Add-Member -NotePropertyName End -NotePropertyValue ($nextStart - 1) + } + + return $sections +} + +function Test-IsFunctionSection { + param( + [string]$Title, + [string[]]$BodyLines + ) + + if ($null -eq $BodyLines -or $BodyLines.Count -eq 0) { + return $false + } + + $body = $BodyLines -join "`n" + $hasStructuredMarkers = ( + $body -match '(^|\n)\s*用途:' -or + $body -match '(^|\n)\s*参数:' -or + $body -match '(^|\n)\s*返回:' + ) + + if ($hasStructuredMarkers) { + return $true + } + + $looksLikeFunctionName = $Title -match '^[A-Za-z_][A-Za-z0-9_]*$' + $hasMeaningfulBody = $body -match '\S' + + return ( + $looksLikeFunctionName -and + $hasMeaningfulBody + ) +} + +function Add-FunctionToGroup { + param( + [System.Collections.Specialized.OrderedDictionary]$GroupMap, + [string]$Category, + [string]$Subcategory, + [string]$FunctionName + ) + + if ([string]::IsNullOrWhiteSpace($FunctionName)) { + return + } + + $categoryName = if ([string]::IsNullOrWhiteSpace($Category)) { "未分类" } else { $Category } + $groupTitle = if ([string]::IsNullOrWhiteSpace($Subcategory)) { + $categoryName + } + else { + "{0} / {1}" -f $categoryName, $Subcategory + } + + if (-not $GroupMap.Contains($groupTitle)) { + $GroupMap[$groupTitle] = [pscustomobject]@{ + Title = $groupTitle + Category = $categoryName + Subcategory = $Subcategory + Functions = [System.Collections.Generic.List[string]]::new() + } + } + + $functionList = $GroupMap[$groupTitle].Functions + if (-not $functionList.Contains($FunctionName)) { + $functionList.Add($FunctionName) + } +} + +function Parse-TslFunctionModule { + param([string]$Path) + + $lines = Get-Content -LiteralPath $Path + $sections = Get-HeadingSections -Lines $lines + $moduleTitle = ($sections | Where-Object { $_.Level -eq 4 } | Select-Object -First 1).Title + + if ([string]::IsNullOrWhiteSpace($moduleTitle)) { + throw "Unable to detect module title in $Path" + } + + $groupMap = [ordered]@{} + $currentCategory = $null + $currentSubcategory = $null + + foreach ($section in $sections | Where-Object { $_.Level -ge 5 }) { + $title = $section.Title.Trim() + if ($title -in @("内容", "范例")) { + continue + } + + $bodyLines = @() + if ($section.End -gt $section.Start) { + $bodyLines = $lines[($section.Start + 1)..$section.End] + } + + $isFunction = Test-IsFunctionSection -Title $title -BodyLines $bodyLines + + switch ($section.Level) { + 5 { + if ($isFunction) { + Add-FunctionToGroup -GroupMap $groupMap -Category "直接函数" -Subcategory $null -FunctionName $title + } + else { + $currentCategory = $title + $currentSubcategory = $null + } + continue + } + 6 { + if ($isFunction) { + Add-FunctionToGroup -GroupMap $groupMap -Category $currentCategory -Subcategory $null -FunctionName $title + } + else { + $currentSubcategory = $title + } + continue + } + 7 { + if ($isFunction) { + Add-FunctionToGroup -GroupMap $groupMap -Category $currentCategory -Subcategory $currentSubcategory -FunctionName $title + } + continue + } + } + } + + $groups = foreach ($entry in $groupMap.GetEnumerator()) { + [pscustomobject]@{ + Title = $entry.Value.Title + Category = $entry.Value.Category + Subcategory = $entry.Value.Subcategory + Functions = @($entry.Value.Functions) + } + } + + $functionCount = ($groups | ForEach-Object { $_.Functions } | Sort-Object -Unique).Count + + return [pscustomobject]@{ + File = [System.IO.Path]::GetFileNameWithoutExtension($Path) + ModuleTitle = $moduleTitle + Groups = $groups + FunctionCount = $functionCount + } +} + +function New-MarkdownModulePage { + param( + [pscustomobject]$Module, + [string]$Summary + ) + + $lines = [System.Collections.Generic.List[string]]::new() + $lines.Add("# $($Module.ModuleTitle)") + $lines.Add("") + $lines.Add("这一页只负责函数定位:先按主题找到模块,再在页内搜索函数名。") + $lines.Add("") + $lines.Add("## 使用方式") + $lines.Add("") + $lines.Add("- 返回总目录:[catalog/index.md](index.md)") + $lines.Add("- 需要基础语法时回到 [../../syntax/index.md](../../syntax/index.md)") + $lines.Add("- 需要金融任务组织方式时回到 [../../finance/index.md](../../finance/index.md)") + $lines.Add("") + $lines.Add("## 模块范围") + $lines.Add("") + $lines.Add("- 说明:$Summary") + $lines.Add("- 主题数:$($Module.Groups.Count)") + $lines.Add("- 函数数:$($Module.FunctionCount)") + $lines.Add("") + $lines.Add("## 主题目录") + $lines.Add("") + + foreach ($group in $Module.Groups) { + $lines.Add("### $($group.Title)") + $lines.Add("") + foreach ($functionName in $group.Functions) { + $lines.Add("- ``$functionName``") + } + $lines.Add("") + } + + return ($lines -join "`r`n").TrimEnd() + "`r`n" +} + +function New-MarkdownCatalogIndex { + param([object[]]$Modules) + + $lines = [System.Collections.Generic.List[string]]::new() + $lines.Add("# Function Catalog") + $lines.Add("") + $lines.Add('这里是 canonical 函数目录。它只回答“函数在哪个模块里”,不承担基础语法教学。') + $lines.Add("") + $lines.Add("## 使用顺序") + $lines.Add("") + $lines.Add("1. 不知道函数在哪个模块,先看下面的模块目录。") + $lines.Add("2. 进入模块页后,在页内搜索具体函数名。") + $lines.Add("3. 如果问题是语法怎么写,回到 [../../syntax/index.md](../../syntax/index.md)。") + $lines.Add("4. 如果问题是金融场景如何组织,回到 [../../finance/index.md](../../finance/index.md)。") + $lines.Add("") + $lines.Add("## 模块目录") + $lines.Add("") + $lines.Add("| 模块 | 分类页 | 范围 | 函数数 |") + $lines.Add("| --- | --- | --- | --- |") + + foreach ($module in $Modules) { + $pageName = "{0}.md" -f $module.File + $lines.Add("| $($module.ModuleTitle) | [$pageName]($pageName) | $($module.Summary) | $($module.FunctionCount) |") + } + + $lines.Add("") + $lines.Add("## 说明") + $lines.Add("") + $lines.Add("- 这套目录页由仓库内的函数语料自动整理生成。") + $lines.Add("- 当前目标是先提供稳定检索层,再逐步补全更细的 canonical 说明。") + $lines.Add("") + + return ($lines -join "`r`n").TrimEnd() + "`r`n" +} + +if (-not (Test-Path -LiteralPath $sourceDir)) { + throw "Source directory not found: $sourceDir" +} + +New-Item -ItemType Directory -Force -Path $outputDir | Out-Null + +$modules = foreach ($meta in $moduleOrder) { + $sourcePath = Join-Path $sourceDir ("{0}.md" -f $meta.File) + if (-not (Test-Path -LiteralPath $sourcePath)) { + throw "Missing module source: $sourcePath" + } + + $module = Parse-TslFunctionModule -Path $sourcePath + $module | Add-Member -NotePropertyName Summary -NotePropertyValue $meta.Summary + $module +} + +$catalogIndex = New-MarkdownCatalogIndex -Modules $modules +Set-Content -LiteralPath (Join-Path $outputDir "index.md") -Value $catalogIndex -Encoding UTF8 + +foreach ($module in $modules) { + $page = New-MarkdownModulePage -Module $module -Summary $module.Summary + Set-Content -LiteralPath (Join-Path $outputDir ("{0}.md" -f $module.File)) -Value $page -Encoding UTF8 +} + +Write-Output ("Generated {0} catalog pages in {1}" -f ($modules.Count + 1), $outputDir) diff --git a/scripts/check_no_legacy_refs.ps1 b/scripts/check_no_legacy_refs.ps1 new file mode 100644 index 00000000..5ccb8758 --- /dev/null +++ b/scripts/check_no_legacy_refs.ps1 @@ -0,0 +1,71 @@ +param( + [string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path +) + +$ErrorActionPreference = "Stop" + +$targets = @( + (Join-Path $RepoRoot "docs/tsl/index.md"), + (Join-Path $RepoRoot "docs/tsl/syntax"), + (Join-Path $RepoRoot "docs/tsl/finance"), + (Join-Path $RepoRoot "docs/tsl/reference") +) + +$excludeFragments = @( + "\docs\plans\", + "\archive\", + "\docs\tsl\legacy\", + "\docs\tsl\syntax_book\" +) + +$pattern = '(?i)\b(?:syntax_book|legacy)\b' + +function Get-RelativePath([string]$basePath, [string]$childPath) { + $baseUri = [System.Uri]::new(($basePath.TrimEnd('\', '/') + [System.IO.Path]::DirectorySeparatorChar)) + $childUri = [System.Uri]::new($childPath) + return [System.Uri]::UnescapeDataString($baseUri.MakeRelativeUri($childUri).ToString()).Replace('\', '/') +} + +$files = foreach ($target in $targets) { + if (!(Test-Path -LiteralPath $target)) { + throw "Target not found: $target" + } + + if ((Get-Item -LiteralPath $target).PSIsContainer) { + Get-ChildItem -LiteralPath $target -Recurse -File -Filter *.md + } + else { + Get-Item -LiteralPath $target + } +} + +$activeFiles = $files | + Where-Object { + $fullName = $_.FullName + foreach ($fragment in $excludeFragments) { + if ($fullName -like "*$fragment*") { + return $false + } + } + return $true + } | + Sort-Object FullName -Unique + +$hits = foreach ($file in $activeFiles) { + Select-String -Path $file.FullName -Pattern $pattern -AllMatches +} + +if ($hits.Count -eq 0) { + Write-Output "No legacy references found in active TSL docs." + exit 0 +} + +Write-Output "Legacy references found in active TSL docs:" +foreach ($hit in $hits) { + $relativePath = Get-RelativePath -basePath $RepoRoot -childPath $hit.Path + Write-Output ("{0}:{1}: {2}" -f $relativePath, $hit.LineNumber, $hit.Line.Trim()) +} + +Write-Output ("Total files scanned: {0}" -f $activeFiles.Count) +Write-Output ("Total legacy hits: {0}" -f $hits.Count) +exit 1 diff --git a/scripts/playbook.py b/scripts/playbook.py index 8dc2cc7f..bcdd6a4e 100644 --- a/scripts/playbook.py +++ b/scripts/playbook.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import re import sys from datetime import datetime, timezone from pathlib import Path @@ -21,7 +22,15 @@ ORDER = [ ] SCRIPT_DIR = Path(__file__).resolve().parent PLAYBOOK_ROOT = SCRIPT_DIR.parent -PATH_CONFIG_KEYS = {"project_root", "target_dir", "agents_home", "codex_home"} +PATH_CONFIG_KEYS = {"project_root", "deploy_root", "agents_home", "codex_home"} +DOCS_INDEX_SECTION_HEADINGS = { + "common": "## 跨语言(common)", + "tsl": "## TSL(tsl/tsf)", + "cpp": "## C++(cpp)", + "python": "## Python(python)", + "typescript": "## TypeScript(typescript)", + "markdown": "## Markdown(markdown)", +} def usage() -> str: @@ -232,6 +241,85 @@ def normalize_langs(raw: object) -> list[str]: return cleaned +def normalize_relative_dir(raw: object, label: str) -> str: + value = str(raw).strip() + if not value: + raise ValueError(f"{label} is empty") + path = Path(value) + if path.is_absolute() or ".." in path.parts: + raise ValueError(f"invalid {label}: {value}") + normalized = path.as_posix() + return "." if normalized == "" else normalized + + +def join_deploy_subpath(root: str, child: str) -> str: + if root in ("", "."): + return child.lstrip("/") + return f"{root.rstrip('/')}/{child.lstrip('/')}" + + +def resolve_in_project_deploy_root(project_root: Path) -> str | None: + try: + rel = PLAYBOOK_ROOT.resolve().relative_to(project_root.resolve()) + if str(rel) != ".": + return rel.as_posix() + except ValueError: + pass + return None + + +def config_requires_deploy_root(config: dict) -> bool: + for key in ( + "vendor", + "sync_rules", + "sync_memory_bank", + "sync_prompts", + "sync_standards", + "install_skills", + ): + if key in config: + return True + return False + + +def resolve_configured_deploy_root(config: dict, project_root: Path) -> str: + playbook_config = config.get("playbook", {}) + raw = None + if isinstance(playbook_config, dict): + raw = playbook_config.get("deploy_root") + vendor_config = config.get("vendor", {}) + if isinstance(vendor_config, dict) and vendor_config.get("target_dir") is not None: + raise ValueError( + "vendor.target_dir is no longer supported; use [playbook].deploy_root" + ) + if raw is not None and str(raw).strip(): + return normalize_relative_dir(raw, "deploy_root") + + in_project_deploy_root = resolve_in_project_deploy_root(project_root) + if in_project_deploy_root is not None: + return in_project_deploy_root + + if config_requires_deploy_root(config): + raise ValueError( + "playbook.deploy_root is required when running from an external clone; " + "set it to the target project's relative deployment path" + ) + + return "docs/standards/playbook" + + +def resolve_deploy_root(context: dict) -> str: + project_root: Path = context["project_root"] + in_project_deploy_root = resolve_in_project_deploy_root(project_root) + if in_project_deploy_root is not None: + return in_project_deploy_root + return context["deploy_root"] + + +def resolve_docs_prefix(context: dict) -> str: + return join_deploy_subpath(resolve_deploy_root(context), "docs") + + def resolve_main_language(config: dict, context: dict) -> str: raw = config.get("main_language") if raw is not None and str(raw).strip(): @@ -254,21 +342,8 @@ def resolve_main_language(config: dict, context: dict) -> str: def resolve_playbook_scripts(project_root: Path, context: dict) -> str: - playbook_scripts = PLAYBOOK_ROOT / "scripts" - try: - rel = playbook_scripts.resolve().relative_to(project_root.resolve()) - return rel.as_posix() - except ValueError: - full_config = context.get("config", {}) - if isinstance(full_config, dict): - vendor_conf = full_config.get("vendor") - if isinstance(vendor_conf, dict): - target_dir = vendor_conf.get("target_dir") - if target_dir: - target_str = str(target_dir).strip().rstrip("/").rstrip("\\") - if target_str: - return f"{target_str}/scripts" - return "docs/standards/playbook/scripts" + _ = project_root + return join_deploy_subpath(resolve_deploy_root(context), "scripts") def read_git_commit(root: Path) -> str: @@ -284,88 +359,75 @@ def read_git_commit(root: Path) -> str: return result.stdout.strip() or "N/A" -def write_docs_index(dest_prefix: Path, langs: list[str]) -> None: - lines = [ - "# 文档导航(Docs Index)", +def extract_docs_index_sections(lines: list[str]) -> dict[str, list[str]]: + heading_to_key = {value: key for key, value in DOCS_INDEX_SECTION_HEADINGS.items()} + starts: list[tuple[int, str]] = [] + for idx, line in enumerate(lines): + key = heading_to_key.get(line) + if key is not None: + starts.append((idx, key)) + + sections: dict[str, list[str]] = {} + for idx, (start, key) in enumerate(starts): + end = starts[idx + 1][0] if idx + 1 < len(starts) else len(lines) + section_lines = lines[start:end] + while section_lines and section_lines[-1] == "": + section_lines = section_lines[:-1] + sections[key] = section_lines + return sections + + +def build_docs_index_lines(langs: list[str], source_path: Path | None = None) -> list[str]: + docs_index_path = source_path or (PLAYBOOK_ROOT / "docs" / "index.md") + source_lines = docs_index_path.read_text(encoding="utf-8").splitlines() + title = source_lines[0] if source_lines else "# 文档导航(Docs Index)" + sections = extract_docs_index_sections(source_lines) + + ordered_keys = ["common", *langs] + result = [ + title, "", f"本快照为裁剪版 Playbook(langs: {','.join(langs)})。", "", - "## 跨语言(common)", - "", - "- 提交信息与版本号:`common/commit_message.md`", ] - for lang in langs: - if lang == "tsl": - lines += [ - "", - "## TSL(tsl)", - "", - "- 代码风格:`tsl/code_style.md`", - "- 命名规范:`tsl/naming.md`", - "- 语法手册:`tsl/syntax_book/index.md`", - "- 工具链与验证命令(模板):`tsl/toolchain.md`", - ] - elif lang == "cpp": - lines += [ - "", - "## C++(cpp)", - "", - "- 代码风格:`cpp/code_style.md`", - "- 命名规范:`cpp/naming.md`", - "- 工具链与验证命令(模板):`cpp/toolchain.md`", - "- 第三方依赖(Conan):`cpp/dependencies_conan.md`", - "- clangd 配置:`cpp/clangd.md`", - ] - elif lang == "python": - lines += [ - "", - "## Python(python)", - "", - "- 代码风格:`python/style_guide.md`", - "- 工具链:`python/tooling.md`", - "- 配置清单:`python/configuration.md`", - ] - elif lang == "typescript": - lines += [ - "", - "## TypeScript(typescript)", - "", - "- 代码风格:`typescript/code_style.md`", - "- 命名规范:`typescript/naming.md`", - "- 工具链:`typescript/toolchain.md`", - "- 配置清单:`typescript/configuration.md`", - ] - elif lang == "markdown": - lines += [ - "", - "## Markdown(markdown)", - "", - "- 代码块与行内代码格式:`markdown/index.md`", - ] + for idx, key in enumerate(ordered_keys): + section = sections.get(key) + if section is None: + raise ValueError(f"docs/index.md is missing section for {key}") + if idx > 0: + result.append("") + result.extend(section) + return result + + +def write_docs_index(dest_prefix: Path, langs: list[str]) -> None: + lines = build_docs_index_lines(langs) docs_index = dest_prefix / "docs/index.md" ensure_dir(docs_index.parent) docs_index.write_text("\n".join(lines) + "\n", encoding="utf-8") -def write_snapshot_readme(dest_prefix: Path, langs: list[str]) -> None: +def write_snapshot_readme(dest_prefix: Path, deploy_root: str, langs: list[str]) -> None: + scripts_path = join_deploy_subpath(deploy_root, "scripts/playbook.py") + docs_index_path = join_deploy_subpath(deploy_root, "docs/index.md") lines = [ "# Playbook(裁剪快照)", "", - f"本目录为从 Playbook vendoring 的裁剪快照(langs: {','.join(langs)})。", + f"本目录为从 Playbook 部署到项目内的裁剪快照(langs: {','.join(langs)})。", "", "## 使用", "", "在目标项目根目录执行:", "", "```sh", - "python docs/standards/playbook/scripts/playbook.py -config playbook.toml", + f"python {scripts_path} -config playbook.toml", "```", "", - "配置示例:`docs/standards/playbook/playbook.toml.example`", + f"配置示例:`{join_deploy_subpath(deploy_root, 'playbook.toml.example')}`", "", "文档入口:", "", - "- `docs/standards/playbook/docs/index.md`", + f"- `{docs_index_path}`", "- `.agents/index.md`", ] (dest_prefix / "README.md").write_text("\n".join(lines) + "\n", encoding="utf-8") @@ -393,11 +455,8 @@ def vendor_action(config: dict, context: dict) -> int: print(f"ERROR: {exc}", file=sys.stderr) return 2 - target_dir = config.get("target_dir", "docs/standards/playbook") - target_path = Path(target_dir) - if target_path.is_absolute() or ".." in target_path.parts: - print(f"ERROR: invalid target_dir: {target_dir}", file=sys.stderr) - return 2 + deploy_root = context["deploy_root"] + target_path = Path(deploy_root) project_root: Path = context["project_root"] dest_prefix = project_root / target_path @@ -471,7 +530,7 @@ def vendor_action(config: dict, context: dict) -> int: copy2(example_config, dest_prefix / "playbook.toml.example") write_docs_index(dest_prefix, langs) - write_snapshot_readme(dest_prefix, langs) + write_snapshot_readme(dest_prefix, deploy_root, langs) write_source_file(dest_prefix, langs) log(f"Vendored snapshot -> {dest_prefix}") @@ -910,32 +969,45 @@ def create_agents_index(agents_root: Path, langs: list[str], docs_prefix: str | "", "标准快照文档入口:", "", - f"- {docs_prefix or 'docs/standards/playbook/docs/'}", + f"- {docs_prefix or 'docs/'}", ] agents_index.write_text("\n".join(lines) + "\n", encoding="utf-8") log("Synced .agents/index.md") -def rewrite_agents_docs_links(agents_dir: Path, docs_prefix: str) -> None: +def rewrite_docs_links_in_markdown(root: Path, docs_prefix: str, recursive: bool) -> None: replacements = { - "`docs/tsl/": f"`{docs_prefix}/tsl/", - "`docs/cpp/": f"`{docs_prefix}/cpp/", - "`docs/python/": f"`{docs_prefix}/python/", - "`docs/typescript/": f"`{docs_prefix}/typescript/", - "`docs/markdown/": f"`{docs_prefix}/markdown/", - "`docs/common/": f"`{docs_prefix}/common/", + "tsl": f"{docs_prefix}/tsl/", + "cpp": f"{docs_prefix}/cpp/", + "python": f"{docs_prefix}/python/", + "typescript": f"{docs_prefix}/typescript/", + "markdown": f"{docs_prefix}/markdown/", + "common": f"{docs_prefix}/common/", } - for md_path in agents_dir.glob("*.md"): + iterator = root.rglob("*.md") if recursive else root.glob("*.md") + patterns = [ + (re.compile(rf"(? None: + rewrite_docs_links_in_markdown(agents_dir, docs_prefix, recursive=False) + + +def rewrite_skill_docs_links(skill_dir: Path, docs_prefix: str) -> None: + rewrite_docs_links_in_markdown(skill_dir, docs_prefix, recursive=True) + + def read_gitattributes_entries(path: Path) -> list[str]: entries: list[str] = [] for line in path.read_text(encoding="utf-8").splitlines(): @@ -1047,13 +1119,7 @@ def sync_standards_action(config: dict, context: dict) -> int: copytree(src, dst) log(f"Synced .agents/{lang} from standards.") - docs_prefix = None - try: - rel_snapshot = PLAYBOOK_ROOT.resolve().relative_to(project_root.resolve()) - if str(rel_snapshot) != ".": - docs_prefix = f"{rel_snapshot.as_posix()}/docs" - except ValueError: - docs_prefix = None + docs_prefix = resolve_docs_prefix(context) if docs_prefix: for lang in langs: @@ -1165,6 +1231,7 @@ def install_skills_action(config: dict, context: dict) -> int: dst.rename(backup) log(f"Backed up existing skill: {name} -> {backup.name}") copytree(src, dst) + rewrite_skill_docs_links(dst, resolve_docs_prefix(context)) log(f"Installed: {name}") return 0 @@ -1246,10 +1313,17 @@ def main(argv: list[str]) -> int: root = (config_path.parent / root).resolve() else: root = config_path.parent + resolved_root = root.resolve() + try: + deploy_root = resolve_configured_deploy_root(config, resolved_root) + except ValueError as exc: + print(f"ERROR: {exc}", file=sys.stderr) + return 2 context = { - "project_root": root.resolve(), + "project_root": resolved_root, "config_path": config_path.resolve(), "config": config, + "deploy_root": deploy_root, } if should_sync_agents(config): diff --git a/scripts/tsl_doc_audit.ps1 b/scripts/tsl_doc_audit.ps1 new file mode 100644 index 00000000..ad88642d --- /dev/null +++ b/scripts/tsl_doc_audit.ps1 @@ -0,0 +1,328 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$Path +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +function Resolve-AuditTargets { + param( + [string]$InputPath + ) + + if (-not (Test-Path -LiteralPath $InputPath)) { + throw "Path not found: $InputPath" + } + + $item = Get-Item -LiteralPath $InputPath + if ($item.PSIsContainer) { + return @(Get-ChildItem -LiteralPath $item.FullName -Recurse -File -Filter "*.md" | Sort-Object FullName) + } + + if ($item.Extension -ne ".md") { + throw "Only Markdown files are supported: $($item.FullName)" + } + + return @($item) +} + +function Get-FirstMeaningfulLine { + param( + [string[]]$Lines + ) + + foreach ($line in $Lines) { + if (-not [string]::IsNullOrWhiteSpace($line)) { + return $line.Trim() + } + } + + return "" +} + +function Get-BlockPreview { + param( + [string]$Code + ) + + $preview = "" + foreach ($line in ($Code -split "`r?`n")) { + if (-not [string]::IsNullOrWhiteSpace($line)) { + $preview = $line.Trim() + break + } + } + + if ([string]::IsNullOrWhiteSpace($preview)) { + return "" + } + + if ($preview.Length -gt 100) { + return $preview.Substring(0, 100) + "..." + } + + return $preview +} + +function Get-SkipReason { + param( + [string]$Language, + [string]$Code + ) + + if ($Language -eq "text") { + return "text block" + } + + $trimmed = $Code.Trim() + if ([string]::IsNullOrWhiteSpace($trimmed)) { + return "empty block" + } + + if ($trimmed -match '(?m)^\s*statement;\s*$') { + return "grammar placeholder" + } + + if ($trimmed -match '…+' -or $trimmed -match '(?m)^\s*(//\s*)?\.{3,}\s*$') { + return "ellipsis placeholder" + } + + if ($trimmed -match '<[^>\r\n]+>') { + return "angle-bracket placeholder" + } + + $meaningfulLines = @( + ($Code -split "`r?`n" | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() }) + ) + if ($meaningfulLines.Count -gt 1 -and + $meaningfulLines[0] -eq "begin" -and + (($meaningfulLines | Select-Object -Skip 1) -match '^(?i:(function|unit|type|class|const|var|namespace|uses))')) { + return "mixed non-standalone snippet" + } + + return $null +} + +function Get-CompileKind { + param( + [string]$Code + ) + + $firstLine = Get-FirstMeaningfulLine -Lines ($Code -split "`r?`n") + if ($firstLine -match '^(?i:(function|unit|type|class|const|var|namespace|uses|\{\$))') { + return "tsf" + } + + return "tsl" +} + +function Invoke-TslCompile { + param( + [string]$Code, + [ValidateSet("tsl", "tsf")] + [string]$Kind + ) + + $tempRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("tsl-doc-audit-" + [guid]::NewGuid().ToString("N")) + New-Item -ItemType Directory -Path $tempRoot | Out-Null + + $process = $null + + try { + $sourcePath = Join-Path $tempRoot ("snippet." + $Kind) + [System.IO.File]::WriteAllText($sourcePath, $Code, [System.Text.UTF8Encoding]::new($false)) + + $psi = New-Object System.Diagnostics.ProcessStartInfo + $psi.FileName = 'tsl' + $psi.Arguments = "-COMPILE `"$sourcePath`"" + $psi.RedirectStandardOutput = $true + $psi.RedirectStandardError = $true + $psi.RedirectStandardInput = $true + $psi.UseShellExecute = $false + $psi.CreateNoWindow = $true + + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $psi + $process.Start() | Out-Null + $process.StandardInput.WriteLine('exit') + $process.StandardInput.Flush() + $process.WaitForExit(30000) | Out-Null + + $stdout = $process.StandardOutput.ReadToEnd() + $stderr = $process.StandardError.ReadToEnd() + $outputText = ($stdout + "`n" + $stderr).Trim() + $lowerText = $outputText.ToLowerInvariant() + $success = $lowerText -match 'compile success' + $failure = $lowerText -match 'compile error' + + if ($success) { + return [pscustomobject]@{ Success = $true; Output = $outputText } + } + if ($failure) { + return [pscustomobject]@{ Success = $false; Output = $outputText } + } + + return [pscustomobject]@{ Success = $false; Output = (if ($outputText) { $outputText } else { "" }) } + } + finally { + if ($process -and -not $process.HasExited) { + $process.Kill() + $process.WaitForExit() + } + if (Test-Path -LiteralPath $tempRoot) { + Remove-Item -LiteralPath $tempRoot -Recurse -Force + } + } +} + +function Wrap-AsFunctionBody { + param( + [string]$Code + ) + + $body = $Code -split "`r?`n" | ForEach-Object { " $_" } + return @( + "function __doc_check__();" + "begin" + $body + "end;" + "" + ) -join "`n" +} + +function Parse-MarkdownBlocks { + param( + [string]$Content + ) + + $blocks = New-Object System.Collections.Generic.List[object] + $lines = $Content -split "`r?`n" + $inFence = $false + $fenceLang = "" + $fenceStartLine = 0 + $buffer = New-Object System.Collections.Generic.List[string] + + for ($i = 0; $i -lt $lines.Length; $i++) { + $line = $lines[$i] + + if (-not $inFence) { + if ($line -match '^\s*```([A-Za-z0-9_-]*)\s*$') { + $inFence = $true + $fenceLang = $Matches[1].ToLowerInvariant() + $fenceStartLine = $i + 1 + $buffer.Clear() + } + continue + } + + if ($line -match '^\s*```\s*$') { + $blocks.Add([pscustomobject]@{ + Language = $fenceLang + StartLine = $fenceStartLine + Code = ($buffer -join "`n") + }) + $inFence = $false + $fenceLang = "" + $fenceStartLine = 0 + $buffer.Clear() + continue + } + + $buffer.Add($line) + } + + return $blocks +} + +$targets = Resolve-AuditTargets -InputPath $Path +$grandPass = 0 +$grandSkip = 0 +$grandFail = 0 + +foreach ($target in $targets) { + $content = Get-Content -LiteralPath $target.FullName -Raw + $blocks = Parse-MarkdownBlocks -Content $content + $results = New-Object System.Collections.Generic.List[object] + + foreach ($block in $blocks) { + if ($block.Language -notin @("tsl", "text")) { + continue + } + + $skipReason = Get-SkipReason -Language $block.Language -Code $block.Code + if ($null -ne $skipReason) { + $results.Add([pscustomobject]@{ + Status = "skip" + StartLine = $block.StartLine + Preview = Get-BlockPreview -Code $block.Code + Detail = $skipReason + }) + continue + } + + $kind = Get-CompileKind -Code $block.Code + $compile = Invoke-TslCompile -Code $block.Code -Kind $kind + + if ($compile.Success) { + $results.Add([pscustomobject]@{ + Status = "pass" + StartLine = $block.StartLine + Preview = Get-BlockPreview -Code $block.Code + Detail = $kind + }) + continue + } + + if ($kind -eq "tsl") { + $wrappedCode = Wrap-AsFunctionBody -Code $block.Code + $wrappedCompile = Invoke-TslCompile -Code $wrappedCode -Kind "tsf" + if ($wrappedCompile.Success) { + $results.Add([pscustomobject]@{ + Status = "pass" + StartLine = $block.StartLine + Preview = Get-BlockPreview -Code $block.Code + Detail = "wrapped tsf" + }) + continue + } + + $compile = $wrappedCompile + } + + $results.Add([pscustomobject]@{ + Status = "fail" + StartLine = $block.StartLine + Preview = Get-BlockPreview -Code $block.Code + Detail = ($compile.Output.Trim()) + }) + } + + $passCount = @($results | Where-Object Status -eq "pass").Count + $skipCount = @($results | Where-Object Status -eq "skip").Count + $failCount = @($results | Where-Object Status -eq "fail").Count + + $grandPass += $passCount + $grandSkip += $skipCount + $grandFail += $failCount + + Write-Output "$($target.FullName): pass=$passCount skip=$skipCount fail=$failCount" + + foreach ($failure in ($results | Where-Object Status -eq "fail")) { + Write-Output " FAIL line $($failure.StartLine): $($failure.Preview)" + foreach ($detailLine in ($failure.Detail -split "`r?`n")) { + if (-not [string]::IsNullOrWhiteSpace($detailLine)) { + Write-Output " $detailLine" + } + } + } +} + +Write-Output "TOTAL: pass=$grandPass skip=$grandSkip fail=$grandFail" + +if ($grandFail -gt 0) { + exit 1 +} + +exit 0 diff --git a/templates/README.md b/templates/README.md index 215dbfb5..2620ed62 100644 --- a/templates/README.md +++ b/templates/README.md @@ -84,7 +84,7 @@ docs/prompts/**/* # 项目新增的文件不会被删除 ### 参考资料(D类,不部署到项目根) ``` -# 留在 docs/standards/playbook/templates/ 中参考 +# 留在 /templates/ 中参考 ci/ # CI 配置 cpp/ # C++ 配置 python/ # Python 配置 @@ -114,10 +114,12 @@ project_name = "MyProject" ``` ```bash -python docs/standards/playbook/scripts/playbook.py -config playbook.toml +python /scripts/playbook.py -config playbook.toml ``` -参数说明见 `playbook.toml.example`(仓库根目录)或 vendoring 后的 `docs/standards/playbook/playbook.toml.example`。 +参数说明见 `playbook.toml.example`(仓库根目录)或项目内的 `/playbook.toml.example`。 + +其中 `` 默认为 `docs/standards/playbook`,也可以按项目配置改成 `custom/playbook` 等自定义目录;对应文档入口会变成 `/docs/...`。 ### 配置节说明 @@ -190,7 +192,7 @@ project/ `{{PROJECT_NAME}}` 可通过 `sync_memory_bank.project_name` 自动替换;未配置时保持原样。 `{{MAIN_LANGUAGE}}` 可通过 `sync_standards.langs[0]` 自动替换;未配置时默认 `tsl`。 -`{{PLAYBOOK_SCRIPTS}}` 自动替换为 Playbook 脚本路径(默认 `docs/standards/playbook/scripts`)。 +`{{PLAYBOOK_SCRIPTS}}` 自动替换为 Playbook 脚本路径(默认 `docs/standards/playbook/scripts`,也可按项目配置改成 `custom/playbook/scripts` 等)。 ## 模板说明 @@ -246,7 +248,7 @@ project/ 1) 先完成 brainstorming,并输出设计文档 `docs/plans/YYYY-MM-DD--design.md`。 2) 询问我“是否进入 `docs/plans/` 实施计划编写阶段”,确认后使用 writing-plans 生成实现计划。 3) 实现计划内明确标注每步要改的文件与命令;验证步骤只包含可通过的局部验证,不包含测试。 -4) 执行计划时只走主循环,并通过 `docs/standards/playbook/scripts/main_loop.py claim/finish` 更新 `memory-bank/progress.md`。 +4) 执行计划时只走主循环,并通过 `/scripts/main_loop.py claim/finish` 更新 `memory-bank/progress.md`。 ``` ### AGENTS.template.md @@ -291,7 +293,7 @@ langs = ["tsl", "cpp", "python"] ```bash python scripts/playbook.py -config playbook.toml -# 然后手动从 docs/standards/playbook/templates/ 复制所需配置到项目根目录 +# 然后手动从 /templates/ 复制所需配置到项目根目录 ``` ## 与 playbook 其他部分的关系 @@ -311,7 +313,7 @@ playbook/ ```bash # 1. 准备配置并执行统一入口 -python docs/standards/playbook/scripts/playbook.py -config playbook.toml +python /scripts/playbook.py -config playbook.toml # 2. 编辑 memory-bank/*.md 填写项目信息 diff --git a/tests/cli/test_playbook_cli.py b/tests/cli/test_playbook_cli.py index 485da82c..e8846bc2 100644 --- a/tests/cli/test_playbook_cli.py +++ b/tests/cli/test_playbook_cli.py @@ -6,17 +6,41 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[2] SCRIPT = ROOT / "scripts" / "playbook.py" +CUSTOM_DEPLOY_ROOT = "custom/playbook" -def run_cli(*args): +def run_script(script, *args): return subprocess.run( - [sys.executable, str(SCRIPT), *args], + [sys.executable, str(script), *args], capture_output=True, text=True, ) +def run_cli(*args): + return run_script(SCRIPT, *args) + + +def write_config(root: Path, name: str, body: str) -> Path: + config_path = root / name + config_path.write_text(body, encoding="utf-8") + return config_path + + class PlaybookCliTests(unittest.TestCase): + def assert_style_cleanup_tsl_docs_prefix( + self, root: Path, agents_home: Path, docs_prefix: str + ) -> None: + agents_index = (root / ".agents" / "tsl" / "index.md").read_text(encoding="utf-8") + self.assertIn(f"`{docs_prefix}/tsl/index.md`", agents_index) + self.assertNotIn("`docs/tsl/index.md`", agents_index) + + skill_file = (agents_home / "skills" / "style-cleanup" / "SKILL.md").read_text( + encoding="utf-8" + ) + self.assertIn(f"`{docs_prefix}/tsl/code_style.md`", skill_file) + self.assertNotIn("`docs/tsl/code_style.md`", skill_file) + def test_help_shows_usage(self): result = run_cli("-h") self.assertEqual(result.returncode, 0) @@ -28,9 +52,10 @@ class PlaybookCliTests(unittest.TestCase): self.assertIn("-config", result.stdout + result.stderr) def test_action_order(self): - config_body = """ + config_body = f""" [playbook] project_root = "." +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [format_md] @@ -47,8 +72,68 @@ langs = ["tsl"] self.assertIn("sync_standards", output) self.assertIn("format_md", output) + def test_format_md_only_does_not_require_deploy_root(self): + with tempfile.TemporaryDirectory() as tmp_dir: + config_body = f""" +[playbook] +project_root = "{tmp_dir}" + +[format_md] +""" + config_path = Path(tmp_dir) / "playbook.toml" + config_path.write_text(config_body, encoding="utf-8") + + result = run_cli("-config", str(config_path)) + + self.assertEqual(result.returncode, 0) + def test_vendor_creates_snapshot(self): with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) + config_body = f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[vendor] +langs = ["tsl"] +""" + config_path = write_config(root, "playbook.toml", config_body) + + result = run_cli("-config", str(config_path)) + + snapshot = root / CUSTOM_DEPLOY_ROOT / "SOURCE.md" + self.assertEqual(result.returncode, 0) + self.assertTrue(snapshot.is_file()) + + def test_vendor_docs_index_uses_new_tsl_entrypoints(self): + with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) + config_body = f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[vendor] +langs = ["tsl"] +""" + config_path = write_config(root, "playbook.toml", config_body) + + result = run_cli("-config", str(config_path)) + + docs_index = root / CUSTOM_DEPLOY_ROOT / "docs/index.md" + self.assertEqual(result.returncode, 0) + text = docs_index.read_text(encoding="utf-8") + self.assertIn("`tsl/index.md`", text) + self.assertIn("`tsl/syntax/index.md`", text) + self.assertIn("`tsl/finance/index.md`", text) + self.assertIn("`tsl/modules/index.md`", text) + self.assertIn("`tsl/reference/index.md`", text) + self.assertNotIn("`tsl/syntax_book/index.md`", text) + + def test_external_clone_requires_explicit_deploy_root(self): + with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) config_body = f""" [playbook] project_root = "{tmp_dir}" @@ -56,20 +141,19 @@ project_root = "{tmp_dir}" [vendor] langs = ["tsl"] """ - config_path = Path(tmp_dir) / "playbook.toml" - config_path.write_text(config_body, encoding="utf-8") + config_path = write_config(root, "playbook.toml", config_body) result = run_cli("-config", str(config_path)) - snapshot = Path(tmp_dir) / "docs/standards/playbook/SOURCE.md" - self.assertEqual(result.returncode, 0) - self.assertTrue(snapshot.is_file()) + self.assertNotEqual(result.returncode, 0) + self.assertIn("deploy_root", result.stdout + result.stderr) def test_sync_memory_bank_creates_memory_bank(self): with tempfile.TemporaryDirectory() as tmp_dir: config_body = f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [sync_memory_bank] project_name = "Demo" @@ -88,6 +172,7 @@ project_name = "Demo" config_body = f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [sync_standards] langs = ["tsl"] @@ -110,6 +195,7 @@ langs = ["tsl"] f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [sync_standards] langs = ["tsl"] @@ -126,6 +212,7 @@ no_backup = true f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [sync_standards] langs = ["tsl", "cpp"] @@ -146,6 +233,7 @@ no_backup = true config_body = f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [sync_standards] langs = ["tsl"] @@ -171,6 +259,7 @@ langs = ["tsl"] config_body = f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [install_skills] agents_home = "{target}" @@ -186,12 +275,34 @@ skills = ["brainstorming"] self.assertEqual(result.returncode, 0) self.assertTrue(skill_file.is_file()) + def test_install_skills_rejects_removed_tsl_guide(self): + with tempfile.TemporaryDirectory() as tmp_dir: + target = Path(tmp_dir) / "agents" + config_body = f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[install_skills] +agents_home = "{target}" +mode = "list" +skills = ["tsl-guide"] +""" + config_path = Path(tmp_dir) / "playbook.toml" + config_path.write_text(config_body, encoding="utf-8") + + result = run_cli("-config", str(config_path)) + + self.assertNotEqual(result.returncode, 0) + self.assertIn("skill not found: tsl-guide", result.stdout + result.stderr) + def test_install_skills_rejects_codex_home(self): with tempfile.TemporaryDirectory() as tmp_dir: target = Path(tmp_dir) / "codex" config_body = f""" [playbook] project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" [install_skills] codex_home = "{target}" @@ -206,5 +317,82 @@ skills = ["brainstorming"] self.assertNotEqual(result.returncode, 0) self.assertIn("codex_home", result.stdout + result.stderr) + def test_external_clone_flow_rewrites_links_with_configured_deploy_root(self): + with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) + agents_home = root / "agents-home" + config_body = f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[vendor] +langs = ["tsl"] + +[sync_standards] +langs = ["tsl"] +no_backup = true + +[install_skills] +agents_home = "{agents_home}" +mode = "list" +skills = ["style-cleanup"] +""" + config_path = write_config(root, "playbook.toml", config_body) + + result = run_cli("-config", str(config_path)) + + self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr) + self.assertTrue((root / CUSTOM_DEPLOY_ROOT / "SOURCE.md").is_file()) + self.assert_style_cleanup_tsl_docs_prefix( + root, agents_home, f"{CUSTOM_DEPLOY_ROOT}/docs" + ) + + def test_deployed_snapshot_rewrites_links_from_snapshot_location(self): + with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) + vendor_config = write_config( + root, + "vendor.toml", + f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[vendor] +langs = ["tsl"] +""", + ) + + vendor_result = run_cli("-config", str(vendor_config)) + self.assertEqual(vendor_result.returncode, 0, msg=vendor_result.stdout + vendor_result.stderr) + + vendored_script = root / CUSTOM_DEPLOY_ROOT / "scripts" / "playbook.py" + agents_home = root / "local-agents" + sync_config = write_config( + root, + "sync.toml", + f""" +[playbook] +project_root = "{tmp_dir}" +deploy_root = "{CUSTOM_DEPLOY_ROOT}" + +[sync_standards] +langs = ["tsl"] +no_backup = true + +[install_skills] +agents_home = "{agents_home}" +mode = "list" +skills = ["style-cleanup"] +""", + ) + + sync_result = run_script(vendored_script, "-config", str(sync_config)) + self.assertEqual(sync_result.returncode, 0, msg=sync_result.stdout + sync_result.stderr) + self.assert_style_cleanup_tsl_docs_prefix( + root, agents_home, f"{CUSTOM_DEPLOY_ROOT}/docs" + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_playbook_docs_index.py b/tests/test_playbook_docs_index.py new file mode 100644 index 00000000..cae5b7c2 --- /dev/null +++ b/tests/test_playbook_docs_index.py @@ -0,0 +1,61 @@ +import importlib.util +import tempfile +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +SCRIPT = ROOT / "scripts" / "playbook.py" + + +def load_playbook_module(): + spec = importlib.util.spec_from_file_location("playbook_script", SCRIPT) + module = importlib.util.module_from_spec(spec) + assert spec.loader is not None + spec.loader.exec_module(module) + return module + + +class PlaybookDocsIndexTests(unittest.TestCase): + def test_build_docs_index_lines_uses_canonical_sections(self): + playbook = load_playbook_module() + + with tempfile.TemporaryDirectory() as tmp_dir: + source = Path(tmp_dir) / "index.md" + source.write_text( + "\n".join( + [ + "# 文档导航(Docs Index)", + "", + "仓库级说明。", + "", + "## 跨语言(common)", + "", + "- 公共入口:`common/commit_message.md`", + "", + "## TSL(tsl/tsf)", + "", + "- 自定义 TSL 入口:`tsl/custom.md`", + "", + "## Python(python)", + "", + "- Python 入口:`python/style_guide.md`", + "", + ] + ) + + "\n", + encoding="utf-8", + ) + + lines = playbook.build_docs_index_lines(["tsl"], source) + + self.assertEqual(lines[0], "# 文档导航(Docs Index)") + self.assertEqual(lines[2], "本快照为裁剪版 Playbook(langs: tsl)。") + self.assertIn("## 跨语言(common)", lines) + self.assertIn("- 公共入口:`common/commit_message.md`", lines) + self.assertIn("## TSL(tsl/tsf)", lines) + self.assertIn("- 自定义 TSL 入口:`tsl/custom.md`", lines) + self.assertNotIn("## Python(python)", lines) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_tsl_entrypoints_consistency.py b/tests/test_tsl_entrypoints_consistency.py new file mode 100644 index 00000000..d9b9cc06 --- /dev/null +++ b/tests/test_tsl_entrypoints_consistency.py @@ -0,0 +1,56 @@ +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +RULESET_TSL = ROOT / "rulesets" / "tsl" / "index.md" +README = ROOT / "README.md" +PLAYBOOK_EXAMPLE = ROOT / "playbook.toml.example" +SKILLS_DOC = ROOT / "SKILLS.md" +TEMPLATES_CI_README = ROOT / "templates" / "ci" / "README.md" +REMOVED_TSL_GUIDE = ROOT / "codex" / "skills" / "tsl-guide" + + +class TslEntrypointsConsistencyTests(unittest.TestCase): + def test_ruleset_lists_canonical_tsl_layers(self): + text = RULESET_TSL.read_text(encoding="utf-8") + self.assertIn("docs/tsl/index.md", text) + self.assertIn("docs/tsl/syntax/index.md", text) + self.assertIn("docs/tsl/finance/index.md", text) + self.assertIn("docs/tsl/modules/index.md", text) + self.assertIn("docs/tsl/reference/index.md", text) + + def test_readme_only_lists_two_official_deployment_routes(self): + text = README.read_text(encoding="utf-8") + self.assertIn("方式一:git subtree", text) + self.assertIn("方式二:外部 clone 后执行部署", text) + self.assertIn("`project_root`:目标项目根目录", text) + self.assertIn("`deploy_root`:相对于 `project_root` 的项目内目标目录", text) + self.assertIn("不是外部 clone 出来的 Playbook 仓库路径", text) + self.assertIn("外部 clone 场景下必须显式填写 `deploy_root`", text) + self.assertNotIn("方式二:手动复制快照", text) + self.assertNotIn("方式三:CLI 裁剪复制", text) + self.assertNotIn("如果省略 `deploy_root`,默认仍部署到 `docs/standards/playbook`", text) + + def test_playbook_example_defines_deploy_root_as_target_path(self): + text = PLAYBOOK_EXAMPLE.read_text(encoding="utf-8") + self.assertIn('deploy_root = "docs/standards/playbook"', text) + self.assertIn("相对于 project_root", text) + self.assertIn("不是外部 clone 的 playbook 路径", text) + self.assertIn("从外部 clone 执行时必填", text) + self.assertNotIn("target_dir", text) + + def test_deployment_docs_do_not_reference_legacy_terms(self): + self.assertNotIn("vendoring", README.read_text(encoding="utf-8")) + self.assertNotIn("`.tmp`", README.read_text(encoding="utf-8")) + self.assertNotIn("vendoring", SKILLS_DOC.read_text(encoding="utf-8")) + self.assertNotIn("vendoring", TEMPLATES_CI_README.read_text(encoding="utf-8")) + + def test_repo_no_longer_ships_tsl_guide_skill(self): + self.assertFalse(REMOVED_TSL_GUIDE.exists()) + self.assertNotIn("tsl-guide", README.read_text(encoding="utf-8")) + self.assertNotIn("tsl-guide", SKILLS_DOC.read_text(encoding="utf-8")) + self.assertNotIn("$tsl-guide", RULESET_TSL.read_text(encoding="utf-8")) + + +if __name__ == "__main__": + unittest.main()