[英]Why doesn't (apply or [true false]) work in Clojure?
根據我對apply的理解,它解壓縮列表並將元素轉換為函數的參數。
我看到(apply + [1 2 3])按預期工作,即:它相當於(+ 1 2 3)。
為什么(apply或[true false])無效? 是不是等同於(或真假)?
因為or
宏,不是正常的功能。 您可以使用(some identity [true false])
獲得相同的效果。
作為替代或你可以使用( 一些謂詞coll)。
clojure.core / some([pred coll])
返回coll中任何x的第一個邏輯真值(pred x),否則為nil。 一個常見的習慣是使用一個集合作為pred,例如這將返回:fred if:fred在序列中,否則為nil :( some some {{fred} coll)
你可以嘗試一些真實的嗎? 和假? 謂詞,
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
或者是一個宏,你不能用作值。
創建一個匿名函數,通過eval擴展或在運行時 :
(apply #(eval (list* 'or %&)) [true false])
值得注意的重要事項之一是評估模型。 or
短路,因此:( (or true :some random expression that never gets evaluated:)
永遠不會評估最后一個。 or
傳統上使用的控制結構與“邏輯或”一樣多。
在傳統的(fxyz)
模型中,評估x,y和z,並將f應用於它們。
在使用(apply f vec)
, 不評估向量的內容,它們按原樣進行。 使用符號向量可以清楚地看到這一點,它們在此上下文中不會對其綁定進行評估。 然而,由於Clojure的矢量創建模型與其他lisps有所不同, [abcd]
產生包含符號a
, b
, c
和d
的評估的向量,這使得這一點變得模糊。 對比大多數Lisp,其中#(abcd)
不評估符號,只是與評估(vector 'a 'b 'c 'd)
a'b'c'd (vector 'a 'b 'c 'd)
(或實際上(apply vector '(abcd))
)相同。
因此,即使可以應用特殊的句法形式,它的結果也會有不透明的語義。 or
首先評估它的第一個參數,如果為真,它會停止並返回它,否則它會轉到第二個並重復直到最后一個。 在apply的情況下,參數已經全部被評估,如果它然后再評估一次? 最有可能導致運行時錯誤?
從實現的角度來看,如果語法也是“對象”並且需要更復雜的評估模型,那么它將非常具有性能。 因此它們不會在運行時解析,而是在編譯時重寫為編譯器原語。
但是,由於這個原因,在邏輯上而不是作為控制結構使用or
使用時,我自己發現有功能or/f
and/f
, if/f
等等可用它們是真正的程序並且評估所有的他們的論點因此可以應用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.