Clojure 宏允许在没有 let 绑定的情况下编写代码
Clojure macro to allow writing code without let bindings
我正在尝试编写一个允许我执行以下操作的宏
(without-nesting
(:= x 1)
(:= y 2)
(:= z 3)
(db-call x y z)
(:= p 33)
(db-call x y z p))
变成
(let [x 1
y 2
z 3]
(db-call x y z)
(let [p 33]
(db-call x y z p)))
到目前为止,我的实现如下
(defn assignment?
[[s _]]
(= s ':=))
(defmacro without-nesting
[& body]
(let [[bindings xs] (split-with assignment? body)
[non-bindings remaining] (split-with (complement assignment?) xs)]
`(let [~@(mapcat rest bindings)]
~@non-bindings
~(when (seq remaining)
`(without-nesting ~@remaining)))))
当 remaining
为空时,我遇到了问题。在我当前的实现中,放置了一个 nil
以防止 non-bindings
中的最后一个表单变为 return 其值。我不知道如何处理递归宏。有人可以帮忙
更新:
所以我能够摆脱 nil 但我只想知道是否有更好的方法来处理这个问题
(defmacro without-nesting
[& body]
(let [[bindings xs] (split-with assignment? body)
[non-bindings remaining] (split-with (complement assignment?) xs)]
`(let [~@(mapcat rest bindings)]
~@non-bindings
~@(if (seq remaining)
[`(without-nesting ~@remaining)]
[]))))
这也是编写代码的好方法吗?或者你看到任何警告?对我来说,与嵌套 let
相比,它看起来更线性
我确实知道人们会如何滥用它。在let
的情况下,如果嵌套变得过多,则提示重构代码。这可能会隐藏
只需使用let
。它已经是递归的。要在您只关心副作用的地方合并函数调用,约定是绑定到下划线。
(let [x 1
y 2
z 3
_ (db-call x y z)
p 33
_ (db-call x y z p)])
我正在尝试编写一个允许我执行以下操作的宏
(without-nesting
(:= x 1)
(:= y 2)
(:= z 3)
(db-call x y z)
(:= p 33)
(db-call x y z p))
变成
(let [x 1
y 2
z 3]
(db-call x y z)
(let [p 33]
(db-call x y z p)))
到目前为止,我的实现如下
(defn assignment?
[[s _]]
(= s ':=))
(defmacro without-nesting
[& body]
(let [[bindings xs] (split-with assignment? body)
[non-bindings remaining] (split-with (complement assignment?) xs)]
`(let [~@(mapcat rest bindings)]
~@non-bindings
~(when (seq remaining)
`(without-nesting ~@remaining)))))
当 remaining
为空时,我遇到了问题。在我当前的实现中,放置了一个 nil
以防止 non-bindings
中的最后一个表单变为 return 其值。我不知道如何处理递归宏。有人可以帮忙
更新:
所以我能够摆脱 nil 但我只想知道是否有更好的方法来处理这个问题
(defmacro without-nesting
[& body]
(let [[bindings xs] (split-with assignment? body)
[non-bindings remaining] (split-with (complement assignment?) xs)]
`(let [~@(mapcat rest bindings)]
~@non-bindings
~@(if (seq remaining)
[`(without-nesting ~@remaining)]
[]))))
这也是编写代码的好方法吗?或者你看到任何警告?对我来说,与嵌套 let
我确实知道人们会如何滥用它。在let
的情况下,如果嵌套变得过多,则提示重构代码。这可能会隐藏
只需使用let
。它已经是递归的。要在您只关心副作用的地方合并函数调用,约定是绑定到下划线。
(let [x 1
y 2
z 3
_ (db-call x y z)
p 33
_ (db-call x y z p)])