了解 APL 中的域错误:copy/pasting 分两步进行

Understanding DOMAIN ERROR in APL: copy/pasting results in two steps works

我已经尝试使用 APL,但 运行 进入域错误,我无法理解。

这是我在 gnu-apl 中尝试过的:


      isPrime ← {2=⍴(0=(⍳⍵)|⍵)/⍳⍵}
      (isPrime¨ ⍳20) / ⍳20
 DOMAIN ERROR
      (isPrime¨⍳20)/⍳20
      ^             ^
</pre>

令我惊讶的是,当我刚刚评估对 isPrime 的调用并复制结果数组时,DOMAIN ERROR 消失了:


      (isPrime¨ ⍳20)<br>
 0  1  1  0  1  0  1  0  0  0  1  0  1  0  0  0  1  0  1  0
</pre>


      0  1  1  0  1  0  1  0  0  0  1  0  1  0  0  0  1  0  1  0 / ⍳20
2 3 5 7 11 13 17 19
</pre>

... 但是将其分配给变量也不起作用:


      ps ← (isPrime¨ ⍳20)
      ps / ⍳20
DOMAIN ERROR
      ps/⍳20
      ^  ^
</pre>

现在我很困惑。我原以为所有三种方式都应该以相同的方式工作:

  1. 直接调用函数
  2. 调用它并copy/pasting它的结果
  3. 使用临时变量代替 copy/paste。

我还仔细检查了基于浏览器的 ngn/apl interpreter。我不得不稍微更改代码,因为 itoa 从 0 开始计数。但是,域错误是相同的:


isPrime ← {2=⍴(0=(1+⍳⍵)|⍵)/(1+⍳⍵)}</p>

<p>⍝ (isPrime¨ (1+⍳20)) / (1+⍳20)
⍝ DOMAIN ERROR</p>

<p>isPrime¨ (1+⍳20)
⍝ 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0</p>

<p>ps ← isPrime¨ (1+⍳20)
⍝ ps / (1+⍳20)
⍝ DOMAIN ERROR</p>

<p>0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 / (1+⍳20)
⍝ 2 3 5 7 11 13 17 19
</pre>

由于两个不同的实现表现出相同的行为,我很确定错误在我这边。不幸的是,我对APL的了解非常有限。

我没有执行你的代码,但我怀疑 isPrime return 中的每个元素本身就是一个向量。

问题是来自 isPrime 的 return 中的每个元素本身都是一个单元素向量 - 并且归约需要一个简单的布尔向量。

⍴¨isPrime¨⍳20
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
      (∊isPrime¨⍳20)/⍳20
2 3 5 7 11 13 17 19

(我不确定这是否适用于 GNU APL。monadic 是 "enlist" 它将把嵌套向量转换成一个简单的向量...)

为避免此问题,您应确保函数的结果是标量。虽然它看起来像那样,但您将标量 (2) 与 1 元素向量 (⍴) 进行比较,后者又使其成为向量。因此,如果您将该单元素向量转换为标量,您的函数将按预期工作:

isPrime ← {2=⍬⍴⍴(0=(1+⍳⍵)|⍵)/(1+⍳⍵)}