这种形式构建有什么问题?

时间:2012-09-16 20:53:29

标签: clojure

考虑有效的clojure形式:

    > (let [a 16 b 8] (/ a b))
2

我正在尝试手动构建它,以便将其提供给eval调用。我之前很快被拒绝了:

> (list 'let '[ 'a '16 'b '8 '] '(/ a b) )
RuntimeException Unmatched delimiter: ]  clojure.lang.Util.runtimeException (Util.java:156)
(/ a b)
RuntimeException Unmatched delimiter: )  clojure.lang.Util.runtimeException (Util.java:156)

引用数组字符[]是不够的。实际上,以下表达式(删除[和])是可以的:

> (list 'let  'a '16 'b '8  '(/ a b) )
(let a 16 b 8 (/ a b))

这个建筑有什么问题?我该如何解决这个问题呢?是否有引用[和]字符的特殊形式?

3 个答案:

答案 0 :(得分:5)

如果您正在尝试生成代码,那么我建议使用auto-gensyms构建此表达式,如下所示:

`(let [a# 16 b# 8] (/ a# b#))

自动gensyms(a#b#)创建保证唯一的符号名称。这并非严格必要,但在更复杂的情况下,它可以帮助避免意外捕获变量名称(例如,通过不同级别的宏扩展)。

注意在表达式的开头使用syntax-quote(`)而不是常规引用(')。在生成代码时,通常比常规引用更好,因为它会自动处理名称空间。

答案 1 :(得分:4)

您可以引用整个矢量:

(list 'let '[a 16 b 8] '(/ a b))

答案 2 :(得分:4)

您也可以引用整个列表。

main=> (def bar '(let [a 16 b 8] (/ a b)))
#'main/bar
main=> bar
(let [a 16 b 8] (/ a b))
main=> (eval bar)
2

或者这样......

main=> (def bar (quote (let [a 16 b 8] (/ a b))))
#'main/bar
main=> bar
(let [a 16 b 8] (/ a b))
main=> (eval bar)
2