我想编写一个clojure vector宏观表单 #[...]
我可以像 #[(inc %1) %2]
一样使用,等效于 (fn [a b] [(inc a) b])
或 #(vector (inc %1) %2)
。
这是一个特殊的数据读取器,还是可以用defmacro
?
只是为了笑,我写了您可能最接近解决方案的是什么。它没有定义读取器的宏,但确实定义了一个宏,几乎允许您要寻找的语法。
我不得不重新发明轮子以允许%
样式隐式参数,因为我无法滥用#()
的工作:
(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,而错过的参数只会通过破坏
默认为它仅允许到
%5
;尽管这是一个可以增加的硬编码极限。使用当前的" var-arg方法",我不能允许任意数量的参数。试图在编译时间实现无限清单显然会流泪。
nil
作为概念证明,它显示了您所追求的是几乎可能。
您应该只使用
#(vector (inc %1) %2)
,或者如评论中的建议
所建议#(do [(inc %1) %2])