代码之家  ›  专栏  ›  技术社区  ›  Michael Borgwardt

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

  •  16
  • Michael Borgwardt  · 技术社区  · 15 年前

    下面的语句代表了我对类型系统(在Java世界之外的操作经验太少)的理解;请纠正任何错误。

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

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

    我对强/弱区别不太确定,我怀疑它的定义不太清楚:

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

    我对强/弱的区别不太确定,我怀疑它的定义不太清楚。

    你是对的:不是。

    这是本杰明·C·皮尔斯的著作。 类型和编程语言 高级类型和编程语言 不得不说:

    我花了几个星期…尝试整理“的术语 强类型 静态类型 安全的 “等等,而且发现这非常困难……这些术语的用法千差万别,几乎使它们无用。

    Luca Cardelli,在他的 打字程序设计 项目,将其定义为没有未选中的运行时类型错误。托尼·霍尔称之为 完全相同 “安全”财产。其他报纸称之为“类型安全”或简单的“安全”。

    马克·杰森·多明斯 wrote a classic rant about this 几年前,在comp.lang.perl.moderated新闻组上,讨论Perl是否是强类型的。在这篇文章中,他指出,在短短的几个小时的研究中,他能够找到8种不同的,有时是相互矛盾的定义,大多来自受人尊敬的来源,如大学教科书或同行评议的论文。特别是,这些文本包含帮助学生区分强类型和弱类型语言的示例,并且根据这些示例,C是强类型的,C是弱类型的,C++是强类型的,C++是弱类型的,Lisp是强类型的,Lisp是弱类型的,Perl是强类型的,Perl是弱类型的。(这能消除任何困惑吗?)

    这个 只有 我所看到的一贯适用的定义是:

    • 强类型 :我的编程语言
    • 弱类型的 :您的编程语言
        2
  •  4
  •   Norman Ramsey    15 年前

    关于 静态和动态类型 你要钱死了。静态类型化意味着程序在执行之前会被检查,并且程序在启动之前可能会被拒绝。动态类型化意味着在执行期间检查值的类型,而类型化不好的操作可能导致程序停止,或者在运行时发出错误信号。静态类型的一个主要原因是排除可能有这样的“动态类型错误”的程序。

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

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

    “强”和“弱”输入法的概念我将其描述为 没有用 因为他们没有一个通用的技术含义。强类型通常意味着类型系统中没有漏洞,而弱类型则意味着类型系统可以被破坏(使任何保证无效)。这些术语通常被错误地用于表示静态和动态类型。要了解区别,可以考虑C:该语言在编译时进行了类型检查(静态类型),但是有很多漏洞;您几乎可以将任何类型的值强制转换为其他相同大小的类型,特别是,您可以自由转换指针类型。Pascal是一种旨在强类型化的语言,但众所周知,它有一个无法预见的漏洞:一个没有标签的变体记录。

    强类型语言的实现通常会随着时间的推移而获得漏洞,因此运行时系统的一部分可以用高级语言实现。例如,目标caml有一个函数 Obj.magic 它具有只返回参数的运行时效果,但在编译时它将任何类型的值转换为任何其他类型的值。我最喜欢的例子是modula-3,它的设计者称其为类型转换构造 LOOPHOLE .

    我鼓励您避免使用“强”和“弱”这两个术语来描述类型系统,而是准确地说出您的意思,例如,“类型系统保证以下类型的错误不会在运行时发生”(强),“静态类型系统不保护某些运行时错误”(弱),或“类型系统有漏洞”。(弱)仅仅称一个类型系统为“强”或“弱”本身并不能很好地进行通信。

        3
  •  2
  •   ddaa    15 年前

    这是我对静态/动态、强/弱类型讨论主题理解的一个非常准确的反映。此外,您还可以考虑其他语言:

    在tcl和bourne shell等语言中,“main”值类型是字符串。数字运算符可用于隐式地将输入值从字符串表示形式和结果值强制为字符串表示形式。它们可以看作是动态弱类型语言的例子。

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

        4
  •  1
  •   zedoo    15 年前

    也许吧 this Book 可以帮忙。不过,要准备好数学。如果我没记错的话,“非数学”语句是:“强类型:一种我觉得可以安全编程的语言”。

        5
  •  1
  •   Nathan Parrish    15 年前

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

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

    我不同意这一说法,至少在C语言中是这样的。你可以在C语言中操作类型系统,这样你就可以处理任何给定的 内存位置 就像一桶比特,但是 变量 大多数情况下都有一个类型,并且该类型具有特定的属性。没有运行时检查(除非您将浮点异常或分段错误视为运行时检查)这一事实实际上并不相关。C可以被认为是“弱类型”,因为编译器将为您执行一些隐式类型转换,但它不会进行太远的转换。

        6
  •  1
  •   Chris Haas    15 年前

    我认为强/弱是隐式转换的概念,一个很好的例子是字符串和数字的加法。在强类型语言中,转换不会发生(至少在我能想到的所有语言中是这样),您将得到一个错误。弱类型语言(如vb(禁用了选项explicit)和javascript)将尝试将一个操作数强制转换为另一个类型。

    在VB.NET中,选项严格关闭:

        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
    

    有些人会说,结果是不可预测的,但他们确实遵循一套规则。

        7
  •  0
  •   Gabriel Ščerbák    15 年前

    嗯,也不知道更多,但是我想提到C++及其隐式会话(隐式构造函数)。这可能是弱类型的一个例子。

        8
  •  0
  •   Brian Postow    15 年前

    我同意其他人所说的“这里似乎没有一个硬性和快速的定义。”我的答案往往是基于语言给你的WRT类型有多少绳子。如果你能伪造任何你想要的东西,那么它是脆弱的。如果它真的不让你陷入麻烦,即使你想,它是强大的。

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

    推荐文章