排名运算符与轴符号

rank operator vs axis notation

几年前我在大型机上偷看了 APL2,还记得有人向我展示了将向量添加到矩阵的问题的解决方案。

鉴于 a←4 4 ⍴ ⍳16⎕io←1

向行添加向量的旧方法类似于

a+(⍴a)⍴10 20 30 40

导致

11 22 33 44
15 26 37 48
19 30 41 52
23 34 45 56

将向量添加到矩阵的列是

a+(4 1⍴10 20 30 40)[;1 1 1 1]

或者,如果您愿意,

a+4/4 1⍴10 20 30 40

导致

11 12 13 14
25 26 27 28
39 40 41 42
53 54 55 56

幸运的是,我能够打电话给那天向我展示 APL2 的人(他已经退休但仍然回答他的 phone)并询问第二个解决方案,他立即记住了我在说什么.

新的 APL2 方法更加简洁、简洁和一致,这些示例将由 a+[2] 10 20 30 40a+[1] 10 20 30 40 解决。凉爽的。它在 Dyalog 中有效。

快进十年或更长时间,我看到有一个叫做排名运算符的新事物。第一个例子可以通过a(+⍤1) 10 20 30 40解决(我还在努力掌握括号的用法,我想我以为我理解了一点,我实际上再生了一些脑细胞)

尽管如此,没有直接(至少对我而言)类似于使用排名运算符的第二个示例 a+[1] 10 20 30 40。我不能说我完全理解它,但在我看来,等级运算符 "re-casts" 它的左参数通过折叠其维度而同时保持内容不变。太多年的 C++ 和 Java 影响了我思考事物的方式。

对于 a+[1] 10 20 30 40 是否有使用排名运算符的简单解决方案?到目前为止我发现的唯一想法是 ⍉(⍉a)(+⍤1) 10 20 30 40,它没有抓住要点并且破坏了整个目的。

为什么排名运算符比轴表示法更可取? "better" 是哪个? (可以肯定的是,这是一个含蓄的术语)乍一看,轴符号对我这个智商一般的人来说很容易掌握。我不能对排名运算符说同样的话。

是否有使用排名运算符 a+[1] 10 20 30 40 的简单解决方案?

是:a(+⍤1 0)10 20 30 40Try it online!
对于二元应用程序,排名运算符实际上需要一个双元素右操作数(但接受一个扩展到两个元素的单例)。 a(f⍤A B)b 意味着 a 的 rank-A 子数组应该与 b 的 rank-B 子数组配对。因此,在您的情况下,a(+⍤1)10 20 30 40(实际上意味着 a(+⍤1 1)10 20 30 40)表示应将 a(行)的排名 1 数组添加到排名 1 数组中10 20 30 40(整个向量)。这里,a(+⍤1 0)10 20 30 40 表示 a(行)的 rank-1 数组应该添加到 10 20 30 40(标量)的 rank-0 数组。

为什么排名运算符比轴表示法更可取?

等级运算符允许您完全控制从每个参数中获取的内容,而括号轴表示法仅允许您扩展排名较低的参数。等级运算符是语言的一个组成部分,可以与任何函数一起使用,甚至是用户定义的函数,而括号轴符号只能与二元标量函数、归约和混合函数的一小部分一起使用。

哪个“更好”?

由于排名运算符遵循运算符的正常 APL 语法并且普遍适用,因此它减少了要记住的规则量。此外,排名运算符还允许使用负数指定相对排名。因此,虽然 ⍤1 表示 适用于秩为 1 的子数组 ,但 ⍤¯1 表示 适用于比整个参数低一级的子数组 .在我看来,这足以安全地认为排名运算符比括号轴“更好”。

我仍在努力掌握括号的用法

我个人不喜欢括号,所以我明白你的意思了。幸运的是,您总是可以随心所欲地减少括号的数量。 a(+⍤1)10 20 30 40 中括号的唯一原因是将数组操作数 1 与数组参数 10 20 30 40 分开。任何其他分隔它们的方法也是可以接受的,我通常为此使用恒等函数 a+⍤1⊢10 20 30 40 Try it online!
但是,您也可以 curry right operands to dyadic operators, yielding monadic operators, which read very nicely: horizontally←⍤1 0 ⋄ vertically←⍤1 1 Try it online!

完整rank operator documentation is available online

我认为,为了将向量添加到矩阵,您不应再使用秩运算符搜索更简单的解决方案。我想引入等级运算符是为了实现原始标量函数的行为,也适用于已定义的函数。也就是说,如果你有一个定义的函数,比如

∇Z←A ADD B
 Z←A + B
∇

然后

a ADD[1] 10 20 30 40

会失败并迫使您使用排名运算符。等级运算符需要括号,因为它的语法有点可疑:

a +⍤1 10 20 30 40    ⍝ ???
a(+⍤1)10 20 30 40    ⍝ maybe this?
a(+⍤1 10) 20 30 40   ⍝ or maybe this?
a(+⍤1 10 20) 30 40   ⍝ or even this?

IBM 足够聪明,将排名运算符标准化但没有实现它(至少在我的 APL2 PC 演示版中)。

多年来,一种流行的观点是应避免使用方括号,即函数的索引和轴 [​​=42=]。这样做的一些理由是方括号语法异常并且与语言的其余部分不一致,方括号内参数的语义在函数组之间不同,它使解析复杂化,等等。 Google "apl axis operator anomalous" 很多例子。

索引

旧索引是熟悉的 x[i] 形式,备选方案包括 "pick" 和 "squad" 函数。更高维度的索引数组使用 x[i;j;k;...;n] 形式,其中 ; 分隔各个维度表达式。可以省略此表达式以表示 "all of that dimension"。然后是索引赋值,可以有选择地插入新值。

轴运算符

首先只有缩小+/[1]a、压缩b/[1]a、展开b\[1]a、最后旋转1⌽[2]x和反转⌽[2]x的轴规格规定.扫描 +\a 稍晚出现,连接 x,[1] y 和层压 x,[0.5] y 也是如此。 (浮点数 "axis" - 天啊)APL2 引入了更多案例,与您的示例 a +[2] b 不同,加上任意坐标 ⊂[2].

等级运算符提供了一种统一的方式来处理坐标规范。