请在 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
by

您可以使用仅命名空间键来增强代码库搜索的严谨性(但您必须进行适当的解析来搜索)。

与 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

您无法强制实施它(尽管我想可以用到 linter)。但我仍然会遵循这个指南,以避免您所讨论的特定情况。

如果采用 :keys-only,这同样无法强制实施。尽管如此,我 personally 还是喜欢这个想法,所以给你 一个赞。

by
我确实认为禁止 :as 是一个更简单的解决方案。因为目前有这么多形式的解构,你可能需要为每种形式提供一个 "only" 变体。

也许,相比于保留 :keys-only,更好地办法是采用 :as-only 或类似选项,也许叫 :into 更好,因为它可以适用于所有解构类型。
...