你知道一种具有静态类型检查且代码是数据的编程语言吗?

17

您能说出具有静态类型检查(类似于Java)并且代码是数据(就像在LISP中一样)的语言吗? 我的意思是指一个语言同时拥有这两点。


1
我倾向于同意这个问题的答案:https://dev59.com/wnA85IYBdhLWcg3wEPVL,即同时拥有两者是不可能的。 - Daniel Pryden
3
@Daniel:那个问题只有得票最低的答案声称无法同时实现两者。它这样做是通过声称打字会非常困难来实现的。确实很难,但并非不可能。 - Nathan Shively-Sanders
这非常类似于 http://stackoverflow.com/questions/3037643/typed-metaprogramming-languages。 - Jacques Carette
http://en.wikipedia.org/wiki/Nemerle - dotneter
6个回答

14

Qi是一种静态类型的Lisp方言。此外,许多其他Lisp方言也具有(可选的)静态类型。

Java本身在这方面的能力非常有限。

有趣的问题不是你是否可以拥有元编程和静态类型,而是你是否可以实现静态类型安全的动态元编程。

有Template Haskell这个工具可以进行元编程并且是类型安全的,但它是静态的元编程。

目前我无法想到任何一种语言实现了我所知道的允许动态元编程以及动态元编程静态类型安全的语言。Qi可能可以实现,但我不能确定。


2
我可以请您澄清一下术语吗?我不确定我完全理解您的观点。动态元编程和静态元编程有什么区别?静态元编程是指“在编译时”,例如宏,而动态元编程是指“在运行时”,例如任意表达式引用吗? - Nathan Shively-Sanders

11

Racket(前身为PLT Scheme)有一个静态类型方言,旨在与Scheme习惯用语良好地配合 - 包括宏。 (它通过对展开结果进行类型检查来工作。)


4

F#具有引用表达式。以下是MSDN页面上的内容:

// typed
let e : Expr<int> = <@ 1 + 1 @>
// untyped
let e' : Expr = <@@ 1 + 1 @@>
// splicing with %
// similar to Lisp's unquote-splicing, but type-checked:
// you can only splice expressions of the appropriate type
<@ 1 + %e @>

我认为这些在C#中是可用的,但是(1)我不知道语法是什么(2)数据结构是不同的。

这些语言允许在编译时将代码作为数据,就像Lisp宏一样:

免责声明:我实际上没有使用过任何一个。据我所知,它们都比Lisp的quote更加复杂。

然而,90%的“代码作为数据”使用quote可以通过闭包来完成,因为它们也会延迟评估。许多语言都有方便的语法来创建闭包(例如C#,Clojure,Scala和Ruby),并且不需要太多使用quote。即使在Scheme中,它是一个明确的Lisp,流行的风格也倾向于传递函数而不是编写宏。


2
宏并非“编译时”。在Lisp解释器中,宏可以完美地工作。Lisp宏也不是90%关于延迟评估。宏有很多用途,大多数与延迟评估无关。 - Rainer Joswig
宏的求值在Common Lisp和Scheme中发生于“读取时间”(据我所知)。我不知道问答者是否会认识这个术语,因此我使用了一个不太准确但更常见的术语。虽然有过具有一级宏的实验性Lisp,但它们并不普遍。至于延迟求值,那正是quote所用之处,而闭包也同样具备,尽管不太方便。我所说的不仅仅是宏,因为宏只是代码即数据的受限使用方式。 - Nathan Shively-Sanders
3
在 Common Lisp 中,宏评估肯定不会发生在“读取时间”。一点都不。宏扩展发生在解释和/或编译期间,这在 CL 标准中有描述。如果代码在解释运行,则宏可以在解释期间扩展。QUOTE 也不是用于延迟像“闭包”一样的评估。QUOTE 用于表示文字数据。引用的代码没有被延迟,所以它可以被“强制执行”。如果要执行引用的代码,则必须对其进行评估。这是一个巨大的区别。 - Rainer Joswig
F#还具有类型提供程序(Type Providers),它们是在编译时运行的自定义DLL。这些使用表达式来生成编译代码,而不是运行时数据结构。 - Hans

4

模板 Haskell 是一种静态类型语言,但它允许您将代码作为数据进行操作,也就是所谓的元编程。相关的语言包括 MetaML 和 MetaOCaml。请查看 Tim Sheard 的工作。


2
MetaML和MetaOCaml与TH非常不同 - 前者是双重类型的(类型生成器保证只生成类型化代码),而TH仅是单一类型的,即仅对模板扩展的结果进行类型检查。 - Jacques Carette
@Jacques 说得好,但它们仍然足够相似,我愿意将它们放在同一个答案中 :-) - Norman Ramsey

0
如果你只是想在静态类型语言中动态执行代码,那么Java本身就可以做到:

http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html

如果你需要更多的功能(例如将方法和类作为一等对象),那么你最好使用像Haskell或C#(如其他答案中提到的)这样的编程语言。


0
也许类似于Smalltalk的反射系统 StrongtalkZero ,但都是静态类型的。

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