Functional programming APL中的条件函数

Functional programming APL中的条件函数,functional-programming,conditional-operator,apl,Functional Programming,Conditional Operator,Apl,在APL方言中,是否有条件函数的符号或众所周知的习语 我肯定我遗漏了一些东西,因为这是一个基本的语言元素。在其他语言中,它被称为条件运算符,但我将在这里避免使用该术语,因为APL运算符完全是另一回事 例如C和朋友有x?T:F Lisp有(如果x T F) Python有T if x else F 等等 我知道现代的APL有:If和friends,但它们是控制程序流的命令语句:它们不返回值,不能在表达式中使用,当然也不能应用于布尔数组。他们有完全不同的目的,这对我来说很好 我能想出的唯一合适的函数

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

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

例如C和朋友有
x?T:F

Lisp有
(如果x T F)

Python有
T if x else F

等等

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

我能想出的唯一合适的函数选择表达式是
(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
我试着用squad
,但在布尔数组上失败得很惨。即使我可以,它仍然必须嵌入
⎕IO
或硬编码的1,就可读性而言更糟糕

在我继续定义我自己的
if
并在我将要编写的每个程序中使用它之前,这方面有什么佳能吗?我是否缺少一个明显的函数或运算符


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

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

我认为答案是在这方面没有标准

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

而对于布尔数组,我使用的索引与上面的操作相同:

f t[x]
我总是使用索引原点0,所以不需要加1,也不需要paren


如果这些还不够简单,我认为您必须使用名为“If”的函数来覆盖它们。这也会让你把真与假放在可能更自然的t f排序中。

这些问题:

(f t)[x]
x⌷f t
x⊃f t
是指对
t
f
进行评估

如果你想短路,你可以使用防护装置:

{x:t ⋄ f}
这相当于

if (x) {
    return t;
}
f;

在一种类似C的语言中。

一种古老的习语,有点像C的三元运算符
?:并返回以下结果:

  r←⍎(¯3 3)[x=42]↑'6×8 ⋄ 6×7' 
请注意,这是为原点0编写的,-3周围的括号是为了清晰起见

x=42计算为零或一,根据这个答案,我们选择-3或3,从而选择并执行字符串的前3个元素(“6x8”)或最后3个元素(“6x7”)。钻石⋄ 只是为了装饰


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

在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


这是一个常见的问题,我认为没有标准答案的原因是,对于您使用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
这个特定的实现以
到子句,因为这有时很方便。没有左手参数,它传入

APL表达式:

(1+x=0)⌷y z 
(1+~a)⌷b c
应为与之等效的C语言

x?y:z
还有所有其他的

(1+x>0)⌷y z 
为了

它应该与C语言等效:

a?b:c

非常感谢。我有C的背景,所以索引原点为零对我来说很有意义,但我不想违背艾弗森的大量论文都假设原点为零的“APL方式”。如果它能简化你的工作,这是一个有效的选择。这不是有点混乱吗?(我讨厌计算字符向量的长度!)。我这里没有APL键盘,但是不能使用两个字符向量的嵌套数组作为take的rarg吗?我怀疑OP的答案取决于我并不完全清楚的上下文。我最后一次看到或使用它是在1979年左右的一个或另一个(夏普或STSC)分时系统上。嵌套数组当时不可用。这是一个愚蠢的问题。需要一艘班轮吗?(是的,我知道这是APL),但是如果您想避免执行这两个函数,那么简单的条件执行有什么错呢。(对不起,我没有APL键盘),比如:。。。执行(一些布尔值)/'f'执行(~一些布尔值)/'t'清晰不是罪恶@ngn所以,在修复了我的vim apl错误之后,我试图得到这样的东西。。。却发现这只是迪亚洛格!啊,太糟糕了。是的,execute可以用于此目的,但我宁愿避免execute,除非它显然是解决问题的最佳方式。在这种情况下,创建一个小实用程序fn,该实用程序将两个表达式作为输入,并使用一个控制结构来仅计算适当的参数,这将起作用,而且更清晰。这样的fn可以返回一个结果。第二个结果不应该是匹配的吗?我在这里看到的问题是,这些值得到了预评估,尽管它们不需要进行预评估。@⋄ F}
。你想这么做吗?@Adám我为什么要这么做?对
x<=0?y:z
(1+~a)⌷b c
a?b:c