在 Clojure 中,表达式的结果可以作为 (def) 的第一个参数吗?
In Clojure, can the result of an expression be the first argument to a (def)?
我的最终目标是用宏生成这段代码,其中单词可以是任何字符串(没有白色 space):
=> (def word "word")
这就是我目前所拥有的。它编译,但不 运行.
=> (defmacro mirror [val] `(def (symbol val) val))
预期行为:
=> (mirror "michael")
=> (mirror "jackson")
=> michael
"michael"
=> jackson
"jackson"
实际行为:
=> (mirror "michael")
Syntax error compiling def at (/tmp/form-init2235651799765014686.clj:1:25).
First argument to def must be a Symbol
据我了解,(def)
需要一个 Symbol 作为第一个参数,(symbol val)
应该 return。我的猜测是编译器在评估它们之前正在检查 (def)
's arguments' 类型,因此它看到的不是符号而是表达式并抛出错误。
(defmacro mirror [val] `(def ~(symbol val) ~val))
如果希望val
是一个字符串文字,akond的解决方案就足够了。
如果你想使用字符串生成表达式,就像 amalloy 在他的评论中所做的那样,你可以这样写:
(defmacro mirror [exp] (let [val (eval exp)] `(def ~(symbol val) ~val)))
使用 amalloy 的例子我们有:
=> (def module-name "foo")
#'user/module-name
=> (mirror (str module-name "-test"))
#'user/foo-test
=> foo-test
"foo-test"
此宏计算表达式 "at compile-time"。这意味着您不能在其中使用局部变量(例如 (let [suffix "-test"] (mirror (str module-name suffix)))
失败)。要评估它 "at run-time" 你可以这样写:
(defmacro mirror [exp] `(let [~'val ~exp] (eval `(def ~(symbol ~'val) ~~'val))))
或者,您可以避免使用宏和 def
,而使用 intern
。
我的最终目标是用宏生成这段代码,其中单词可以是任何字符串(没有白色 space):
=> (def word "word")
这就是我目前所拥有的。它编译,但不 运行.
=> (defmacro mirror [val] `(def (symbol val) val))
预期行为:
=> (mirror "michael")
=> (mirror "jackson")
=> michael
"michael"
=> jackson
"jackson"
实际行为:
=> (mirror "michael")
Syntax error compiling def at (/tmp/form-init2235651799765014686.clj:1:25).
First argument to def must be a Symbol
据我了解,(def)
需要一个 Symbol 作为第一个参数,(symbol val)
应该 return。我的猜测是编译器在评估它们之前正在检查 (def)
's arguments' 类型,因此它看到的不是符号而是表达式并抛出错误。
(defmacro mirror [val] `(def ~(symbol val) ~val))
如果希望val
是一个字符串文字,akond的解决方案就足够了。
如果你想使用字符串生成表达式,就像 amalloy 在他的评论中所做的那样,你可以这样写:
(defmacro mirror [exp] (let [val (eval exp)] `(def ~(symbol val) ~val)))
使用 amalloy 的例子我们有:
=> (def module-name "foo")
#'user/module-name
=> (mirror (str module-name "-test"))
#'user/foo-test
=> foo-test
"foo-test"
此宏计算表达式 "at compile-time"。这意味着您不能在其中使用局部变量(例如 (let [suffix "-test"] (mirror (str module-name suffix)))
失败)。要评估它 "at run-time" 你可以这样写:
(defmacro mirror [exp] `(let [~'val ~exp] (eval `(def ~(symbol ~'val) ~~'val))))
或者,您可以避免使用宏和 def
,而使用 intern
。