首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clojure动态绑定、读字符串和eval无法解析符号。

clojure动态绑定、读字符串和eval无法解析符号。
EN

Stack Overflow用户
提问于 2017-11-08 10:28:04
回答 1查看 449关注 0票数 1
代码语言:javascript
复制
  (declare ^:dynamic symbol-table)
  (defn answer []
    (prn "blah")
    (binding [symbol-table {:answer 42}]
      (-> "[:h1 (:answer symbol-table)]" read-string eval)))

当在repl上执行时,上面的代码将按预期运行。它回来了

代码语言:javascript
复制
cpress.hsp> (answer)
"blah"                                                                                                                                                                                      
[:h1 42]

但是,当它在由http-kit生成的线程中执行时,我将无法解析符号。

代码语言:javascript
复制
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上模拟此操作,请生成一个线程来运行应答函数。

代码语言:javascript
复制
  (.. (Thread. answer) start)

为什么会发生这种情况,以及如何解决?

一些实验表明,由于名称空间的原因,它无法找到符号。例如,我没有从读字符串中获取表达式,而是输入了一个文字。

代码语言:javascript
复制
  (defn answer2 []
    (binding [symbol-table {:answer 42}]
      (prn (eval `[:h1 (:answer symbol-table)])) ;;works                                                                                                                                    
      ;;(eval '[:h1 (:answer symbol-table)]) ;; does not works                                                                                                                              
      ))

第一个eval使用语法引用,但当我使用常规引用时,它不起作用。语法引用解析命名空间,而常规引用不能解析命名空间。如果读字符串返回一个带有命名空间限定符号的表达式,那么我认为它将解决我的问题,但读字符串不会。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-08 11:31:36

运行eval时,表单中的非限定符号将在运行时(而不是定义函数的名称空间)的当前命名空间中解析。

要解决这个问题,您可以创建一个包含绑定到所需名称空间的eval版本:

代码语言:javascript
复制
(defn local-eval [x]
  (binding [*ns* (find-ns 'my-namespace)]
    (eval x)))

(显然,您需要更改my-namespace以反映正确的名称)。然后你用它来代替:

代码语言:javascript
复制
(defn answer []
  (binding [symbol-table {:answer 42}]
    (-> "[:h1 (:answer symbol-table)]" read-string local-eval)))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47177243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档