编写 Clojure #[...] 向量函数宏

彼得鲁斯·塞隆

我想编写一个#[...]我可以使用的 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]]

但我不能说我推荐使用它。

  • 它不利于可读性。

  • 而不是抛出ArityExceptions,错过的参数将只是默认nil通过解构

  • 它最多只允许%5; 尽管这是一个可以增加的硬编码限制。使用当前的“var-arg 方法”,我不能允许任意数量的参数。试图在编译时实现无限列表显然会流泪。

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

你应该只使用

#(vector (inc %1) %2)

相反,或者按照评论中的建议

#(do [(inc %1) %2]) 

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章