Clojure宏返回两个或多个s表达式
Clojure中有没有一种方法可以编写一个宏(或使用现有宏)来返回两个或多个s表达式 例如。假设我正在尝试生成前10个正方形:Clojure宏返回两个或多个s表达式,clojure,Clojure,Clojure中有没有一种方法可以编写一个宏(或使用现有宏)来返回两个或多个s表达式 例如。假设我正在尝试生成前10个正方形: (map * (range 10) (range 10)) 现在我想尝试使用repeat,以便以后可以提供功率(目前为2)作为参数: (map * (repeat 2 (range 10))) 但是,上述操作不起作用,因为repeat返回具有两个范围(而不是两个范围)的单个s表达式 请不要提供“返回前10个方块”函数的替代实现。我对处理这种情况的惯用方法或普遍适用的
(map * (range 10) (range 10))
现在我想尝试使用repeat,以便以后可以提供功率(目前为2)作为参数:
(map * (repeat 2 (range 10)))
但是,上述操作不起作用,因为repeat返回具有两个范围(而不是两个范围)的单个s表达式
请不要提供“返回前10个方块”函数的替代实现。我对处理这种情况的惯用方法或普遍适用的变通方法感兴趣
我想我正在寻找一种方法来实现下面的爆炸:
(explode '( a b c )) ;; evals to a b c
(map * (explode (repeat 2 (range 10)))
单个宏无法执行此操作 宏是一个函数,它接受一个s表达式并将其转换为另一个s表达式。输入可以是表达式的任何序列(符号、灵长类、其他表达式等),输出是插入以代替原始宏调用的单个表达式 一般来说,宏必须围绕映射和转换整个表单的调用
(your-macro-here (map * (repeat 2 (range 10))))
如果您有两个宏,一个生成表达式,另一个包含整个外部形式,那么外部宏可能会找到包含宏结果的单个表达式,在您的示例中是两个范围,并将它们提升到一个级别,成为独立的表达式。我不建议在实践中这样做,它只是用来说明宏的功能 正如Arthur所说,宏不能完全满足您的需求。根据您希望对这些表单执行的操作,变通方法是可能的 如果您只是想计算宏生成的多个表单,例如简化样板代码,则可以将这些多个表单包装为
do
表单:
(defmacro defn-foos [& foos]
`(do ~@(map (fn [foo] `(defn ~foo [])) foos)))
(defn-foos my-fn-1 my-fn-2)
;; expands as:
;; (do (defn my-fn-1 [])
;; (defn my-fn-2 []))
如果您希望在函数调用中使用展开的表单作为位置参数,就像您所做的那样,那么您最好将它们包装在列表中,然后使用apply
将列表作为位置参数解压到函数中
要了解其工作原理,请注意原始问题中的第二个示例可以使用apply
进行简单修改:
(apply map * (repeat 2 (range 10)))
你的问题措辞有些混乱。如果您能提供一个您希望看到的语法示例,这将非常有用;目前,您使用的是map
和repeat
,它们在Clojure中已经有了特定的定义。@JohnJ请参阅我文章的更新部分