请在2024 Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面了解此功能的工作原理。

+5
提问于 Clojure

虽然存在assoc-in,但没有clojure.core/dissoc-in。
确实,可以用update-in和dissoc构建dissoc-in,但这同时也是对assoc-in的一种反驳。
当提供了assoc-in的捷径时,为了保持一致性,也应该提供dissoc-in的捷径。
实现方式与assoc-in类似。

已有16个回答

+1

评论由:alexmiller

我们必须考虑除了map以外的向量或关联数据结构。我也希望不使用标志,而是允许一次移除多个。

使用类似以下的方式

(update-in [{:foo 1}] [0] dissoc :foo)

我们将得到{{[{}]}},所以现有的方式确实会留下空集合。

我还查看了一些现有的dissoc-in实现,例如core.incubator、taoensso.encore、clj-http、medley、useful、plumbing等。大多数与单个key-path一起工作,并留下空集合——这些似乎主要来源于incubator版本。Encore版本通过将key path与要移除的最终leaf keys分离开来处理多个路径(变元)。Medley、useful和plumbing版本仅适用于map并且移除空map。

我想象不出我们会在core中创建特定于map的版本(since all the other -in functions are generic)并因此得出结论我们需要一个允许留下空集合的dissoc-in。考虑到这一点,我不太确定dissoc-in与update-in + dissoc相比是否有足够的价值值得添加到core中,尤其是在它存在于各种工具库中(很多情况下语义不同)。那么我们可能会破坏(或至少给)现有dissoc-in实现的用户带来不便。我将对此公开征求评论,但我想在这里拒绝这个增强功能。

+1

评论由:alexmiller

是的,尽管我认为在更新案例中,这些因素平衡的方式不同。在更新中,实现较少,并且它们与我们提议添加的内容相匹配。因此,它们为用核心功能替换现有功能创造了可能性。

我认为常见的实用工具库实现(flatland/useful/plumbing)实际上满足了一个不同的需求——仅在图上执行更新-in、dissoc和路径移除。所以,如果目标是覆盖常见的用法,那么我们只需要让它只在工作图上,并移除留下的空路径。然而,我认为这与其他的-in函数有些矛盾。我猜可能存在一个中间地带,可以进行路径删除,但同时使其在图之外生效——这既能满足实用库的需要,又能像其他的-in函数一样通用。如果你需要留下空集合,你可以现在所做的那样,使用 update-in + dissoc。

0 投票

由: jafingerhut 发布的评论

2012年9月13日的补丁文件 patch clj-1063-add-dissoc-in-patch-v2.txt 优于 2012年9月7日的 diff 文件 001-dissoc-in.diff。它修复了一个错误(在文档字符串中缺少最后的 "),并为新函数添加了一个测试案例。

0 投票

由: bronsa 发布的评论

感谢修复 Andy

0 投票

由: jafingerhut 发布的评论

这个建议的 dissoc-in 应该与 clojure.core.incubator 中的那个进行比较,我刚好遇到它。我看到它们看起来不同,但还没检查是否有任何行为上的差异。

https://github.com/clojure/core.incubator/blob/master/src/main/clojure/clojure/core/incubator.clj

0 投票
评论由: bronsa 发布

clojure.core.incubator 中的 dissoc-in 会递归地移除空图

user=> (clojure.core.incubator/dissoc-in {:a {:b {:c 1}}} [:a :b :c])
{}

而在这个补丁中的那个则不会(正如我预期的)

user=> (dissoc-in {:a {:b {:c 1}}} [:a :b :c])
{:a {:b {}}}
0 投票

由: stu 发布的评论

请在孵化器中完成这项工作。

0 投票

评论由:andrewhr做出

保留空路径是不是大家最期待的行为?我认为,既然 {{assoc-in}}/{{update-in}} 在过程中都会创建路径,这种行为看起来就像是真正的“双重”。

{{nil}} 搬弄可能会在处理某些问题时效果不佳,这些问题对 {{dissoc-in}} 的使用者来说可能会过于模糊不解?

0 投票

评论由:alexmiller

补丁中的测试太简单了。应该测试多级、记录、向量等。

0 投票
_评论由:[email protected]_

正在测试 "clj-1063-add-dissoc-in-patch-v2.txt"


(dissoc-in {} [:a :b :c])
=> {:a {:b nil}}


这种行为相当意外。虽然孵化器版本没有这个问题,但它确实会删除空映射。

我正在对这个补丁编写测试(以及可能的新 dissoc-in),但对于是否应该保留空路径或移除空路径这一点还不明确?我不介意哪种方式,尽管我更倾向于同意 Andrew Rosa 的看法,即保留它们更为对称。
0 投票

评论者:[email protected]

@alex,你想保留空路径还是移除它们?两种方式都可以接受,尽管我认为略倾向于保留。一旦我知道你想朝哪个方向走,我将为这个写测试。

0 投票

评论由:alexmiller

一个和另一个之间的权衡有哪些?

在使用 dissoc-in 代替物(update-in 包含 dissoc 等)的地方,人们期望什么样的行为?

0 投票
(_评论由:michalmarczyk_)

如果我们只想处理嵌套在映射中的映射…,我可能会更倾向于移除空子路径。

然而,如果我们想在途中承认向量,那么留下空路径可以明确语义。


(dissoc-in [{:foo 1}] [0 :foo])
;= [{}]


相比之下,移除空路径可能会引起一些问题,这些问题要么需要限制移除路径的行为仅对映射有效,要么在有向量嵌套为条目时抛出异常。这两种方法似乎都不理想。
0 投票

评论者:michalmarczyk

此外,我们可以在技术上接受一个标志来决定是否应移除空路径,并确保用户仅在没有任何向量的情况下传入{{true}}。但我不太喜欢这种方法,因为对我来说,更多参数的自然目的是为{{dissoc}}和{{dissoc-in}}的匹配变长语义提供附加路径(参阅CLJ-1771)。

0 投票

由: bronsa 发布的评论

同样,对于包含update的辩论也是如此。因为updatedissoc-in可以在几个实用库中找到,所以这应该表明人们并不愿意只是使用update-in + dissoc

当然,将其添加到核心函数将导致在使用某些库时出现警告(它不会破坏任何事情,与update相关的AOT错误已被解决),但我认为这并不是一个大问题;新版本的这些库很快就会发布,即使如此,警告也不会是世界末日。

...