【问题标题】:clojure macro evalclojure 宏评估
【发布时间】:2012-11-19 14:20:45
【问题描述】:

被 clojure 及其宏所吸引和陌生,我为自己设定了编写一个宏的任务,该宏从诸如“abc”之类的字符列表中生成所有长度为“n”的字符串。所以对于 n=2,输出应该是“aa”“ab”“ac”“ba”“bb”“bc”“ca”“cb”“cc”。我从以下函数作为模板开始: (defn mkstr [n v] (for [i v j v] (str i j)))。 for绑定中'v'的重复以及创建多少个变量应该是'n'的函数;在这种特定情况下:2.

在阅读了'quote' 'unquote' 等内容之后,然后按照关于宏的优秀在线教程,经过多次试验和错误以及一些简单的运气,我设法生成了以下函数和宏,无论'n' 的值。真正困难的部分是生成 'for' 绑定所需的可变数量的代码。

(defn mkvars [n] 
"Gives a list of 'n' unique symbols"
(let [vc (repeatedly n #(gensym ))] vc)) 

(defmacro mkcoms [n syms] 
"Generates a list of possible combinations of length 'n' from a string of symbols"
`(let [vs# (mkvars ~n) sy# ~syms  
    forarg# (vec (interleave vs# (repeat ~n sy#)))]
     `(for ~forarg# (str ~@vs#))))

现在我的“真正”问题或缺乏理解是,要获得输出,我必须这样做: (评估(mkcoms len 字符))。为什么这只能通过使用 'eval' 起作用?诚然,它可以按原样使用,但感觉有些不对劲。

【问题讨论】:

    标签: clojure macros eval


    【解决方案1】:

    您的宏正在返回一个带引号的形式,这就是当您将它传递给 eval 时它可以工作的原因。我不明白宏的目的是什么,所以我希望这个解释是你所追求的。

    宏应该生成它所代表的代码并返回它。您的宏会生成一个带引号的表单。如果您删除了反引号的外层,看起来其意图是成为执行扩展(宏)而不是结果代码的代码的一部分,那么您确实会在宏扩展时执行:

    (defmacro mkcoms [n syms]                                                                                                      
      "Generates a list of possible combinations of length 'n' from a string of symbols"                                           
      (let [vs     (mkvars n)                                                                                                      
            sy     syms                                                                                                            
            forarg (vec (interleave vs (repeat n sy)))]                                                                            
        `(for ~forarg (str ~@vs))))
    

    这听起来像是您所追求的,尽管我承认我不明白您为什么希望这发生在“编译时”和运行时。

    【讨论】:

    • 感谢您的回答。它消除了对宏编写的一些误解,但也展示了如何将常规函数代码与生成的代码混合,反之亦然。经过进一步的实验,我意识到自动生成符号似乎是多么耗时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 2015-04-01
    • 1970-01-01
    • 2011-07-12
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多