Enhancements in Dyalog v20.0: Arrays, Namespaces, Composition, Inline Tracing - Asher Harvey-Smith
摘要
Dyalog v20.0 引入了数组符号、内联跟踪器和 behind 组合运算符,显著提升了 APL 编码体验和调试效率。
<p><a href="https://lobste.rs/s/boef7v/enhancements_dyalog_v20_0_arrays">Comments</a></p>
查看缓存全文
缓存时间: 2026/06/26 02:05
### TL;DR
Dyalog v20.0 引入了数组符号(直接编写多行数组)、内联跟踪器(分步骤解析复杂表达式)和 behind 组合运算符(预处理左参数),显著提升了编码体验和调试效率。
## 数组符号
版本 20 最大的变化之一就是数组符号,它允许直接以类似多行文本的形式编写数组,而不再需要逐个拼接或使用函数构造。
### 向量符号
使用括号 `()` 和菱形符号 `⋄` 或换行符分隔元素。例如:
```
(New York ⋄ 2025 + 1)
```
会创建一个两元素数组:第一个元素是字符向量 `'New York'`,第二个元素是表达式 `2026` 的结果。数组中的每个元素可以是任意表达式,不限于常量。
### 矩阵符号
方括号 `[]` 用于定义矩阵,每一行放在一个括号层内。例如:
```
[ (3 1 2 3) ]
[ (4 5 6 7) ]
```
等价于矩阵 `3 1 2 3` 行和 `4 5 6 7` 行。更高维度可以通过嵌套实现:如果每个位置放的是矩阵而不是向量,就定义三维数组。
### 编辑器中的体验
在 IDE 中,数组符号完全受支持。输入上述表达式后,按回车即可看到结果。点击“显示为数组符号”按钮可以以格式化的多行数组符号打印输出,而且该输出本身就是有效的 APL 语法——你可以直接编辑这个块,比如修改文字或数字,再重新求值。编辑器中还有一个“用数组符号编辑”的按钮,将数组内容展开为数组符号形式,允许自由修改。之后可以通过“编辑”->“重新格式化”(或数字键盘上的斜杠)将编辑结果规范化。
### 命名空间符号
类似地,用括号 `()` 配合 `name: value` 的形式可以定义命名空间。例如:
```
(foo: 1 2 3 ⋄ bar: 4 5 6)
```
这会创建一个包含 `foo` 和 `bar` 两个名字的命名空间。空括号 `()` 因为存在歧义(空向量还是空命名空间),被定义为空命名空间(因为已有其他方式写空向量如 `''` 或 `⍬`)。
数组符号完美支持嵌套,可以在命名空间内部再嵌入矩阵或其他结构。
## 内联跟踪
内联跟踪器是版本 20 新增的调试工具,用于逐步观察复杂表达式中每个原语的执行顺序和中间结果。它比传统的逐行跟踪更细致,能一次只函数一个地推进。
### 使用方法
在会话中,选中一个表达式(例如一个函数调用),然后选择菜单“操作”->“内联跟踪”,或按快捷键 Ctrl+Alt+Enter。跟踪器会进入模式,把表达式分解为单个原语步骤,每一步显示当前参数和结果。
### 示例
例如表达式 `(⌈/⍵)÷10`,内联跟踪会首先展示 `⌈/` 被调用,右参数是 `⍵`,左参数为空(单子调用)。继续步进,它会计算 `⌈/`,然后显示除法操作,左参数是 `⌈/` 的结果,右参数是 `10`。
另一个更复杂的例子:`(⊢/¨⊢)` 在复用的应用上,内联跟踪能逐步显示每个 `⊢/` 对 `⍵` 的每个元素如何执行,最终混合得到结果。对于复杂的无注释代码或初学者理解执行顺序极其有用。
## Behind 组合运算符
Behind 是新的组合运算符,填补了之前只能预处理右参数(使用 compose `∘`)而不能预处理左参数的空白。
### 背景
Compose `∘` 将右参数进行预处理。例如 `neg recip`(先倒数再取反),其中 recip 预处理右参数。而 behind `⍤`(符号为 `⍤`,但文中用文字描述)允许预处理左参数。二元 behind 的定义是:`X f⍤g Y` 等价于 `(f X) g Y`——先将左参数 `X` 通过 `f` 转换,再交给 `g` 处理。如果缺省左参数,则 behind 会将右参数复制一份作为左参数(单子调用时等同于 `(f Y) g Y`)。
### 示例
- **成员资格应用**:我们想检查单词 `'dog'` 是否包含在字符向量列表 `'dog' 'cat' 'fish'` 中。直接使用 `'dog' ∊ 'dog' 'cat' 'fish'` 会因为广播导致扫描每个字母。传统做法是先用 `⊂` 封闭整个 `'dog'`。现在可以用 behind 重写:`⊂⍤∊`。然后定义为函数 `word_member ← ⊂⍤∊`,可以到处使用,甚至在 tacit 表达式中。
- **最小值掩码**:给定列表 `10 15 10 20`,想得到等于最小值的掩码。可写为 `(⌊⍵) = ⍵`,但 using behind 可以写成 `⌊⍤=`,其中 left argument 被复制一份。这样表达式直接是 `⌊⍤= `,简洁。
- **条件筛选**:`behind replicate` 是最有用的场景。例如从 `1 -2 3 -4 5` 中保留正数,可以写 `(×⍤) / ⍵`(其中 `×` 绑定 0 表示大于0的测试)。实际写法如 `(×∘0)⍤/`(假定的形式)。展示内联跟踪时,可以看到 `×` 先应用于左参数得到掩码,然后 replicate 执行。
Behind 让许多需要临时定义或包三明治的操作变得直接,尤其适合在 tacit 风格中使用。
## 系统函数(简要提及)
版本 20 还引入了系统函数 `⎕V`、`⎕VGET` 和 `⎕SH`(quad shell),但因时间限制未在演讲中详细展开。
---
**Source**: [Enhancements in Dyalog v20.0: Arrays, Namespaces, Composition, Inline Tracing - Asher Harvey-Smith](https://www.youtube.com/watch?v=1IaLs96lEEg)
相似文章
对 APL 等数组语言的有原则性重新思考
本文提出了一种有原则性的方法来重新思考 APL 等数组语言,通过将变量建模为输入维度的函数,旨在相较于传统方法提高可读性和错误检查能力。
@justloveabit: https://x.com/justloveabit/status/2055263377006747820
介绍Claude Code 2.1.142新版本与CodeGraph、MCP的组合使用,通过本地语义知识图谱大幅提升大型代码库的探索效率,tool call减少92%,速度提升71%。
Typst: Designing for Incrementality
Typst 通过约束记忆化(comemo)和纯函数设计,使语言和编译器协同工作,实现高效的增量编译和实时预览。文章详细介绍了布局缓存、模块评估记忆化、函数纯度以及内省系统的设计思路。
@ArizePhoenix: • 更快的追踪分析: 使用自然语言过滤器、一键图表缩放和专用注释列。 • 扩展…
Arize Phoenix 宣布更新,包括使用自然语言过滤器的更快追踪分析,以及用于管理保留分配和模型提供商的扩展 REST API。
布尔扫描的对称性
本文探讨了数组语言(如APL)中布尔扫描的对称性,通过函数方程和算法洞见讨论了折叠和扫描的优化方法。