绑定数量未知的 Clojure 列表理解(可变 'for')
Clojure list comprehension where the number of bindings is not known (variadic 'for')
在 Clojure 中创建可变参数 'for' 的好方法是什么?
我写了这个:
(defmacro variadic-for
[f colls]
(let [bindings (map (fn [coll] [(gensym) coll]) colls)]
`(for ~(vec (apply concat bindings))
(~f ~@(map first bindings)))))
所以我可以这样使用:
(variadic-for + [[1] [2] [3 4]])
结果将是所有可能的总和,其中每个给定集合代表该绑定的可能值。
有更好的方法吗?除了 'for'.
之外,我不知道用于以这种方式创建所有排列的 Clojure 核心中的任何内容
我认为您的宏实现很棒,但将其作为函数实现具有增加可组合性的优势。例如,您可以将 variadic-for
传递给一个函数。这是 variadic-for
作为函数的实现:
(defn combine2 [A B]
(for [a A
b B]
(conj a b)))
(defn combinations [colls]
(reduce combine2 [[]] colls))
(defn variadic-for [f colls]
(map #(apply f %) (combinations colls)))
我相信某些库中已经有一个 combinations
函数,但您自己实现它很容易,就像上面所做的那样。
如果 variadic-for
是一个宏,您将无法执行以下操作:
(def combinatorial+ (partial variadic-for +))
(combinatorial+ [[1] [2] [3 4]])
;; => (6 7)
也许cartesian-product
from clojure.math.combinatorics
?
(defn variadic-for [f colls]
(map #(apply f %)
(apply clojure.math.combinatorics/cartesian-product colls)))
(variadic-for + [[1] [2] [3 4]])
=> (6 7)
在 Clojure 中创建可变参数 'for' 的好方法是什么?
我写了这个:
(defmacro variadic-for
[f colls]
(let [bindings (map (fn [coll] [(gensym) coll]) colls)]
`(for ~(vec (apply concat bindings))
(~f ~@(map first bindings)))))
所以我可以这样使用:
(variadic-for + [[1] [2] [3 4]])
结果将是所有可能的总和,其中每个给定集合代表该绑定的可能值。
有更好的方法吗?除了 'for'.
之外,我不知道用于以这种方式创建所有排列的 Clojure 核心中的任何内容我认为您的宏实现很棒,但将其作为函数实现具有增加可组合性的优势。例如,您可以将 variadic-for
传递给一个函数。这是 variadic-for
作为函数的实现:
(defn combine2 [A B]
(for [a A
b B]
(conj a b)))
(defn combinations [colls]
(reduce combine2 [[]] colls))
(defn variadic-for [f colls]
(map #(apply f %) (combinations colls)))
我相信某些库中已经有一个 combinations
函数,但您自己实现它很容易,就像上面所做的那样。
如果 variadic-for
是一个宏,您将无法执行以下操作:
(def combinatorial+ (partial variadic-for +))
(combinatorial+ [[1] [2] [3 4]])
;; => (6 7)
也许cartesian-product
from clojure.math.combinatorics
?
(defn variadic-for [f colls]
(map #(apply f %)
(apply clojure.math.combinatorics/cartesian-product colls)))
(variadic-for + [[1] [2] [3 4]])
=> (6 7)