我对类型系统的理解是否正确?

时间:2010-01-25 19:40:24

标签: language-agnostic type-systems

以下陈述代表了我对类型系统的理解(它在Java世界之外的实践经验太少);请更正任何错误。

静态/动态区别似乎非常明确:

  • 静态类型语言为每个变量,字段和参数分配一个类型,编译器会阻止不兼容类型之间的分配。示例:C,Java,Pascal。
  • 动态类型语言将变量视为可以容纳您想要的任何内容的通用容器 - 只有在您对值实际执行操作时才会在运行时检查类型(如果有的话),而不是在分配它们时。示例:Smalltalk,Python,JavaScript。
  • 类型推断允许静态类型语言看起来像(并具有一些优势)动态类型语言,通过从上下文推断类型,这样您就不必将它们声明为大多数时间 - 但与动态语言不同,你不能这样最初使用变量来保存字符串,然后为其分配一个整数。示例:Haskell,Scala

我对弱/弱的区别不太确定,我怀疑它的定义不是很明确:

  • 强类型语言为每个运行时值分配一个类型,并且只允许执行为该类型定义的操作,否则会出现显式类型错误。
  • 弱类型语言没有运行时类型检查 - 如果您尝试对不支持的值执行操作,则结果是不可预测的。它实际上可能会做一些有用的事情,但更有可能会导致数据损坏,崩溃或一些难以理解的二次错误。
  • 似乎至少有两种不同类型的弱类型语言(或者可能是连续统一体):
    • 在C和汇编程序中,值基本上是比特桶,因此任何事情都是可能的,如果你让编译器取消引用以空字符结尾的字符串的前4个字节,你最好希望它引导一个不包含合法机器的地方代码。
    • PHP和JavaScript通常也被认为是弱类型的,但不要将值视为不透明的位桶;但是,它们会执行隐式类型转换。
  • 但是这些隐式转换似乎主要适用于字符串/整数/浮点变量 - 这是否真的能保证分类为弱类型?或者还有其他问题,这些语言的类型系统可能会混淆错误吗?

8 个答案:

答案 0 :(得分:17)

  

我不太确定强弱差别,我怀疑它的定义不是很明确。

你是对的:事实并非如此。

这就是类型和编程语言高级类型和编程语言的作者Benjamin C. Pierce所说的:

  

我花了几周时间...尝试整理“强类型”,“静态类型”,“安全,“等等,发现它非常困难......这些术语的使用是多种多样的,使它们几乎无用。

Luca Cardelli在他的 Typeful Programming 文章中将其定义为缺少未经检查的运行时类型错误。 Tony Hoare将完全相同的属性称为“安全性”。其他论文称之为“类型安全”或简称“安全”。

Mark-Jason Dominus wrote a classic rant about this几年前在comp.lang.perl.moderated新闻组中讨论了Perl是否是强类型的。在这种咆哮中,他指出,在短短几个小时的研究中,他能够找到8种不同的,有时相互矛盾的定义,主要来自大学教科书或同行评审论文等受人尊敬的来源。特别是,那些文本包含的示例旨在帮助学生区分强类型和弱类型语言,并且根据这些示例,C是强类型的,C是弱类型的,C ++是强类型的,C ++是弱类型的,Lisp是强类型,Lisp是弱类型的,Perl是强类型的,Perl是弱类型的。 (这是否可以解决任何混淆?)

我一直看到的定义是:

  • 强类型:我的编程语言
  • 弱类型:您的编程语言

答案 1 :(得分:4)

关于静态和动态类型,你已经死了钱。静态类型意味着在执行之前检查程序,并且程序在启动之前可能会被拒绝。动态类型意味着在执行期间检查值的类型,并且类型不佳的操作可能导致程序在运行时停止或以其他方式发出错误信号。静态类型的主要原因是排除可能具有此类“动态类型错误”的程序。

Bob Harper认为动态类型语言可以(并且应该)被认为是具有单一类型的静态类型语言,Bob称之为“值”。这种观点是公平的,但它仅在有限的背景下有用,例如试图准确理解语言的类型理论。

虽然我认为你掌握了这个概念,但是你的子弹并不清楚类型推断只是静态类型的一个特例。在大多数具有类型推断的语言中,类型注释是可选的,但不一定在所有上下文中。 (示例:ML中的签名。)高级静态类型系统通常会在注释和推理之间进行权衡;例如,在Haskell中,您可以键入更高级别的多态函数(箭头左侧的forall),但只能使用注释。因此,如果您愿意添加注释,则可以让编译器接受在没有注释的情况下被拒绝的程序。我认为这是类型推断的未来潮流。

“强”和“弱”打字的想法我将其描述为无用,因为他们没有普遍认同的技术含义。强类型通常意味着类型系统中没有漏洞,而弱类型意味着类型系统可以被破坏(使任何保证无效)。这些术语经常被错误地用于表示静态和动态类型。为了看到差异,想想C:语言在编译时被类型检查(静态类型),但是存在很多漏洞;你几乎可以将任何类型的值转换为相同大小的另一种类型 - 特别是,你可以自由地转换指针类型。 Pascal是一种旨在强类型的语言,但却有一个无法预料的漏洞:一个没有标记的变体记录。

强类型语言的实现通常会随着时间的推移而产生漏洞,通常是因为部分运行时系统可以用高级语言实现。例如,Objective Caml有一个名为Obj.magic的函数,它具有简单地返回其参数的运行时效果,但在编译时它将任何类型的值转换为任何其他类型的值。我最喜欢的例子是Modula-3,其设计师称他们的类型转换构造LOOPHOLE

我鼓励你避免关于类型系统的术语“强”和“弱”,而是准确地说出你的意思,例如,“类型系统保证在运行时不会发生以下类错误” (强),“静态类型系统不能防止某些运行时错误”(弱),或“类型系统有漏洞”(弱)。只是将类型系统称为“强”或“弱”本身并不能很好地沟通。

答案 2 :(得分:2)

这是对我自己对静态/动态,强/弱打字讨论主题的理解的准确反映。此外,您还可以考虑其他语言:

在TCL和Bourne Shell等语言中,“main”值类型是字符串。可以使用数字运算符隐式强制将字符串表示形式的输入值和结果值强制转换为字符串表示形式。它们可以被视为动态弱类型语言的例子。

Forth可能是静态弱类型语言的一个例子。该语言不执行自己的类型检查,主堆栈可以互换地包含指针,整数,字符串(通常表示为两个单元格,起始和长度)。操作符的不一致使用可能导致有趣或未指定的行为。典型的Forth实现为浮点数提供单独的堆栈。

答案 3 :(得分:1)

也许this Book可以提供帮助。但是要准备一些数学。如果我没记错的话,一个“非数学”的陈述是:“强类型:我认为可以安全编程的语言”。

答案 4 :(得分:1)

  

似乎至少有两种不同类型的弱类型语言(或者可能是连续统一体):

     
      
  • 在C和汇编程序中,值基本上是比特桶,因此任何事情都是可能的,如果你让编译器取消引用以空字符结尾的字符串的前4个字节,你最好希望它引导一个不包含合法机器的地方代码。
  •   

我不同意这个说法,至少在C语言中。你可以用C语言操作类型系统,这样你就可以将任何给定的内存位置视为一桶位,但是变量绝对有一个类型,该类型具有特定属性。没有运行时检查(除非您将浮点异常或分段错误视为运行时检查)这一事实并不真正相关。在编译器为你执行一些隐式类型转换的意义上,C可以被认为是“弱类型”,但是它并没有走得太远。

答案 5 :(得分:1)

我认为强/弱是隐式转换的概念,一个很好的例子是添加字符串和数字。在强类型语言中,转换不会发生(至少在我能想到的所有语言中)并且您将收到错误。像VB这样的弱类型语言(使用Option Explicit Off)和Javascript将尝试将其中一个操作数转换为另一种类型。

在VB.Net中,Option Strict Off:

    Dim A As String = "5"
    Dim B As Integer = 5
    Trace.WriteLine(A + B) 'returns 10

使用Option Strict On(将VB转换为强类型语言),您将收到编译器错误。

在Javascript中:

    var A = '5';
    var B = 5;
    alert(A + B);//returns 55

有些人会说结果不可预测但实际上确实遵循一套规则。

答案 6 :(得分:0)

嗯,也不知道更多,但我想提一下C ++及其隐式转换(隐式构造函数)。这也可能是弱打字的一个例子。

答案 7 :(得分:0)

我同意其他人说“这里似乎没有一个硬性和快速的定义。”我的答案往往是基于语言为你提供WRT类型的绳索数量。如果你几乎可以伪造任何你想要的东西,那么它很弱。如果它真的不能让你陷入麻烦,即使你想要,它也很强大。

我真的没有看到太多的语言绕过这个边界,所以我不能说我曾经需要一个更好的定义......