【发布时间】:2019-11-14 00:48:55
【问题描述】:
我经常想用所有键构建映射,但不希望键在其值为 nil 时显示。所以:
(building-map :a 1 :b nil :c 3 :d nil :e 5)
会产生 {:a 1 :c 3 :e 5}。 (显然我事先并不知道这些值,但为了演示的目的对其进行硬编码很方便。)我决定构建我自己的忽略 nils 的 assoc 类型函数,称为“asif”:
(defn asif [m & kvs]
(if (empty? kvs)
m
(if (second kvs)
(recur (assoc m (first kvs) (second kvs)) (drop 2 kvs))
(recur m (drop 2 kvs)))))
(我从查看 assoc 开始,所以我知道这是他们所谓的“幼稚”实现。但现在用它运行。)现在,当然,因为我很贪婪,我希望它递归地工作:
(asif {} :a 1 :b 2 :c 3 :d nil :e {:sub1 1 :sub2 nil :a 1})
这应该返回 {:a 1 :b 2 :c 3 :e {:sub1 1 :a 1}}。但它当然不会,因为它只是将“e”上的地图视为单个值。
我目前的解决方案是这样做:
(asif {} :a 1 :b 2 :c 3 :d nil :e (asif {} :sub1 1 :sub2 nil :a 1))
这行得通,而且很好,但是这种“我已经用 & 收集了 parms”的情况现在想递归它们,但我不能,这一直让我感到烦恼。我知道我可以:
- 传入整个地图而不是使用 & 开始。
- 编写宏
但是有没有办法使用 & 来做到这一点? (我在其他方法中使用了“应用”。)或者当你用 & 收集参数时,骰子已经投下?
更新:澄清一下,这并不是真的要删除 nil——不是要使用剩余参数(因此是主题标题)。这只是我定期遇到的一个问题,并且(在这个特定的例子中)我今天在思考“我可以使用 [& rest] 来编写一个递归地忽略 nil 值的 assoc 模拟”时碰巧再次遇到它?
【问题讨论】:
-
您是否考虑过一种方法,即使用常规函数构建地图,然后使用递归修剪具有 nil 值的地图条目的函数?
-
是的,那是我的第一个要点“通过整个地图”。我所拥有的一切都很好。我更感兴趣的是 & 是否真的可以在这里投入使用。
标签: clojure