13

考虑一个具有以下签名的函数:

(defn make-widget [& {:keys [x y] :or {x 10 y 20}}]
 ...)

将映射传递给函数的最佳方法是什么,例如:

(make-widget {:x 100})

或者

(make-widget {:y 200 :x 0})

我目前想到的是 via ,vec例如:flattenapply

(apply make-widget (flatten (vec ({:x 100}))

我坚信有更好的方法来做到这一点。你能考虑一个吗?

4

3 回答 3

11

我也想不出更优雅的方式,尽管在我看来应该有一个(比如 的特定于地图的变体apply)。

但是,使用flatten除了不是很优雅之外还有其他问题。如果您的地图的值是集合,flatten那么它们也会递归地工作,所以事情可能会完全混淆。这个替代方案避免了这个问题:

(apply make-widget (apply concat {:x 100}))
于 2013-10-15T07:37:49.913 回答
8

还有一个已知的(至少不是我发明的)功能“mapply”:

(defn mapply [f & args] (apply f (apply concat (butlast args) (last args))))

可以像这样应用

(mapply your-function {:your "map"})

至于为什么 Clojure 核心中缺少这种特定于语言的功能,并且实现得更加原生和优雅,没有人能给我一个明确的答案。

更新

在我花了很多时间在 Clojure 编程之后,我个人倾向于避免创建接受 a{}作为可变参数的函数。虽然起初这看起来很吸引人,但实际上经验证明,{}由于许多原因,通过显式传递总是更好。

于 2013-10-17T14:49:10.330 回答
7

您可以使用:

(apply make-widget (mapcat identity {:x 200 :y 0}))
于 2013-10-15T08:36:26.003 回答