考虑有效的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))
这个建筑有什么问题?我该如何解决这个问题呢?是否有引用[和]字符的特殊形式?
答案 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