在Clojure中执行动态绑定的函数 [英] Executing a dynamically bound function in Clojure

查看:111
本文介绍了在Clojure中执行动态绑定的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在数据结构中预先存储一堆函数调用,然后在另一个函数中评估/执行它们。

I'd like to pre-store a bunch of function calls in a data structure and later evaluate/execute them from within another function.

对于在 defn (即使函数定义在我创建数据结构之后)的命名空间级别定义的函数,但不能使用让函数中的[name(fn letfn ]。

This works as planned for functions defined at namespace level with defn (even though the function definition comes after my creation of the data structure) but will not work with functions defined by let [name (fn or letfn inside the function.

包含的示例:

(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
)))

如果你想知道我的测试设置,看到这6个语句的结果我评论/取消注释确定/失败的行的特定,然后调用(runit)从REPL。

In case you're wondering about my test setup, to see the result of those 6 statements I comment/uncomment specific of the OK/failing lines and then call (runit) from the REPL.

有一个简单的解决方案,我可以承诺得到 eval 'd

Is there a simple fix I could undertake to get eval'd quoted calls to functions to work for functions defined inside another function?

更新:

这(根据danlei的建议) 让我们看看是否可以让这个方法在现实生活中工作。

This (based on danlei's suggestion) does work. Let's see if I can get this method working in "real life!"

(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!
))






更新:

这段代码进入我的解决方案, a href =http://stackoverflow.com/questions/2500504/constraint-satisfaction-problem>约束满足问题 - 我想了解谁拥有斑马!我对Clojure很新,特别是函数式编程,这使得这个练习颇具挑战性。我陷入了很多坑,但我同意,因为它是学习经验的一部分。

This code is going into my solution for a Constraint Satisfaction Problem - I want to find out who owns the zebra! I'm fairly new to Clojure and especially functional programming, and this has made the exercise quite challenging. I'm falling into a lot of pits but I'm OK with that as it's part of the learning experience.

我用来指定约束作为一堆简单向量,如下:

I used to specify the constraints as a bunch of simple vectors, like this:

[:con-eq :spain :dog]
[:abs-pos :norway 1]
[:con-eq :kools :yellow]
[:next-to :chesterfields :fox]

其中每个向量的第一个将指定约束的类型。但是,这导致我对这些规则的分派机制的一个尴尬的实现,所以我决定将它们编码为(引用)函数调用:

where the first of each vector would specify the kind of constraint. But that led me to an awkward implementation of a dispatch mechanism for those rules, so I decided to encode them as (quoted) function calls instead:

'(coloc :japan :parliament) ; 10
'(coloc :coffee :green) ; 12
'(next-to :chesterfield :fox) ; 5

所以我可以用一个简单的 eval 。这看起来很多更优雅和lisp-y。但是,这些函数都需要访问我的域数据(名为 vars ),并且该数据会随着程序运行而不断变化。我不想通过引入一个额外的参数来破坏我的规则,所以我想让 vars 可用于 eval

so I can dispatch the constraining rule with a simple eval. This seems a lot more elegant and "lisp-y." However, each of these functions needs to access my domain data (named vars), and this data keeps changing as the program runs. I didn't want to blemish my rules by introducing an extra argument, so I wanted vars to be available to the eval'd functions via dynamic scoping.

我现在了解到动态范围可以使用 binding 来完成,但它还需要一个声明

I've now learned that dynamic scoping can be done using binding, but it also needs a declare.

推荐答案

这个?

(def foo '(bar))
(declare bar)

(binding [bar (fn [] (println "hello bar"))]
  (eval foo))

如果是,您的问题会简化为:

If yes, your problem reduces to this:

(let [foo 1]
  (eval 'foo))



这不会工作,因为eval不会在词法环境中求值。你可以使用vars来解决:

This won't work, because eval does not evaluate in the lexical environment. You can get around that using vars:

(declare foo)

(binding [foo 1]
  (eval 'foo))

就这一点而言,Clojure似乎有类似于CL的语义,cf。 CLHS

As far as that is concerned, Clojure seems to have similar semantics to CL, cf. the CLHS:


在当前动态环境和null词法环境中求值形式。

Evaluates form in the current dynamic environment and the null lexical environment.

这篇关于在Clojure中执行动态绑定的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆