2012-02-11 36 views
6

来自Java背景,我非常喜欢静态类型安全性,并且不知道clojure程序员如何处理数据格式定义的问题(可能不只是类型,而是一般不变量,因为类型只是一个)clojure中的数据格式安全

这与“Clojure中的类型安全性”类似,但更关注如何在编译时检查类型的方面,而我更关注如何问题切实解决。

作为一个实际的例子,我正在考虑处理特定文档格式的编辑器应用程序。每个文档由多种不同类型的元素组成(图形元素,字体元素等)。不同的元素类型会有编辑器,当然也有函数用于将文档从其字节流转换为字节流,磁盘格式。

我感兴趣的基本问题是编辑器和读/写功能必须就通用数据格式达成一致。在Java中,我会将文档的数据建模为对象图,例如一个类代表一个文档,一个类代表每个元素。通过这种方式,我可以获得关于数据结构的编译时间保证,并且图形元素的字段“宽度”是整数而不是浮点数。它并不保证宽度是正数 - 但是使用getter/setter接口将允许相应的类添加这样的不变保证。

能够依赖于此可以使处理这些数据的代码变得更简单,并且格式违规可以在编译时或运行时早期(其中某些代码试图修改会违反不变量的数据)。

如何在Clojure中实现类似的“数据格式可靠性”?据我所知,没有办法执行编译时检查,隐藏域函数接口后面的域数据似乎不被认为是非惯用的(或者我误解了?),那么Clojure开发人员应该怎么做才能感到安全?数据的格式传递到它们的功能?如何让您的代码尽快出错,而不是在用户编辑了20多分钟并尝试保存到磁盘之后,保存功能注意到字体列表中存在由于编辑器错误?

请注意,我对Clojure和学习很感兴趣,但没有写出任何实际的软件,所以可能我只是感到困惑,答案很简单 - 如果是这样,对于浪费你的时间 :)。

回答

8

我没有看到任何错误或unidiomatic关于使用验证API来构建和操纵您的数据,如下所示。

(defn text-box [text height width] 
    {:pre [(string? text) (integer? height) (integer? width)]} 
    {:type 'text-box :text text :height height :width width}) 

(defn colorize [thing color] 
    {:pre [(valid-color? color)]} 
    (assoc thing :color color)) 

... (colorize (text-box "Hi!" 20 30) :green) ... 

此外,参考文献(VARS,参考文献,原子,药剂)可以具有相关联validator function可用于确保在任何时候都有效状态。

+0

感谢迄今为止的答案。由于这是一个相当开放的问题,我会在接受之前等一会儿。验证函数听起来像是一个有趣的解决方案,但是(保持这个例子),如果你有一个大文档作为你的状态,每次做一个小小的改变就完全验证它,这似乎是低效率的 - 在这样的模型中,我猜测使用验证操纵功能将是可取的。 – Medo42 2012-02-12 23:17:29

5

好问题 - 我还发现从静态类型语言转换为动态类型语言需要更多关心类型安全性。幸运的是,TDD技术在这里帮助了巨大的数量。

我通常会写一个“验证”函数来检查所有关于数据结构的假设。我也经常用Java来做这个,因为它不变的假设,但是在Clojure中它更重要,因为你需要检查类型以及类型。

然后,您可以用几种方式验证功能:

  • 截至REPL快速检查:(validate foo)
  • 在单元测试:(is (validate (new-foo-from-template a b c)))
  • 对于关键功能的运行时检查,例如检查(read-foo some-foo-input-stream)有效

如果你有一个复杂的数据结构,它是多个不同组件类型的树,你可以写为每个组件类型验证功能,并具有对整个文档调用验证的验证功能每个子组件递归地。一个很好的诀窍是使用协议或multimethods为每个组件类型生成验证函数多态。