朱莉娅语言是动态类型的吗?

105

许多博客以及手册都说Julia是动态类型语言。 但从我阅读手册的看法,它更像是带有静态类型检查类型推断的语言,类似F#

  • Julia是带有类型推断的静态类型语言吗?
  • Julia是动态类型语言吗?
  • 我假设它是动态类型的语言,因为手册错了的可能性很小。
  • Julia是否涉及类型推断?
3个回答

159
蒂姆·霍利的回答非常正确,但我会详细说明一下。首先,让我们定义一些术语 - 你可能不同意我的定义,但至少你会知道我在说什么。在我看来,静态语言和动态语言之间的主要区别在于:在静态语言中,表达式具有类型;在动态语言中,值具有类型。
在静态语言中,有规则来确定程序中每个表达式的类型。表达式的类型决定程序的行为。不能为每个表达式确定一致类型的程序被认为是不正确的,并且无法编译。在存在多态性的情况下,表达式的类型可能不是单个具体类型:参数多态性可以被视为让相同的代码描述一组具体类型算法的方法,这些算法由类型的参数索引;子类型多态性可以被视为在否则静态语言中引入有限数量的动态行为。
另一方面,动态语言没有为表达式分配类型的规则:类型是通过程序执行时数据流方式暗示的。一般来说,表达式可能产生任何类型的值。因此,类型理论家有时将动态语言描述为“单类型”-即从静态的角度来看,“类型”本质上是表达式的属性,在动态语言中,所有表达式的类型都是Any。当然,这是将静态类型的概念(仅对表达式有意义)应用于类型仅对值有意义的语言。
Julia明确地位于动态阵营中:类型是值而不是表达式的属性。代码的结果类型是通过值在执行时如何流动来确定的;语言不包括在执行之前为表达式分配类型的任何规则。但与许多动态语言不同,Julia具有相当复杂的用于谈论类型的语言,并且您可以使用类型注释来注释表达式。例如,x::T是一个断言,即x是类型为T的值;如果这是真的,则x::T计算为x的值,否则会引发错误并且该表达式不返回值。方法签名中的类型注释具有稍微不同的含义:它们不是断言现有值的类型,而是指示仅当相应参数为指定类型时才适用该方法。无论哪种情况,以下代码都可以安全地假定x的值是类型T。
[旁白:在一些具有“渐进”或“可选”类型的语言中,类型注释将语言从动态模式切换到静态模式:没有类型注释的方法是动态的;有类型注释的方法是静态的。在静态代码中,有规则将所有表达式分配给类型,并且代码必须满足这些规则。这不是Julia的工作方式-具有类型注释的代码仍然是动态的,并且具有与没有类型注释的代码相同的语义。]

F#、OCaml 或 Haskell 等语言中的类型推断是确定表达式类型的一部分。如果编译器无法推断任何表达式的类型,则您的程序将无法编译。这些语言都使用某种形式的 Hindley-Milner 类型推断,这是一种非常巧妙的方法,可以从代码结构中推导出表达式的类型,而不必编写显式类型(与动态语言相比,动态语言的类型是由代码执行隐含的)。大多数情况下根本不需要任何类型注释,这与像 C++、C# 和 Java 这样需要冗长类型声明的语言相比非常愉快。然而,这与像 Julia 和 Python 这样的动态语言非常不同,其中不需要类型注释仅仅是因为表达式没有预定的类型是完全可接受的。在 Hindley-Milner 语言中,您可能不必像在 C++ 或 Java 中那样编写许多类型,但每个表达式都必须具有编译器可以计算的预定类型。

Julia 的编译器也进行类型推断,但它非常不同:并不是每个表达式都需要有可推断的类型。编译器分析代码以尝试预测表达式的类型,并使用该信息生成更高效的机器代码。但是,如果它无法确定表达式的类型,那没关系:编译器只会发出通用代码,该通用代码将使用运行时类型信息仍能正常工作。在 Julia 中,大部分情况下类型推断只是一种优化 - 您的代码将以相同方式工作,无论是否进行类型推断 - 但是通过成功的类型推断,它将运行得更快。


2
删除类型注释不会改变Julia程序的含义,这显然是不正确的。当然会改变,因为Julia的方法分派机制如此运作。 - Steven Obua
4
@Steven_Obua,我不相信我的回答说或意味着类型注释没有语义意义,是吗? - StefanKarpinski
1
非常好的且富有信息量的回答,但是您在某个时候确实说过:“这不是Julia的工作方式——带有类型注释的代码仍然是动态的,并且与没有类型注释的代码行为相同。” - Steven Obua
5
“behaves the same” 指的是 “具有相同的语义”,但是,是的,我可以澄清这个区别。 - StefanKarpinski

39

两者都是正确的。Julia是动态类型语言,但在编写良好的Julia代码中,类型通常可以被推断出来。当可能性存在时,你经常会获得重大的性能提升。

关于这个问题有一些讨论,详见FAQ


4

它是动态类型的,但如果您指定类似变量::type的类型,则可以将该变量视为静态类型(这将提高编译器无法自动推断类型的情况下的性能)


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