【问题标题】:How to pass all key value pairs of a hashmap into a function (without passing the whole hashmap)?如何将哈希图的所有键值对传递给函数(不传递整个哈希图)?
【发布时间】:2021-04-28 13:01:04
【问题描述】:

我想将 hashmap 的所有 key-val 对传递给一个函数,而不是整个 hashmap。

所以我有一个我无法更改的函数,看起来像这样:

(defn foo [a b c & {:keys [x y z]}]
  (println x y z))

我有一个哈希图,其中包含可变数量的键和值。假设一个实例是:

(def bar {:d 1
          :e 2
          :x "x"
          :y "y"})

如何在不传递整个哈希图的情况下将所有键值对传入 foo? 我想做

(foo "a" "b" "c" 
     :d 1
     :e 2
     :x "x"
     :y "y")

【问题讨论】:

  • 我认为最后一个代码块有错字,我认为应该是(foo "a" "b" "c" :x "x" :y "y")
  • 你可以用concat构造一个参数序列,然后apply你的函数foo给它:(apply foo (apply concat "a" "b" "c" bar))
  • @A.Webb 天哪,这行得通!太棒了,谢谢!
  • @SteffanWestcott 否定。 foo 中的 & {:keys [x y z]} 应该忽略 :d 和 :e。我只是想展示我将使用的地图的可变性,但感谢您的检查!
  • 这是最近添加到 clojure.core 的内容,看起来很相关:clojure.org/news/2021/03/18/apis-serving-people-and-programs

标签: clojure hashmap


【解决方案1】:

select-keys 可用于将映射修剪到所需的键:

(apply foo "a" "b" "c" (apply concat (select-keys bar [:x :y :z])))

或者,一个厚颜无耻的解决方法是使用 Clojure 1.11.0-alpha1 或更高版本的 supports keyword arguments to be passed as maps。有了这个,你可以简单地做:

(foo "a" "b" "c" bar)

【讨论】:

  • (apply concat (select-keys bar [:x :y :z])) 也可以是(mapcat #(find bar %) [:x :y :z])
【解决方案2】:

如果 foo 是您“继承”的东西,那么一种方法是:

(apply foo "a" "b" "c" (into [] cat bar))

这“扁平化”键值并应用调用。

如果您只想传递所需的内容,您可以使用select-keys on bar先。

如果foo 是您自己编写的,请重新考虑。这个 乍一看,这种图案很适合人类消费,但它变得 很难通过地图。所以我的建议是:只允许 作为第四个参数传递的映射。如果那里的地图是可选的, 提供另一个 foo 的 arity 版本,它传递一个空映射。

【讨论】:

  • 不幸的是 foo 不是我写的,为了向后兼容需要保持这样。传入地图会是更好的设计!哦,好吧。
猜你喜欢
  • 2017-07-22
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
  • 2023-03-28
  • 2013-09-04
  • 1970-01-01
  • 2016-08-13
  • 2012-10-07
相关资源
最近更新 更多