【问题标题】:Conditional function in APLAPL 中的条件函数
【发布时间】:2017-12-10 10:37:39
【问题描述】:

在任何 APL 方言中,是否有条件函数的符号或众所周知的习语?

我确定我遗漏了一些东西,因为它是一种基本的语言元素。在其他语言中,它被称为 条件运算符,但我将在此处避免使用该术语,因为 APL 运算符完全是另外一回事。

比如C和朋友有x ? T : F
LISP 有 (if x T F)
Python有T if x else F
等等。

我知道现代 APL 有 :If 和朋友,但它们是控制程序流的命令式语句:它们不返回值,不能在表达式中使用,当然也不能应用于布尔数组。它们完全有不同的目的,这对我来说很好。

我能想到的唯一合适的表达式是(F T)[⎕IO+x],虽然它可以完成工作,即使在数组上,它看起来也不是特别简写或可读:

      ('no' 'yes')[⎕IO+(⍳5)∘.>(⍳5)]
no  no  no  no  no
yes no  no  no  no
yes yes no  no  no
yes yes yes no  no
yes yes yes yes no

我尝试使用小队 提出类似的表达式,但在布尔数组上惨遭失败。即使可以,它仍然必须嵌入 ⎕IO 或硬编码的 1,就可读性而言,这更糟糕。

在我继续定义我自己的if 并在我将要编写的每个程序上使用它之前,是否有任何规范?我是否缺少明显的功能或运算符?

(SO 上有没有 APL 程序员?:-)

【问题讨论】:

    标签: functional-programming conditional-operator apl


    【解决方案1】:

    这些问题:

    (f t)[x]
    x⌷f t
    x⊃f t
    

    tf 是否都会被评估。

    如果你想把东西短路,你可以使用守卫:

    {x:t ⋄ f}
    

    这相当于

    if (x) {
        return t;
    }
    f;
    

    使用类 C 语言。

    【讨论】:

    • 更愚蠢的问题。需要一个班轮吗? (是的,我知道这是 APL),但是如果您想避免执行这两个函数,那么简单的条件执行有什么问题。 (对不起,我没有 APL 键盘),类似于:... 执行 (some_boolean) / 'f' 执行 (~some_boolean)/'t' 清晰不是罪过!
    • @ngn 所以,在修复了我的 vim-apl 错误之后,我试图得到这样的东西......只是发现它只是 Dyalog !啊,太糟糕了。
    • 是的,execute 可以用于此目的,但我更愿意避免执行,除非它显然是解决问题的最佳方法。在这种情况下,创建一个小型实用程序 fn 将两个表达式作为输入并使用控制结构来仅评估适当的参数,这样 IMO 会更清晰。这样的 fn 可以返回结果。
    【解决方案2】:

    是的,SO 上有 APL 程序员(但不是很多!)。

    我认为答案是没有标准。

    对于标量解决方案,我使用“pick”:

      x⊃f t
    

    对于布尔数组,我像上面一样使用索引:

    f t[x]
    

    我总是使用索引原点零,所以不需要加1,也不需要括号。

    如果这些还不够简单,我认为你必须用一个名为“if”的函数来覆盖它们。这也可以让你把真假放在更自然的 t f 顺序中。

    【讨论】:

    • 谢谢。我来自 C 背景,所以索引原点为零对我来说很有意义,但我不想违背“APL 方式”
    • 艾弗森的大量论文自始至终都假定原点为零。如果它简化了您正在做的事情,这是一个有效的选择。
    • 我是 APL 新手,所以我可能会产生误解,但我认为第二个表达式中是否需要括号可能取决于方言。在 Dyalog 网站 (dyalog.com/uploads/documents/MasteringDyalogAPL.pdf) 上第 172 页的 Bernard Legrand 所著的“掌握 Dyalog APL”一书中,它说 IBM 兼容版本的 APL 处理此问题的方式与 Dyalog 不同。
    【解决方案3】:

    在 Dyalog APL 中,您可以使用:

    'value if true' (⊣⍣condition) 'value if false'
    

    这个想法是将(left tack - 它总是返回它的左参数,同时丢弃右参数)0(对于 false)或 1(对于 true)次 - 到右参数。因此,如果它被应用 0 次(即根本没有),则正确返回未修改的参数,但如果应用(一次),则应用左参数。例如:

          a b←3 5
          Conditional←⊣⍣(a=b)
          'match' Conditional 'different'
    different
          a b←4 4
          Conditional←⊣⍣(a=b)
          'match' Conditional 'different'
    match
    

          Cond←{⍺(⊣⍣⍺⍺)⍵}
          bool←a=b
          'match'(bool Cond)'different'
    match
    

    【讨论】:

    • 第二个结果不应该是match吗?
    • 我在这里看到的问题是这些值会被预先评估,尽管不需要它们。
    • @ΈρικΚωνσταντόπουλος 想知道为什么没有人回答{x : T ⋄ F}。你想这样做吗?
    • @Adám 我为什么要这样做?是的somebody has.
    【解决方案4】:

    执行类似于 C 的三元运算符 ? : 并返回结果的一个古老的习惯用法如下:

      r←⍎(¯3 3)[x=42]↑'6×8 ⋄ 6×7' 
    

    请注意,这是为原点 0 编写的,并且 -3 3 周围的括号是为了清楚起见。

    x=42 计算结果为 0 或 1,取决于这个答案,我们选择 -3 或 3,因此选择并执行字符串的前 3 个元素(“6x8”)或后 3 个元素(“6x7”) .钻石 ⋄ 只是用来装饰的。

    不用说,如果有 :if :else 可用,则可能不会这样编码,尽管控制结构形式不会返回结果。

    【讨论】:

    • 是不是有点乱? (我讨厌必须计算 char 向量的长度!)。我这里没有 APL 键盘,但不能使用两个 char 向量的嵌套数组作为 take 的 rarg 吗?我怀疑 OP 的答案取决于我并不完全清楚的上下文。
    • 我最后一次看到或使用它是在 1979 年左右,在一个或另一个(夏普或 STSC)分时系统上。嵌套数组当时不可用。
    【解决方案5】:

    这是一个常见的问题,我认为没有标准答案的原因是,对于您使用 APL 所做的事情,实际上对它的需求比其他语言要少。

    也就是说,有时需要它,而我在 GNU APL 中实现 IFELSE 运算符的方式就是使用这个函数:

    ∇Z ← arg (truefn IFELSE falsefn) condition ;v
      v←⍬
      →(0=⎕NC 'arg')/noarg
      v←arg
    noarg:
      →condition/istrue
      Z←falsefn v
      →end
    istrue:
      Z←truefn v
    end:
    ∇
    

    函数可以这样调用:

          3 {'expression is true' ⍵} IFELSE {'was false' ⍵} 0
    was false 3
    

    这个特定的实现将左侧参数作为 传递给子句,因为这有时很方便。如果没有左手参数,它会传入

    【讨论】:

      【解决方案6】:

      APL 表达式:

      (1+x=0)⌷y z 
      

      应该是

      的 C 语言等价物
      x?y:z
      

      还有其他人

      (1+x>0)⌷y z 
      

      x<=0?y:z
      

      等等。一般来说,如果 a b c 是各自语言的表达式,则 APL 表达式:

      (1+~a)⌷b c
      

      应该相当于C语言:

      a?b:c
      

      【讨论】:

        猜你喜欢
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-22
        • 2021-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多