许多博客和手册本身都说Julia是动态键入的。但是从我对手册的阅读中,听起来更像是使用类型推断(例如F#) 静态键入的。
- 朱莉娅是否使用类型推断静态键入?
- 它是动态输入的吗?
- 我假设它是动态键入的,手册似乎不太可能是错误的。
- Julia完全涉及类型推断吗?
Answers:
蒂姆·霍利(Tim Holy)的回答很正确,但我会详细说明。首先,让我们定义一些术语–您可能不同意我的定义,但至少您会知道我在说什么。在我看来,静态和动态语言之间的主要区别在于:在静态语言中,表达式具有类型;在静态语言中,表达式具有类型。在动态语言中,值具有类型。
在静态语言中,有一些规则可以确定程序中每个表达式的类型。表达式的类型决定了程序的行为。不允许为每个表达式确定一致类型的程序被认为是错误的,将无法编译。在存在多态的情况下,表达式的类型可能不是单一的具体类型:可以将参数多态性视为让同一代码描述整个具体类型的算法家族的一种方式,该算法由类型的参数索引;可以将子类型多态性视为将有限数量的动态行为引入到其他静态语言中。
另一方面,动态语言没有为表达式分配类型的规则:数据在执行时流经程序的方式暗含了类型。通常,表达式可以根本产生任何类型的值。因此,类型理论家有时将动态语言描述为“单型”-即从静态角度来看,“类型”本质上是表达式的属性,而动态语言中的所有表达式都具有类型Any
。当然,这是将静态类型(仅对表达式有意义)应用于一种语言,其中类型仅对值有意义。
朱莉娅正处于动态阵营中:类型是值的属性,而不是表达式。代码的结果类型由值在执行时如何流过代码决定。该语言不包含在执行表达式之前为表达式分配类型的任何规则。但是,与许多动态语言不同,Julia具有一种相当复杂的语言来谈论类型,您可以用类型来注释表达式。例如,x::T
是一个断言,它x
是type的值T
;如果是真的,则x::T
求值为x
,否则将引发错误,并且表达式不返回任何值。方法签名中的类型注释的含义稍有不同:它们不是声明现有值的类型,而是表示仅当相应参数为所指示类型时才应用该方法。无论哪种情况,以下代码都可以安全地假定of的值为x
type T
。
[另外:在某些具有“渐进”或“可选”类型的语言中,类型注释将语言从动态模式切换为静态模式:没有类型注释的方法是动态的;具有类型注释的方法是静态的。在静态代码中,存在为所有表达式分配类型的规则,并且代码必须满足这些规则。这不是Julia的工作方式-带类型注释的代码仍然是动态的,并且与不带类型注释的代码具有相同的语义。]
使用F#,OCaml或Haskell等语言进行类型推断是确定表达式类型的一部分。如果编译器无法推断任何表达式的类型,则您的程序已损坏并且将无法编译。这些语言都使用某种形式的Hindley-Milner类型推断,这是从代码结构中导出表达式类型的一种非常聪明的方法,而无需写出显式类型(将其与动态语言进行比较,在动态语言中,类型被隐含)执行代码)。在大多数情况下,根本不需要类型注释,这与C ++,C#和Java等语言中可能需要的冗长的类型声明相比是一件令人愉快的事情。但是,这是非常不同的 来自动态语言(例如Julia和Python),它们不需要类型注释,仅仅是因为表达式没有预定的类型是完全可以接受的。在Hindley-Milner语言中,您可能不必编写与C ++或Java一样多的类型,但是每个表达式必须具有编译器可以计算的预定类型。
Julia的编译器会进行类型推断,但有很大不同:不必每个表达式都具有可推断的类型。编译器分析代码以尝试预测表达式的类型,然后使用该信息生成更有效的机器代码。但是,如果它不能确定表达式的类型,那么没什么大不了的:编译器只是使用运行时类型信息发出将始终起作用的通用代码。在Julia的大部分情况下,类型推断只是一种优化-无论有没有代码,代码都可以按相同的方式工作-但是成功进行类型推断后,它的运行速度将大大提高。
它是动态类型的,但是如果您指定类似variable :: type的类型,则可以认为该变量是静态类型的(在编译器无法自动推断类型的情况下,这将提高性能)