我希望能够在数据结构中预存一些函数调用,并在另一个函数内部稍后评估/执行它们。对于使用
下面是一个简单的自包含示例:
如果你好奇我的测试设置,想要查看这6个语句的结果,我会注释/取消注释一些OK /失败的行,然后从REPL中调用(runit)。
有没有简单的解决方案可以让在另一个函数内定义的函数的eval'd quote'd调用函数正常工作?
更新:
这种方法(基于danlei的建议)确实有效。让我们看看我能否在“现实生活”中让这种方法起作用!
所以我可以通过简单的
我现在已经学会了使用
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
)))
如果你好奇我的测试设置,想要查看这6个语句的结果,我会注释/取消注释一些OK /失败的行,然后从REPL中调用(runit)。
有没有简单的解决方案可以让在另一个函数内定义的函数的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!
))
更新:
这段代码将会被用于我的解决方案,解决一个约束满足问题 - 我想要找出谁是斑马的主人! 我对Clojure和函数式编程都比较陌生,这让我练习变得更加有挑战性。我会遇到许多困难,但这是学习过程中的一部分。
我曾经将约束条件指定为一堆简单的向量,就像这样:
[:con-eq :spain :dog]
[:abs-pos :norway 1]
[:con-eq :kools :yellow]
[:next-to :chesterfields :fox]
每个向量的第一个元素指定了约束的类型。但这会导致一种尴尬的实现方式,需要为这些规则编写调度机制,因此我决定将它们编码为(引用)函数调用:
'(coloc :japan :parliament) ; 10
'(coloc :coffee :green) ; 12
'(next-to :chesterfield :fox) ; 5
所以我可以通过简单的
eval
调度约束规则。这似乎更加优雅和“lisp-y”。然而,每个函数都需要访问我的域数据(命名为vars
),并且该数据在程序运行时不断变化。我不想通过引入额外的参数来玷污我的规则,因此我希望通过动态作用域使vars
对eval
的函数可用。我现在已经学会了使用
binding
进行动态作用域,但它也需要一个declare
。
binding
的实际应用。我非常乐意听取对我的业余方法的建设性批评。 - Carl Smotricz