2012-01-13 21 views
1

嗨,大家好:在java中,我们都有使用我们的ide来遍历复杂数据类型深度的经验:Clojure:地图列表地图...如何讨论任何数据结构

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

但是,在Clojure中,由于缺少静态类型,这变得不重要。我们如何“抵抗”或者对抗可能来自嵌套数据结构的复杂事物的Clojure?

1)对clojure数据结构的深度有一个可取的“限制”?

2),用于处理abritrarily深度嵌套的数据结构的一个常见成语,这防止 错误,例如误的列表在地图,或无法正确下部/上部外壳一个变量名?

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

回答

5

关键字是你的朋友在这里

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

尝试坚持与地图,因为他们更内在自我描述。
然后用螺纹先玩和.. macroes

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

,走的事实,关键字也是看起来他们的自我起来的地图功能的优势。

当您在带有代码完成的IDE中工作时,它将解析代码,然后构建有关该代码的数据,然后解析该数据以生成其建议。如果你的数据是自我声明的(它可以是'读'),那么即使没有IDE,你也可以得到这个数据。

PS:这导致约“代码数据”已经被人过多次表示更聪明,比我:)

2

测试在REPL你功能的正确性是一个良好的开端标准咆哮。一个改进的好方法是单元测试,也许可以使用前置和后置条件(http://objectcommando.com/blog/2010/03/07/design-by-contract-with-clojure/)。

使用关键字时,您的示例可以变成(get-in dog [:collar :tag :name])。和“修改”assoc-inupdate-in

+0

好的答案,最近我在一个项目上做了同样的工作。 REPEL节省时间,进入,更新,关联对于嵌套地图非常有用,解构和多方法可以消除混乱,并有助于专注于处理数据的逻辑。对于验证,我已经使用closchema https://github.com/jestan/closchema,它大部分时间都在工作:) – 2012-01-16 15:50:24

1

链式获得者往往违反了Law of Demeter。在这样做时,您将代码耦合到整个数据结构,这可能会非常棘手和复杂。在函数式语言中,clojure更自然地使用递归和序列处理来保持简单和习惯。所以:

  1. 告诉,别问。而不是要求“狗的领子的标签的名称......”尝试询问狗对象或高级功能来做你想做的事。
  2. 正如ponzao所说,测试,测试和测试。在REPL测试浏览您的选项,写小单元测试为
+0

我从来没有听说过德米特法律适用于函数式语言或数据结构。 – 2012-01-14 18:48:27

+0

@DavidJacobs Demeter的*法则可以被理解为“更喜欢更高层次的抽象概念”。*告诉别问*仅仅是面向对象的说法:“不要依赖表示;依赖于协议“。它们都适用于FP和OOP。例如,考虑一个总结列表元素的函数。你可以通过模式匹配列表的头部和尾部来编写它,但最好不要关心具体的类型,而应该使用'reduce'。突然你的功能在所有的集合上工作,并且当你的程序切换到其他数据结构时不会中断。 – 2012-01-16 10:29:35

0

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

你不能。这是这种语言的失败之一。如果你想静态输入,那么clojure不是你的东西。很多人会推荐使用嵌套地图,这些地图很慢,根本不提供安全性,也不是数据类型。地图是一种数据类型,嵌套地图不是,它们是假装的对象。就像javascript一样,clojure要求程序员跟踪各种数据的实际内容,因为Clojure中的数据是由5种不同的数据结构组成的,而不是数据结构本身。

1

在这方面,我发现了一个很棒的图书馆,它是制作棱镜的人的Schema library。它提供了一种为嵌套数据结构添加可选键入的方法,例如您在问题中引用的数据结构。这可以在运行时(或仅在测试时)执行,以验证对函数的输入。另外,它也是一个很好的文档,描述了函数对其输入的假设(这不是小事)。