Macros clojure宏有问题吗

Macros clojure宏有问题吗,macros,clojure,Macros,Clojure,我正在尝试编写一个宏,可以用来在新线程上调用函数,并在运行函数后打印函数名和线程名 到目前为止,我得到的是: (defmacro start-threads [f] '(let [t (Thread. 'f)] (prn (str "running " 'f " on: " (.getName t))))) 当我跑步时: (start-threads funcname) 输出:“在线程47上运行f”。我希望它能输出:“正在运行函数名:

我正在尝试编写一个宏,可以用来在新线程上调用函数,并在运行函数后打印函数名和线程名

到目前为止,我得到的是:

     (defmacro start-threads [f]
        '(let [t (Thread. 'f)]
            (prn (str "running " 'f " on: " (.getName t)))))
当我跑步时:

    (start-threads funcname)

输出:“在线程47上运行f”。我希望它能输出:“正在运行函数名:Thread-47。当我尝试取消引用它时,它尝试对函数求值。我知道我没有运行。从这里的线程开始,但我应该能够在后面添加它。我确信这里并不完全需要宏,我只是出于好奇才开始思考clojure中的宏是如何工作的。

基本上,您需要的是语法引号,而不是普通引号

(defmacro start-threads [f]
  `(let [t# (Thread. ~f)]
    (prn (str "running " '~f " on: " (.getName t#)))))
~f
在语法引号中插入
f
的值,
'~f
引用该值,
t#
生成自动gensym,因此变量名不会与任何周围名称冲突

但正如您正确地注意到的,您真的不需要宏来实现这一点。它很容易成为一种功能:

(defn start-threads [f]
  (let [t (Thread. f)]
    (prn (str "running " f " on: " (.getName t)))))

基本上,您需要的是语法引号,而不是普通引号

(defmacro start-threads [f]
  `(let [t# (Thread. ~f)]
    (prn (str "running " '~f " on: " (.getName t#)))))
~f
在语法引号中插入
f
的值,
'~f
引用该值,
t#
生成自动gensym,因此变量名不会与任何周围名称冲突

但正如您正确地注意到的,您真的不需要宏来实现这一点。它很容易成为一种功能:

(defn start-threads [f]
  (let [t (Thread. f)]
    (prn (str "running " f " on: " (.getName t)))))

谢谢,这肯定很有帮助。我想我想做的一件事是不要得到函数的字符串表示,它看起来像data_staging.main$write_thread@52a731cb,我想要输入的实际文本作为宏的参数。所以(开始线程写入线程)将输出“running write thread on:thread-47”。“显然没什么大不了的,我只是好奇这是怎么做到的。”SeanGeoffreyPietz:啊,我明白了。好的,我已经更改了代码,使其可以这样工作。唯一的区别是您只需要引用第二个
~f
。这需要一个宏来完成,因为参数将在传递给函数执行之前进行计算。谢谢,这绝对是有帮助的。我想我想做的一件事是不要得到函数的字符串表示,它看起来像data_staging.main$write_thread@52a731cb,我想要输入的实际文本作为宏的参数。所以(开始线程写入线程)将输出“running write thread on:thread-47”。“显然没什么大不了的,我只是好奇这是怎么做到的。”SeanGeoffreyPietz:啊,我明白了。好的,我已经更改了代码,使其可以这样工作。唯一的区别是您只需要引用第二个
~f
。这需要一个宏来完成,因为参数将在传递给函数执行之前进行计算。