我想编写一个#[...]
我可以使用的 Clojure 矢量宏形式#[(inc %1) %2]
,它相当于(fn [a b] [(inc a) b])
or #(vector (inc %1) %2)
。
这是一个特殊的数据读取器,还是可以用defmacro
?
只是为了一笑,我写了可能是您最接近解决方案的方法。它没有定义 reader 宏,但它定义了一个几乎允许你正在寻找的语法的宏。
我不得不重新发明轮子以允许%
样式隐式参数,因为我无法滥用#()
:
(defn arg-list
"Returns a lazy-seq of (%, %2, %3, ...) strings."
([] (arg-list 1))
([n] (lazy-seq
(cons (str "%" (if (> n 1) n))
(arg-list (inc n))))))
(defmacro lambda
"Use as you would #(). (map (lambda (* % 2)) [1, 2, 3])"
[& body]
(let [arg-syms (->> (arg-list) (take 5) (mapv symbol))]
`(fn [& ~arg-syms]
~@body)))
这定义了一个模仿#()
阅读器宏的常规宏。它的计算结果是一个可变参数函数,该函数将列表中的前 5 个参数绑定到“百分比”符号。它允许%
样式参数:
(mapv (lambda (* % %2)) [1 2 3] [1 5 9])
[1 10 27]
然后,您可以使用它来定义一个几乎可以满足您要求的宏:
(defmacro vec-f [& elems]
`(lambda (vec ~(vec elems))))
(mapv (vec-f (inc %) %2) [1 2 3] [1 5 9])
[[2 1] [3 5] [4 9]]
但我不能说我推荐使用它。
它不利于可读性。
而不是抛出ArityException
s,错过的参数将只是默认nil
通过解构
它最多只允许%5
; 尽管这是一个可以增加的硬编码限制。使用当前的“var-arg 方法”,我不能允许任意数量的参数。试图在编译时实现无限列表显然会流泪。
不过,作为概念证明,它显示了您所追求的几乎是可能的。
你应该只使用
#(vector (inc %1) %2)
相反,或者按照评论中的建议
#(do [(inc %1) %2])
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句