我正在尝试编写的线程宏有点麻烦。我发布了一个精简版,以显示我遇到了什么问题。
(defmacro <->
[v & fs]
`(do
(-> ~v ~@fs)
~v))
宏首先等同于线程 - &gt;宏,但不返回线程操作的结果,而是返回传递的原始值。
我遇到的麻烦就是当我这样做时:
(<-> 1
(<-> println)
(<-> println))
我希望输出为
1
1
=> 1
但由于宏在外面评估,宏扩展看起来像:
(do
(do
(println
(do
(println 1)
1))
(do
(println 1)
1)) 1)
,结果是
1
1
1
=> 1
我可以看到为什么会发生这种情况,因为宏是从外部进行评估的,但我不确定如何修复它以便宏实际上按预期工作(即在将其线程化到下一个表单之前评估值v)
答案 0 :(得分:3)
您的宏扩展为其v
参数被评估两次的形式。您只需要评估v
一次,let
- 绑定结果,以便稍后可以引用该值。
(defmacro <-> [v & fs]
(let [$v (gensym "$v_")]
`(let [~$v ~v]
(-> ~$v ~@fs)
~$v)))
请注意使用gensym
生成新的符号。