簡體   English   中英

Clojure 中的變量 scope + eval

[英]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/evaluationevalload-string等生成臨時命名空間來評估其內容。 因此,我希望上述代碼示例都不起作用,因為(def x 3)是在我當前的命名空間中完成的,而不是由eval創建的命名空間。

  1. 為什么第一個代碼示例有效,而后兩個無效?
  2. 如何在不使用def的情況下eval具有綁定變量的表單?

謝謝!

1.:

這不起作用的原因(或多或少)在您鏈接的頁面上給出:

It is an error if there is no global var named by the symbol […]

和:

[…]

  1. 在當前命名空間中進行查找以查看是否存在從符號到 var 的映射。 如果是,則該值是符號所引用的 var 的綁定值。

  2. 這是一個錯誤。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM