根据我对apply的理解,它解压缩列表并将元素转换为函数的参数。
我看到(apply + [1 2 3])按预期工作,即:它相当于(+ 1 2 3)。
为什么(apply或[true false])无效?是不是等同于(或真假)?
答案 0 :(得分:19)
因为or
是一个宏,而不是一个普通的函数。您可以使用(some identity [true false])
获得相同的效果。
答案 1 :(得分:4)
作为或的替代方法,您可以使用(某些谓词coll)。
clojure.core / some([pred coll])
返回第一个逻辑true值 (pred x)对于coll中的任何x,否则 零。一个常见的习语是使用一套 作为预测,例如这将 return:fred if:fred是在 序列,否则为零:(一些#{:fred} coll)
答案 2 :(得分:3)
你可以尝试一些真实的吗?和假?谓词,
user=> (some true? [true false false])
true
user=> (not (some true? [true false false]))
false
user=> (some false? [true false false])
true
user=> (not (some false? [true false false]))
false
答案 3 :(得分:0)
或是一个宏,您不能将其用作值。
创建一个匿名函数,通过eval在运行时扩展或:
(apply #(eval (list* 'or %&)) [true false])
答案 4 :(得分:0)
值得注意的重要事项之一是评估模型。 or
短路,因此:(or true :some random expression that never gets evaluated:)
永远不会评估最后一次。 or
传统上与控制结构一样使用'逻辑或'。
在(f x y z)
的传统模型中,评估x,y和z,并将f应用于它们。
在(apply f vec)
的使用中,向量的内容未评估,它们按原样进行。使用符号向量可以清楚地看到这一点,它们在此上下文中不会对其绑定进行评估。然而,由于Clojure的矢量创建模型与其他lisps有所不同,[a b c d]
生成一个包含符号a
,b
的评估的向量,这一点被混淆了。 c
和d
。对比大多数Lisps,其中#(a b c d)
不评估符号,只是与评估(vector 'a 'b 'c 'd)
(或实际上(apply vector '(a b c d))
)相同。
因此,即使可以应用特殊的句法形式,它的结果也会有不透明的语义。 or
首先计算其第一个参数,如果为true,则停止并返回该参数,否则它将转到第二个并重复直到最后一个。在apply的情况下,参数已经全部被评估,如果它然后再评估一次?很可能在此过程中导致运行时错误?
从实现的角度来看,如果语法也是“对象”并且需要更复杂的评估模型,那么它将非常具有性能。所以它们不是在运行时解析,而是在编译时重写为编译器原语。
但是,由于这个原因,当or
在逻辑上而不是作为控制结构使用时,我自己发现函数or/f
,and/f
,{{1}很方便等等,可以使用哪些是真正的程序并评估它们的所有参数,因此可以应用。