Clojure静态类型化

25

我知道这可能听起来是对Lisp追随者(和其他喜欢动态语言的人)的亵渎,但增强Clojure编译器以支持静态(编译时)类型检查有多困难?

撇开静态和动态类型的争论,这是否可行(不是“是否可取”)?

我在想,添加一个新的读取宏来强制进行编译时类型(#^宏的增强版本),并将类型信息添加到符号表中,将允许编译器标记变量错误使用的地方。例如,在下面的代码中,我希望出现编译时错误(#* 是“编译时”类型宏):

(defn get-length [#*String s] (.length s))
(defn test-get-length [] (get-length 2.0))

#^ 宏甚至可以与全局变量(*compile-time-type-checking*)一起重用,以强制编译器进行检查。

对可行性有何想法?


(definline t [] (list '.charAt "hello" (nth [1 "a" 2 :c 0] (rand-int 4))))(definline t [] (list '.charAt "你好"(nth [1 "a" 2:c 0](rand-int 4)))) - Pepijn
3
+1 我非常喜欢在Clojure中获得一些可选的静态类型检查,就像Racket中的http://docs.racket-lang.org/ts-guide/beginning.html那样。 - jneira
一些常见的Lisp编译器,如SBCL,可以检测到一些静态类型错误,例如这个。 - Rainer Joswig
6个回答

11

这是有可能的。不过,我认为Clojure不会采用任何形式的弱静态类型——它所带来的好处太少了。

然而,Rich Hickey多次表达了他对Qi语言强大、可选和表现力强的类型特性的喜爱。http://www.lambdassociates.org/qilisp.htm

alt text


2
谢谢David - 你有任何Rich表达这个观点的参考资料吗? - hawkeye

8

我几周前确实看过这个。希望它能够完全成熟。 - Ralph

8

当然可以。编译器已经在1.3开发分支中对原始参数类型进行了一些静态类型检查。


现在有可能实现,只需要有人花时间去实现,但大多数人并不真正关心。(我们将不得不使用Java类型系统,而这本身就不是很好的选择) - nickik
@nickik:是的,但你也知道,世界上有两种程序员:一种喜欢动态类型,另一种讨厌它。如果Clojure有可选的静态类型,许多“动态类型讨厌者”可能会尝试它。 - Ralph
我听到的共识是现在不值得这样做,因为Clojure编译器在某个时候将会用Clojure重写。 - user61051
1
@Ralph:静态风扇仍然不会喜欢它,因为大多数代码都不是类型安全的,而且类型系统很糟糕(这是Haskell人说的,我不知道是否属实)。 - nickik

0

由于一次只能读取和评估一个表单,因此您无法进行前向引用,这使得它有些受限。


2
Clojure支持declare的前向引用。 - dnolen
Clojure 支持“变量”的前向引用,这对于静态类型检查没有任何好处。你无法在不知道类型的情况下进行静态检查(除了名称外,你对数据结构一无所知)。这就是为什么许多静态类型语言具有两个通过编译器的原因。首先构建符号表,然后进行检查。因此,Stuart所说的对于已经定义的类型(原始类型、STD lib 等,包括您程序中到目前为止定义的任何类)是正确的,但它并不是一个通用解决方案。 - Bryan
在“declare”中,可以有类型提示吗? - Ralph
我认为这取决于你的类型系统是如何实现的,可能并不需要。这就是为什么我提到了 Qi。 - dnolen
1
F# 没有前向引用,这很好。实际上这是件好事,你总是知道如何读取代码。它确实有 'and',但只适用于有限范围的前向检查。 - Robert Jeppesen

0

声明可以具有类型提示,因此可以声明一个变量,该变量“是”尚未定义但包含有关结构的数据类型,但这将非常笨重,并且您必须在任何可能在类型定义之前执行的代码路径之前执行它。 基本上,您希望预先定义所有用户定义的类型,然后像正常情况下使用它们一样。 我认为这使库编写变得有些卑劣。

我之前并不是要说这不可能,只是对于用户定义的类型而言,它比预定义的类型复杂得多。 这样做的好处与成本是应该认真考虑的事情。 但是我鼓励任何有兴趣的人尝试一下,看看他们能否使其工作!


Clojure(以及其他Lisp语言)的一大优点是宏系统。我同意在declare中添加元数据有些笨拙,但是通过新的宏(例如:declare-typed),添加元数据可以变得非常容易。对于def也是一样。 - Ralph
正如dnolen在另一个评论线程中指出的那样,您不必使用两遍类型检查算法。这就是为什么我在描述静态类型语言时使用了“许多”而不是“全部”的原因。 - Bryan

0

虽然这是一个老问题,但有两个重要的观点:我认为Clojure不支持阅读器宏,只支持普通的lisp宏。现在我们在Clojure中有core.typed选项进行类型标注。


Clojure确实支持阅读器宏,只是不支持用户定义的阅读器宏。 - Ralph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接