编写一个clojure#[..]向量函数宏



我想编写一个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,而错过的参数只会通过破坏

  • 默认为nil
  • 它仅允许到%5;尽管这是一个可以增加的硬编码极限。使用当前的" var-arg方法",我不能允许任意数量的参数。试图在编译时间实现无限清单显然会流泪。

作为概念证明,它显示了您所追求的是几乎可能。

您应该只使用

#(vector (inc %1) %2)

,或者如评论中的建议

所建议
#(do [(inc %1) %2]) 

最新更新