1

大家好:在 java 中,我们都有过使用我们的 ide 来“遍历”复杂数据类型深处的经验:

dog.getCollar().getCollarTag().getName(); 

但是,在 Clojure 中,由于缺少静态类型,这变得非常重要。我们如何“防御”或 Clojure 对抗可能来自嵌套数据结构的复杂元素?

1) 对 clojure 数据结构深度的建议“限制”?

2) 处理深度嵌套的数据结构的常用习语,它可以防止错误,例如将列表误认为映射,或未能正确地小写/大写变量名?

如果我在这里听起来有点偏离范式,请原谅我......通过在 REPL 中不断测试,可能会有效地遏制此类错误。但是,我想知道是否有任何其他方法可以确保,在编译时,该代码尽可能正确(即单元测试、IDE / emacs 插件等...)

4

5 回答 5

6

关键字是你的朋友

(def my-animals  { :dog {:collar {:tag {:name "fido"}}}})

尽量坚持使用地图,因为它们本质上是自我描述的。
然后先玩线程和..

(-> my-animals :dog :collar :tag :name)

并利用关键字也是在地图中自行查找它们的功能这一事实。

当您在具有代码完成功能的 IDE 中工作时,它会解析代码,然后构建有关该代码的数据,然后解析该数据以产生建议。如果您的数据是自我声明的(可以“读取”),那么即使没有 IDE,您也可以得到它。

ps:这导致“代码就是数据”的标准咆哮已经被比我聪明得多的人表达了很多次:)

于 2012-01-13T23:57:37.603 回答
3

在 REPL 中测试函数的正确性是一个好的开始。改进它的一个好方法是单元测试,也许还可以使用前置条件和后置条件(http://objectcommando.com/blog/2010/03/07/design-by-contract-with-clojure/)。

使用关键字时,您的示例可以变成(get-in dog [:collar :tag :name]). assoc-in以及用or进行的“修改” update-in

于 2012-01-14T11:58:43.217 回答
2

有一个很棒的库,我觉得在这方面真的很有帮助,它是来自制作 Prismatic 的人的Schema 库。它提供了一种为嵌套数据结构(例如您在问题中引用的数据结构)添加可选类型的方法。这可以在运行时(或仅在测试时)强制执行,以验证函数的输入。此外,它还可以作为很好的文档,描述函数对其输入的假设(这可不是小事)。

于 2013-09-29T18:29:51.887 回答
1

How do we "defend" or Clojure against complexites that might arrive from nested data structures?

你不能。这是这种语言的缺点之一。如果你想要静态类型,那么 clojure 不是你的事。很多人会推荐使用嵌套映射,它们速度慢、根本不提供安全性并且不是数据类型。Map 是一种数据类型,嵌套映射不是,它们是假装的对象。与 javascript 非常相似,clojure 要求程序员跟踪各种数据的实际内容,因为 Clojure 中的数据是由 5 种不同的数据结构组合而成,而不是数据结构本身。

于 2012-01-15T21:21:46.127 回答
1

链式吸气剂通常违反得墨忒耳法则。在这样做时,您将代码耦合到整个数据结构,这可能是棘手和复杂的。在函数式语言中,clojure 感觉更自然地使用递归和序列处理来保持简单和惯用。所以:

  1. 告诉,不要问。而不是询问“狗项圈标签的名称......”尝试询问狗对象或高级函数来执行您想要的操作。
  2. 正如 ponzao 所说,测试、测试和测试。在 repl 上进行测试以探索您的选择并编写小型单元测试作为
于 2012-01-14T15:58:33.590 回答