另类Clojure线程宏

时间:2017-01-09 00:10:01

标签: clojure macros

我正在尝试编写的线程宏有点麻烦。我发布了一个精简版,以显示我遇到了什么问题。

(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)

1 个答案:

答案 0 :(得分:3)

您的宏扩展为其v参数被评估两次的形式。您只需要评估v一次,let - 绑定结果,以便稍后可以引用该值。

(defmacro <-> [v & fs]
  (let [$v (gensym "$v_")]
    `(let [~$v ~v]
       (-> ~$v ~@fs)
       ~$v)))

请注意使用gensym生成新的符号。