分享您的想法,参加 2024 年 Clojure 状态调查!

欢迎!请参阅 关于 页面了解此功能的更多信息。

+1
Clojure

我们处理一个相当大的 Clojure 代码库,并多次遇到这个问题。

声明一下,我们的设计是“一切都是一个地图”,因此这已经困扰我们一段时间了,像下面的解决方案可能会引起争议

所以我们有 :keys, :strs 用于解构一个地图

(def my-func [{:keys [a b c] :as z}])

问题在于,对于调用者来说,很难知道函数最终从 z 地图中使用了哪些内容(人们总是可以使用 get 获取到解构之外的某些内容。更糟糕的是,my-func 最终会將 z 移交给其他地方,这使得在不查看 z 所在位置的情况下进行重构变得困难

而是像这样(名称目前不重要)

(def my-func [{:keys-only [a b c] :as z}])

它只从地图中提取了 a b c,并且 z 只包含 a b c 键,这意味着函数有强合同,规定了该函数需要什么。不再有重构挑战

4 个回答

+1

您可以使用命名空间键,以提高代码库搜索的严谨性(但您需要使用正确的解析进行搜索)。

与 select-keys 类似,移除键似乎是盲目使用的工具。

如果您的主要目标是控制所有围绕数据流动的事务,您可以考虑将数据处理置于像Prismatic Graph(或者叫Plumbing?)之类的监管之下。您需要的不是确切的Graph/Plumbing,但您明白了,可以自行创建适合的设施。为此困扰,您可以获得的不只是“执行”,还有诸如x未使用之类的有帮助的报告,或者自动处理步骤以生成可能的输出子集。

+1

仅仅移除:as z有用吗?没有东西可以解构。 ;)

这在某些情况下确实可以工作 :)
0 投票

您尝试使用spec了吗?

我当然已经检查了spec。我原本预期这会更像是语言构造而非库。此外,我对spec的研究还不够深入,因此不知道如何实现上述功能?我可以想到的一种方式是

     (def my-func [m] (let [m (s/conform :spec m)]))

有更好的方法吗?
–2 投票

我的规则是不允许使用:as

你无法强制执行(尽管我想检查器也可能)。但这是一个指南,我可以遵循以避免你提到的特定情况。

如果确实有:keys-only,这也不能真正强制执行。话虽如此,我个人喜欢这个想法,所以给了你一个赞。

但我确实认为禁止:as 是一个更简单的解决方案。因为解构有许多形式,你需要为它们所有的“仅”变异。

也许:keys-only 更好的方法是有:as-only 或类似的东西,也许最好叫:into。这样就会适用于所有解构类型。
...