Car*_*icz 5 binding eval clojure
我想在数据结构中预先存储一堆函数调用,然后在另一个函数中评估/执行它们.
这对于在命名空间级别定义的函数按计划工作defn(即使函数定义在我创建数据结构之后),但不适用于函数定义的函数let [name (fn或letfn函数内部的函数.
这是我的小型自包含示例:
(def todoA '(funcA))
(def todoB '(funcB))
(def todoC '(funcC))
(def todoD '(funcD)) ; unused
(defn funcA [] (println "hello funcA!"))
(declare funcB funcC)
(defn runit []
(let [funcB (fn [] (println "hello funcB"))]
(letfn [(funcC [] (println "hello funcC!"))]
(funcA) ; OK
(eval todoA) ; OK
(funcB) ; OK
(eval todoB) ; "Unable to resolve symbol: funcB in this context" at line 2
(funcC) ; OK
(eval todoC) ; "Unable to resolve symbol: funcC in this context" at line 3
)))
Run Code Online (Sandbox Code Playgroud)
如果您想知道我的测试设置,要查看这6个语句的结果,我评论/取消注释OK /失败行的具体内容,然后(runit)从REPL 调用.
是否有一个简单的解决方法,我可以保证让eval"d quote到功能d调用另一个函数内部定义的函数工作?
更新:
这(基于danlei的建议)确实有效.让我们看看我是否可以在"现实生活中"使用这种方法!
(def todoB '(funcB))
(declare funcB)
(defn runit []
(binding [funcB (fn [] (println "hello funcB"))]
(funcB)
(eval todoB) ; "Unable to resolve symbol: funcB in this context" at line 1!
))
Run Code Online (Sandbox Code Playgroud)
更新:
这段代码进入我的约束满足问题的解决方案- 我想知道谁拥有斑马!我对Clojure很熟悉,尤其是函数式编程,这使得练习非常具有挑战性.我陷入了很多陷阱,但我很乐意,因为这是学习经历的一部分.
我曾经将约束指定为一堆简单的向量,如下所示:
[:con-eq :spain :dog]
[:abs-pos :norway 1]
[:con-eq :kools :yellow]
[:next-to :chesterfields :fox]
Run Code Online (Sandbox Code Playgroud)
其中每个向量的第一个将指定约束的类型.但这导致我对这些规则的调度机制的笨拙实现,所以我决定将它们编码为(引用)函数调用:
'(coloc :japan :parliament) ; 10
'(coloc :coffee :green) ; 12
'(next-to :chesterfield :fox) ; 5
Run Code Online (Sandbox Code Playgroud)
所以我可以用简单的方式发送约束规则eval.这似乎更优雅和"lisp-y".但是,这些函数中的每一个都需要访问我的域数据(命名vars),并且这些数据会随着程序的运行而不断变化.我不想通过引入额外的参数来玷污我的规则,所以我希望通过动态范围vars可用于eval'd函数.
我现在已经知道动态范围可以使用binding,但它也需要一个declare.
你的意思是这样的吗?
(def foo '(bar))
(declare bar)
(binding [bar (fn [] (println "hello bar"))]
(eval foo))
Run Code Online (Sandbox Code Playgroud)
如果是,您的问题将减少到:
(let [foo 1]
(eval 'foo))
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为eval不会在词法环境中进行评估.你可以使用vars解决这个问题:
(declare foo)
(binding [foo 1]
(eval 'foo))
Run Code Online (Sandbox Code Playgroud)
就这一点而言,Clojure似乎与CL具有相似的语义,参见 该CLHS:
评估当前动态环境和null词法环境中的表单.