Clojure应用映射和关键字参数解构

13

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

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

如何最好地将map传递给函数,例如:

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

我目前想到的方法是通过vecflattenapply实现,例如:

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

我坚信有更好的方法来做这件事。你能否考虑一下呢?

3个回答

11

我也想不到更加优美的方法,不过我认为应该有一种方式(例如apply的特定于映射的变体)。

但是,除了不太优美之外,使用flatten还存在问题。如果您映射的值是集合,flatten也会对这些值进行递归处理,因此可能会完全混乱。这个替代方案避免了这个问题:

(apply make-widget (apply concat {:x 100}))

mapply函数是执行此操作的标准方式,非常见答案中描述了该函数。 - Paul Legato

8

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

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

这可以像应用程序一样使用

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

关于为什么Clojure核心缺乏特定语言功能的实现方式,没有人能够给我一个清晰的答案,这些功能可以更本地化和优雅地实现。
更新:在我花费大量时间使用Clojure进行编程之后,我个人倾向于不创建接受vararg {} 的函数。尽管一开始可能看起来很吸引人,但实际经验证明,显式传递{} 在许多方面始终更好。

1
万能的mapply已经被打包好了,可以在https://github.com/ToBeReplaced/mapply上找到。只需将[org.tobereplaced/mapply "1.0.0"]添加到您的project.clj依赖项中即可。 - Paul Legato

7

您可以使用:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接