简体   繁体   English

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

[英]Writing a Clojure #[…] Vector Function Macro

I want to write a Clojure vector macro form #[...] I can use like #[(inc %1) %2] that is equivalent to (fn [ab] [(inc a) b]) or #(vector (inc %1) %2) . 我想写一个Clojure向量宏格式#[...]我可以像#[(inc %1) %2]这样使用,它等效于(fn [ab] [(inc a) b])#(vector (inc %1) %2)

Is this a special data reader, or can this be written with defmacro ? 这是特殊的数据读取器,还是可以用defmacro编写?

Just for a laugh, I wrote up what is probably the closest you're going to come to a solution. 只是为了开怀大笑,我写下了可能最接近您的解决方案。 It doesn't define a reader macro, but it does define a macro that almost allows for the syntax you're looking for. 它没有定义阅读器宏,但确实定义了几乎允许您要查找的语法的宏。

I had to reinvent the wheel a bit to allow for % style implicit parameters since I couldn't get abusing #() to work: 我不得不重新发明轮子以允许%样式隐式参数,因为我无法滥用#()来工作:

(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)))

This defines a regular macro that mimics the #() reader macro. 这定义了模仿#()阅读器宏的常规宏。 It evaluates to a variadic function that has the first 5 arguments in the list bound to "percentage" symbols. 它求值是一个可变参数函数,该函数的列表中的前5个参数绑定到“百分比”符号。 It allows for % style parameters: 它允许%样式参数:

(mapv (lambda (* % %2)) [1 2 3] [1 5 9])
[1 10 27]

Then, you can just use that to define a macro that almost does what you're looking for: 然后,您可以使用它来定义几乎可以完成您要查找的宏:

(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]]

But I can't say that I recommend its use. 但是我不能说我建议使用它。

  • It doesn't lend itself to readability. 它不适合阅读。

  • Instead of throwing ArityException s, the missed arguments will just default to nil via destructuring 不会抛出ArityException ,而是通过解构将错过的参数默认为nil

  • It only allows up to %5 ; 它最多只允许%5 ; although that's a hard-coded limit that can be increased. 尽管这是可以增加的硬编码限制。 Using the current "var-arg method", I can't allow for an arbitrary number of parameters. 使用当前的“ var-arg方法”,我不允许使用任意数量的参数。 Trying to realize an infinite list at compile time will obviously end in tears. 试图在编译时实现一个无限列表显然会落泪。

As a proof of concept though, it shows what you're after is almost possible. 不过,作为概念证明,它表明您追求的目标几乎是可能的。

You should just use 你应该用

#(vector (inc %1) %2)

instead, or, as suggested in the comments 相反,或者按照评论中的建议

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM