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)之类的监督之下。您需要的并不是确切的图/管道,但您已经明白了这个想法,可以创建自己的设施以适应需要。作为麻烦的回报,您不仅可以获得“执行”,还可以获得实用报告,例如告知某个数据未使用,或自动排队处理步骤以生成可能的输出子集。

+1

仅仅删除:as z是否可行?无法解构你不拥有的东西。 ;)

这当然在少数情况下是可行的 :)
0

您尝试使用spec了吗?

我确实检查了spec。我原本期望它更像是语言结构而不是库。另外,我没有深入研究spec,所以不清楚上述方法如何实现?我能想到的一种方法是

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

有更好的方法吗?
–2

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

虽然你无法强制实施(尽管我认为代码检查器可以做到),但这是一种指导原则,我可以用来避免你提到的具体情况。

如果你有:keys-only,它也难以实施。尽管如此,我个人喜欢这个想法,所以给你点个赞。

尽管这样,我认为禁止:as是一个更简单的解决方案。因为有太多形式的解构,你将需要为所有它们提供一个"only"变体。

也许用:as-only或类似的东西代替:keys-only是一个更好的方法,也许最好叫做:into。因为这将适用于所有解构类型。
...