fn,让内部clojure宏观
我遇到了Clojure宏的某些局限性。我不知道如何优化以下代码?
(defmacro ssplit-7-inefficient [x]
(let [t 7]
;; Duplicated computation here!
`(do [(first (split-with #(not (= '~t %)) '~x))
(drop 1 (second (split-with #(not (= '~t %)) '~x)))])))
(ssplit-7-inefficient (foo 7 bar baz))
;; Returns: [(foo) (bar baz)]
这是一些不起作用的方法:
(defmacro ssplit-7-fails [x]
(let [t 7]
`(do ((fn [[a b]] [a (drop 1 b)]) (split-with #(not (= '~t %)) '~x)))))
(ssplit-7-fails (foo 7 bar baz))
;; Error: Call to clojure.core/fn did not conform to spec.
(defmacro ssplit-7-fails-again [x]
(let [t 7]
`(do
(let [data (split-with #(not (= '~t %)) '~x)]
((fn [[a b]] [a (drop 1 b)]) data)))))
(ssplit-7-fails-again (foo 7 bar baz))
;; Error: Call to clojure.core/let did not conform to spec.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请注意,
split-with-with
仅分配一次。您可以使用某些破坏性来获得想要的东西:
在其他用例中, 也很有用:
Note that
split-with
splits only once. You can use some destructuring to get what you want:In other use cases,
partition-by
can be also useful:关于clojure中的宏的推理并不容易 - (在我的视图中,
acroexpand -1
与Common Lisp的Macroexpand -1
... )。我的方式是第一个建立助手功能的方法。
此功能使用破坏性,因此
split-with-with-with
是“有效的”。它几乎可以做到宏应该做的事情。只是那个必须引用
该论点 - 使其有效。
从这个步骤到宏并不困难。
宏插入助手函数的调用时,宏应自动引用参数。
这样我们就可以称呼:
使用此技巧,甚至将功能概括为:
宏体内的(辅助)功能的使用 - 甚至其他宏 - 或递归功能或递归宏 - 称为其他宏的宏 - 宏(称为其他宏)宏是。因为它表明在制定/定义宏时可以使用整个LISP。大多数语言的宏通常无法做的事情。
It is not so easy to reason about macros in Clojure - (in my view
macroexpand-1
alienates the code a lot - in contrast to Common Lisp'smacroexpand-1
...).My way was first to build a helper function.
This function uses destructuring so that the
split-with
is "efficient".It does nearly exactly what the macro should do. Just that one has to quote
the argument - so that it works.
From this step to the macro is not difficult.
The macro should just automatically quote the argument when inserting into the helper function's call.
So that we can call:
Using this trick, even generalize the function to:
The use of (helper) functions in the macro body - and even other macros - or recursive functions or recursive macros - macros which call other macros - shows how powerful lisp macros are. Because it shows that you can use the entirety of lisp when formulating/defining macros. Something what most language's macros usually aren't able to do.