Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure:如何在本地范围内评估引用的表单?_Clojure - Fatal编程技术网

Clojure:如何在本地范围内评估引用的表单?

Clojure:如何在本地范围内评估引用的表单?,clojure,Clojure,我想定义一个宏,随机选择一个给定表达式并对其求值。比如说, (equal-chance (println "1") (println "2")) (let [x 10] (eval '(println x))) 一半时间打印“1”,另一半时间打印“2” 我试着用 (defmacro equal-chance [& exprs] `(rand-nth '~exprs)) 但这将返回一个引用的表单,而不是对其进行计算(即,它将返回(println“1”),而不是实际

我想定义一个宏,随机选择一个给定表达式并对其求值。比如说,

(equal-chance
  (println "1")
  (println "2"))
(let [x 10] (eval '(println x)))
一半时间打印“1”,另一半时间打印“2”

我试着用

(defmacro equal-chance
  [& exprs]
    `(rand-nth '~exprs))
但这将返回一个引用的表单,而不是对其进行计算(即,它将返回
(println“1”)
,而不是实际打印“1”)。我不能使用
eval
,因为它不保留绑定。比如说,

(equal-chance
  (println "1")
  (println "2"))
(let [x 10] (eval '(println x)))
投诉无法解析符号x


是否有方法在本地范围内评估引用的表单?或者有更好的方法来解决这个问题?

只是不要引用对
rand nth
或表达式的调用。这将满足您的要求:

(defmacro equal-chance
  [& exprs]
    (rand-nth exprs))

不能在仅在编译时存在的词法环境中计算运行时值。解决方案是使用
fn
而不是
quote
,使用函数调用而不是
eval

(defmacro equal-chance [& exprs]
  `((rand-nth [~@(map (fn [e] `(fn [] ~e)) exprs)])))

其工作方式是将
(equal chance e1 e2…
扩展为
((rand nth[(fn[]e1)(fn[]e2)…])
,这非常有效!我自己永远也不会想到这一点,谢谢。我更喜欢使用delay/force而不是fn/call:
(force(rand nth[~@(map(partial list`delay)exprs)])
这并不适用于所有情况
(dotimes[i10](相等概率1,2,3))
将返回其中一个数字10次。