Val*_*nck 6 macros clojure destructuring
我正在尝试编写一个宏,它通过解构扩展为let形式.我的问题是我希望得到let表单中定义的符号列表,包括通过destruturing获得的符号.
用例
我试图将这种行为分解出来,例如验证:
(let [a (foo bar)
{x :x,
y :y,
{u :u, v: v :as nested-map} :nested} some-map]
(and x y nested-map u v ; testing truthiness
(valid-a? a)
(valid-x? x)
(valid-y? y)
(valid-nested? nested-map)
(valid-u-and-v? u v)
))
Run Code Online (Sandbox Code Playgroud)
提出的解决方案
通过某种类型的and-let
宏来实现这一点真的很好,我可以像这样调用它:
(and-let [a (foo bar)
{x :x,
y :y,
{u :u, v: v :as nested-map} :nested} some-map]
(valid-a? a)
(valid-x? x)
(valid-nested? nested-map)
(valid-u-and-v? u v))
Run Code Online (Sandbox Code Playgroud)
我错过了什么
但是我错过了一些访问let表单中绑定的符号列表的方法.如果我有类似list-bound-symbols
函数的东西,我可以这样做:
(defmacro and-let
"Expands to an AND close that previouly checks that the values declared in bindings are truthy, followed by the tests."
[bindings & tests]
(let [bound-symbols (list-bound-symbols bindings) ;; what I'm missing
]
`(let ~bindings
(and
~@bound-symbols
~@tests)
)))
Run Code Online (Sandbox Code Playgroud)
有谁知道我怎么可能这样做?
解构由clojure.core/destructure
函数处理.它是公开的,所以我们可以自己调用它并提取所有本地的名称,包括那些命名用于解构的中间结果:
(defmacro and-let [bindings & tests]
(let [destructured (destructure bindings)]
`(let ~destructured
(and ~@(take-nth 2 destructured)
~@tests))))
Run Code Online (Sandbox Code Playgroud)
似乎工作:
(let [foo nil]
(and-let [a 1
[b c] [2 3]]
(nil? foo)))
;= true
Run Code Online (Sandbox Code Playgroud)