Clojureで機能しないのはなぜですか([True False]を適用または[True False])機能させませんか?
質問
私がApplyについて理解していることから、それはリストを開梱し、要素を関数の引数に変えます。
(apply + [1 2 3])が期待どおりに機能すること、つまり( + 1 2 3)に相当することがわかります。
なぜ(適用または[true false])無効なのですか?それは同等ではありません(または真の偽)?
解決
なぜなら or
マクロであり、通常の関数ではありません。同じ効果を得ることができます (some identity [true false])
.
他のヒント
代替手段として また 使用できます(いくつか 述語coll)。
clojure.core/some([pred coll])
collのxの最初の論理真の値(pred x)を返します。 1つの一般的なイディオムは、セットをPredとして使用することです。たとえば、これは戻ります。Fredif:Fredがシーケンスにあり、そうでなければnil:(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
また マクロであり、価値として使用できません。
匿名関数を作成し、拡大します また で ランタイム 評価経由:
(apply #(eval (list* 'or %&)) [true false])
注意すべき重要なことの1つは、評価モデルです。 or
したがって、短絡、したがって: (or true :some random expression that never gets evaluated:)
最後を評価しないでください。 or
従来、制御構造と同じくらい「論理的または」と同じくらい使用されています。
の伝統的なモデルで (f x y z)
, 、x、y、zを評価し、fがそれらに適用されます。
の使用で (apply f vec)
ベクトルの内容はです いいえ 評価されて、それらはそのままと考えられます。これは、シンボルのベクトルで最もはっきりと表示されます。このコンテキストでは、バインディングを評価しません。ただし、これは、ベクターの作成のためのClojureのモデルが他のLISPよりも何らかの異なるという事実によって難読化されています。 [a b c d]
シンボルの評価を含むベクトルを生成します a
, b
, c
, 、 と d
. 。ほとんどのLISPは対照的です #(a b c d)
シンボルを評価せず、評価するのと同じです (vector 'a 'b 'c 'd)
(または実際に (apply vector '(a b c d))
).
したがって、特別な構文フォームを適用できたとしても、結果は不透明なセマンティクスがあります。 or
最初に最初の引数を評価します。もし真であれば、それは停止してそれを返します。応募の場合、引数はすべて評価されていますが、2回目の評価を行う必要がありますか?途中でランタイムエラーが発生する可能性が最も高いですか?
実装の観点から見ると、構文が「オブジェクト」でもあり、はるかに複雑な評価モデルが必要な場合、非常にパフォーマンスが非常に活発になります。そのため、実行時に解決されるのではなく、コンパイル時にコンパイラプリミティブに書き直されます。
しかし、この理由で、いつ or
制御構造としてではなく論理的に使用されています、私自身は関数を持っているのが便利だと思います or/f
, and/f
, if/f
, 、真の手順であり、それらのすべての議論を評価し、したがって適用できるET CETETERA。