Julia 是动态类型的吗?

Is Julia dynamically typed?

很多博客了,manual itself, say that Julia is dynamically typed。 但是从我对手册的阅读来看,这听起来更像是 statically typed with type inference, like F#.

两者都是正确的。 Julia 是动态类型的,但在编写良好的 julia 代码中,通常可以推断出类型。如果可能的话,您通常会获得重大的性能提升。

有人对此进行了一些讨论 in the FAQ

Tim Holy 的回答非常正确,但我会详细说明一下。首先,让我们定义一些术语——您可能不同意我的定义,但至少您会明白我在说什么。在我看来,静态语言和动态语言之间的主要区别在于:在静态语言中,表达式具有类型;在静态语言中,表达式具有类型。在动态语言中,值有类型。

在静态语言中,有一些规则可以确定程序中每个表达式的类型。表达式的类型决定了程序的行为。不允许为每个表达式确定一致类型的程序被认为是不正确的,并且不会编译。在存在多态性的情况下,表达式的类型可能不是单一的具体类型:参数多态性可以被认为是一种让相同代码描述一整套具体类型算法的方式,由类型的参数索引;子类型多态性可以被认为是将有限数量的动态行为引入到静态语言中。

另一方面,动态语言没有为表达式分配类型的规则:数据在程序执行时流过程序的方式暗示了类型。通常,表达式可能会产生任何类型的值。正因为如此,类型理论家有时将动态语言描述为“统一的”——即从静态的角度来看,“类型”本质上是表达式的 属性,动态语言中的所有表达式都具有 [=10] 类型=].当然,这是将类型的静态概念(仅对表达式有意义)应用到类型概念仅对值有意义的语言。

Julia 完全属于动态阵营:类型是 属性 值而不是表达式。代码的结果类型取决于执行时值如何流经它;该语言不包含任何在执行表达式之前将类型分配给表达式的规则。然而,与许多动态语言不同,Julia 有一种相当复杂的语言来讨论类型,您可以用类型注释表达式。例如,x::T 是断言 x 是类型 T 的值;如果为真,x::T 的计算结果为 x 的值,否则会引发错误并且表达式 returns 没有值。方法签名中的类型注释的含义略有不同:它们不是断言现有值的类型,而是指示该方法仅在相应参数属于指定类型时才适用。在任何一种情况下,以下代码都可以安全地假设 x 的值是 T.

类型

[旁白:在某些具有“渐进”或“可选”类型的语言中,类型注释将语言从动态模式切换为静态模式:没有类型注释的方法是动态的;带有类型注解的方法是静态的。在静态代码中,有为所有表达式分配类型的规则,代码必须满足这些规则。这不是 Julia 的工作方式——带有类型注释的代码仍然是动态的,并且与没有类型注释的代码具有相同的语义。]

F#、OCaml 或 Haskell 等语言中的类型推断是确定表达式类型的一部分。如果编译器无法推断出任何表达式的类型,则您的程序将被破坏并且无法编译。这些语代码的执行)。大多数时候根本不需要类型注释,与 C++、C# 和 Java 等语言中可能需要的冗长类型声明相比,这是非常令人愉快的。然而,这与像 Julia 和 Python 这样的动态语言非常不同,在这些语言中不需要类型注释只是因为表达式没有预先确定的类型是完全可以接受的。在 Hindley-Milner 语言中,您可能不必像在 C++ 或 Java 中编写那么多类型,但每个表达式都必须具有编译器可以计算的预定类型。

Julia 的编译器会进行类型推断,但它非常不同:没有必要让每个表达式都具有可推断的类型。编译器分析代码以尝试预测表达式的类型,并使用该信息生成更高效的机器代码。但是,如果它不能确定表达式的类型,那也没什么大不了的:编译器只是使用 运行-time 类型信息发出无论如何都能工作的通用代码。在 Julia 中的大部分时间里,类型推断只是一种优化——无论有没有它,你的代码都将以相同的方式工作——但如果类型推断成功,它会 运行 快很多。

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