【发布时间】:2017-08-25 13:55:21
【问题描述】:
我正在尝试使用引用将seq-exprs 传递给for,但我在下面的两次尝试都导致CompilerException java.lang.IllegalArgumentException: for requires a vector for its binding。我显然误解了引用和评估(以及相关概念)的工作原理。
(let [v ['b (range 2)]]
(for v b))
(let [v '[b (range 2)]]
(for v b))
正确的方法是什么?您将如何向初学者解释为什么上述实现都不起作用?谢谢!
编辑:
我知道我能做到
(let []
(for [b (range 2)] b))
我想要实现的是能够传递绑定向量(例如,另一个函数的输出)
编辑 2,动机/背景:
我正在构建一个转译器 [repo],我正在尝试翻译和展开一个 for 循环(包括嵌套循环,example),所以我认为我可以将要迭代的变量范围附加到seq-exprs同时通过嵌套循环更深入地遍历 AST(抽象语法树),然后评估每个原始块中包含的翻译关系(关系总是可以一个一个地翻译)给定由 clojure for 生成的“绑定”。如果有“更好”的方法,您有什么建议吗?
【问题讨论】:
-
最后你想要这样的东西:(for [i (0 1)])?你想达到什么目的?你可以像这样使用 for:(for [i (range 2)] (println "i is: " i)),也 for requires vector binding like this ->[
] -
这是一个最小的例子 - 我希望能够将向量
seq-exprs作为变量传递给for。 -
因为
for是一个宏,它在编译时扩展,这意味着绑定向量应该是一个文字向量,而不是一个 var,你想要做的事情是完全不可能的(编译器只是不知道v的运行时值)。您可以做的是使用另一个返回for宏的宏(它仍然无法对v的运行时值进行操作)或者您可以使用eval,这很糟糕。你为什么还要这样做? -
for产生一个序列。如果您总是要将参数向量传递给for,为什么不将for产生的序列传递给您希望使用它的任何东西?
标签: clojure