Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure宏评估_Clojure_Macros_Eval - Fatal编程技术网

clojure宏评估

clojure宏评估,clojure,macros,eval,Clojure,Macros,Eval,由于对clojure及其宏的了解和熟悉,我给自己设定了一个任务,即编写一个宏,从诸如“abc”之类的字符列表中生成所有长度为“n”的字符串。因此,对于n=2,输出应为“aa”“ab”“ac”“ba”“bb”“bc”“ca”“cb”“cc”。我从以下函数作为模板开始: (定义mkstr[n v](表示[i v j v](str i j)))。在for binding中重复“v”,并创建多少个var作为“n”的函数;在这种特殊情况下:2 在阅读了“quote”“unquote”等相关内容后,在阅读了

由于对clojure及其宏的了解和熟悉,我给自己设定了一个任务,即编写一个宏,从诸如“abc”之类的字符列表中生成所有长度为“n”的字符串。因此,对于n=2,输出应为“aa”“ab”“ac”“ba”“bb”“bc”“ca”“cb”“cc”。我从以下函数作为模板开始: (定义mkstr[n v](表示[i v j v](str i j)))。在for binding中重复“v”,并创建多少个var作为“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#))))
现在,我的“真正”问题或缺乏理解是,为了获得输出,我必须这样做:
(eval(mkcoms len chars))。为什么只有使用“eval”才起作用?诚然,它是可用的,但感觉有些不对劲

您的宏返回一个带引号的表单,这就是为什么当您将它传递给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))))

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

谢谢您的回答。它消除了对宏编写的一些误解,但也展示了如何将常规函数代码与生成的代码混合使用,反之亦然。经过进一步的实验,我意识到auto gensym似乎是多么耗时。