簡體   English   中英

clojure動態綁定,讀取字符串和eval無法解析符號

[英]clojure dynamic binding, read-string and eval Unable to resolve symbol

  (declare ^:dynamic symbol-table)
  (defn answer []
    (prn "blah")
    (binding [symbol-table {:answer 42}]
      (-> "[:h1 (:answer symbol-table)]" read-string eval)))

上面的代碼在repl中執行時按預期運行。 它返回

cpress.hsp> (answer)
"blah"                                                                                                                                                                                      
[:h1 42]

但是,當它在由http-kit生成的線程中執行時,出現無法解析的符號

Exception in thread "Thread-43" 
java.lang.RuntimeException: Unable to resolve symbol: symbol-table in this context, compiling:(NO_SOURCE_PATH:0:0)
        at clojure.lang.Compiler.analyze(Compiler.java:6792)
        at clojure.lang.Compiler.analyze(Compiler.java:6729)
        at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3874)
        at clojure.lang.Compiler.analyzeSeq(Compiler.java:7005)
        at clojure.lang.Compiler.analyze(Compiler.java:6773)

在repl上對此進行模擬以生成一個線程來運行答案函數

  (.. (Thread. answer) start)

為什么會發生這種情況以及如何解決?

一些實驗表明,由於命名空間的原因,它找不到符號。 例如,我不是從讀取字符串中獲取表達式,而是輸入文字

  (defn answer2 []
    (binding [symbol-table {:answer 42}]
      (prn (eval `[:h1 (:answer symbol-table)])) ;;works                                                                                                                                    
      ;;(eval '[:h1 (:answer symbol-table)]) ;; does not works                                                                                                                              
      ))

第一個eval使用有效的語法引用,但是當我使用常規引用時,它不起作用。 語法引用解析名稱空間,而常規引用則不能。 如果read-string返回帶有命名空間限定符號的表達式,那么它將解決我認為的問題,但read-string不會

當您運行eval時,在運行時將在當前名稱空間中解析表單中不合格的符號(而不是在定義函數的名稱空間中)。

為了解決這個問題,您可以創建一個eval版本,並將其命名空間綁定到所需的命名空間:

(defn local-eval [x]
  (binding [*ns* (find-ns 'my-namespace)]
    (eval x)))

(顯然,您需要更改my-namespace以反映正確的名稱)。 然后使用它代替:

(defn answer []
  (binding [symbol-table {:answer 42}]
    (-> "[:h1 (:answer symbol-table)]" read-string local-eval)))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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