Core.typed 向动态类型 Clojure 中添加了一个可选的类型系统。它的目标是做到两全其美:即具有 Clojure 的简洁性和灵活性又能获得类型检查语言所具有的安全保证。因为这个类型系统是可选的,所以你可以在它能够提供最大价值的地方逐步地使用它。 core.typed 的用户手册中提到:
如果给类型加上合适的文档说明,那么它就是一个非常好的机器可检查的文档。它们永远都不会过时并且通常是非常重要的,因为它能够快速地提醒用户函数的功能。
在程序发展的时候类型化是有用的,特别是有多个贡献者的时候。如果一个贡献通过了类型系统,我们就知道它是类型正确的(类型错误几乎是最常见的用户编程错误)。
Core.typed 能够通过类型推理功能自动地为你指出很多类型,var 变量、函数参数和一些宏需要显式的类型注解,你还能够注解协议和数据类型。例如,一个求和函数的注解可能是这样的:
(ann add [Number Number -> Number]) (defn add [a b] (+ a b))
因为类型声明和实现是分离的,所以你能够很容易地向第三方代码中添加类型注解,就像 clojure.core 这里所实现的那样。
core.typed 的作者 Ambrose Bonnaire-Sergeant 说,当前的0.2 版本已经做好了产品化的准备,这意味着它“能够找到真实代码中的bug,并且不会让你已有的代码慢下来”。API 现在也应该稳定了。
InfoQ 与 Ambrose 进行了一次谈话以便于了解他是如何开始 core.typed 的:
该项目开始是我在西澳大利亚大学计算机科学学士的本科荣誉项目。我受到了 Sam Tobin-Hochstadt 类型化 Racket 的启发,它也是类型化 Clojure 内部很多理论和实现的源泉【编辑注释:类型化 Clojure 是 core.typed 之前的名称】。
InfoQ: 谈到验证,在 core.typed 中有很多单元测试。你还正式地验证你的类型检测器吗?(我假定 core.typed 使用了 core.typed?)
我相信所有的项目都将从验证技术的结合中受益。Core.typed 主要使用了单元测试验证,但是我也已经开始了类型检查实现。类型检测器具有广泛的适应性,它甚至能够静态地验证与使用其他验证技术相关的属性。例如,如果 core.typed 和 Prismatic 架构互相了解,那么 core.typed 就能够检查你的运行时测试架构是否能够充分地避免类型错误。
类型化 Clojure 在 _ 编译时 _ 能够检查的一些更加有趣的属性包括没有空指针异常, 正确的 Java 互操作和不可变绑定的正确使用。
具备良好测试覆盖率的类型检查代码体在寻找 bug 的时候并不是必须的,但是我发现将无类型代码转换成有类型代码的过程类似于代码审查。
InfoQ: 对于 Scala 程序员而言,有一些类型名称可能看起来很熟悉。Scala 也具有局部类型推理,那么 Scala 对 core.typed 有什么影响么?类型系统能够很好地测量出代码的复杂度:如果你的类型是巨大且凌乱的,那么可能有重构的机会。因为凌乱的类型通常意味着凌乱的逻辑。
确实有一些影响。类型化 Clojure 接口能够和 Java 代码友好相处,比较一下 Scala 是如何处理 Java 类型系统中的一些怪癖是非常有用的,例如数组协变和空指针。
还有一点点嫉妒 Scala:Odersky 的彩色局部类型推理(Colored Local Type Inference)就是局部类型推理的一个非常好的扩展,它允许 Scala 程序员省略某些注解。类型化 Clojure 和类型化 Racket 使用了另一种方式扩展局部类型推理,但是我们总是关注于使用像彩色局部类型推理这样的扩展去避免某些不必要的注解。
InfoQ: Clojure 社区的反馈如何?
对于社区的反应我一直都非常高兴。我认为这表明 Clojure 程序员在构建 Clojure 程序的时候一直都在渴望一个强大的、完全可选的类型系统。
InfoQ: 你下一个版本的计划是什么?
作为全职类型化 Clojure 开发集资项目的一部分,我已经列举了我接下来的计划。
我希望尽快完成的变化包括:支持将 Clojurescript 作为类型检查的目标,能够基于静态类型生成运行时契约,实现自托管的 Clojure 编译器并推出类型化 Clojure 能够满足的边界。
如果想进一步地了解与 core.typed 相关的信息,那么可以访问项目网站,或者看看这个工作室记录。如果你喜欢core.typed,不要忘记支持Ambrose 的 资金募集计划。
评论