18

時折、他の人の Clojure コードを見ているdefnと、var-quote 構文を使用して定義され、呼び出された関数が表示されます。

user> (defn a [] 1)
#'user/a
user> (a)   ; This is how you normally call a function
1
user> (#'a) ; This uses the var-quote syntax and produces the same result
1

私の人生では、関数を呼び出すこれら2つの方法の違いを理解できません。評価ドキュメントには、呼び出しの演算子が var である場合に何が起こるかを示すものは何も見つかりません。これは、2 番目の形式が好まれる理由を示唆している可能性があります。bindingどちらも、割り当てと構文引用に対して同じように応答するようです。

(a)それで、誰かがと上記の違いを説明するコードサンプルを提供してもらえます(#'a)か?

編集: var-quote を使用して、字句バインディングによってシャドウされている var を取得できることは知っていletますが、私が見ているコードではそうではないようです。

4

2 に答える 2

21

(#'a)は常にvar aを参照し(a)ますが、ローカル バインディングによってシャドーイングできます。

user> (defn a [] 1)
#'user/a
user> (let [a (fn [] "booh")] [(a) (#'a)])
["booh" 1]

しかし、var-quote / 関数呼び出しの実際の使用のほとんどは、var-quote 式を直接呼び出すのではなく、その値をキャッシュして、渡されたときに高次構造が var a の値ではなく現在の値を参照するようにします。

(defn a [] 1)
(defn my-call [f] (fn [] (+ 1 (f))))
(def one (my-call a))
(def two (my-call #'a))
(defn a [] 2)

user> (one)
2
user> (two)
3

これは、他のパッケージの他の関数の束にラップされる関数を変更する対話型開発に最も役立ちます。

于 2013-02-08T00:25:05.057 に答える
7

2 番目の形式では、clojure が設定するプライバシー制限を回避できます。

したがって、たとえば、プライベート関数を含むライブラリを開発し、それらを別の名前空間からテストしたい場合、それらを直接参照することはできません。ただし、var quote 構文を使用してそれらにアクセスできます。これは非常に便利です。

プライバシーは clojure は、本質的に、Java で見られるプライバシーとは対照的に、自動ドキュメンテーションの形式です。あなたはそれを回避することができます。

user> (defn- a [] 1)
#'user/a
user> (ns user2)
nil
user2> (user/a)
CompilerException java.lang.IllegalStateException: var: #'user/a is not public,    compiling:(NO_SOURCE_PATH:1) 
user2> (#'user/a)
1
user2> 
于 2013-02-08T10:50:17.153 に答える