[英]Variable scope + eval in Clojure
在 Clojure 中,
(def x 3)
(eval '(prn x))
打印 3,而
(let [y 3]
(eval '(prn y)))
和
(binding [z 3] (eval '(prn z)))
生成“無法解析 var”異常。
根據http://clojure.org/evaluation , eval
, load-string
等生成臨時命名空間來評估其內容。 因此,我希望上述代碼示例都不起作用,因為(def x 3)
是在我當前的命名空間中完成的,而不是由eval
創建的命名空間。
def
的情況下eval
具有綁定變量的表單?謝謝!
1.:
這不起作用的原因(或多或少)在您鏈接的頁面上給出:
It is an error if there is no global var named by the symbol […]
和:
[…]
在當前命名空間中進行查找以查看是否存在從符號到 var 的映射。 如果是,則該值是符號所引用的 var 的綁定值。
這是一個錯誤。
eval
在空(CL-lingo 中的null )詞匯環境中評估 forms。 這意味着,您不能從調用者的 scope 訪問詞法變量綁定。 此外, binding
會為現有變量創建新的綁定,這就是為什么您不能“單獨”使用它,而無需declare
d 或定義您def
綁定的變量。 此外,詞法變量(至少在 CL 中,但如果 Clojure 不是這種情況,我會感到驚訝)在運行時已經不復存在——它們被轉換為地址或值。
另請參閱我關於此主題的舊帖子。
2.:
所以,你必須使用動態變量。 您可以避免顯式def
,但您仍然至少需要declare
它們(其中def
s var 名稱沒有綁定):
user=> (declare ^:dynamic x)
#'user/x
user=> (binding [x 10] (eval '(prn x)))
10
nil
順便說一句:我想您知道為什么需要 eval,並且當其他解決方案合適時,它的使用被認為是邪惡的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.