在学术 CS 世界中,“非类型化”是否也意味着“动态类型化”?

我正在看一个幻灯片,上面写着“ JavaScript 是无类型的”这与我认为的事实相矛盾,所以我开始挖掘,试图了解更多。

每一个对 JavaScript 是一种非类型化语言吗?的回答都说 JavaScript 是 没有非类型化的,并且提供了各种形式的静态、动态、强和弱类型的例子,这些我都很熟悉也很满意。.所以这不是解决问题的办法。

于是我问 JavaScript 的创始人 Brendan Eich,他说:

学术类型使用“非类型化”来表示“没有静态类型”。它们足够聪明,能够看到值具有类型(当然!).背景事宜。

以学术为中心的计算机科学家们是否使用“非类型化”作为“动态类型化”的同义词(这有效吗?)还是我忽略了什么更深层次的东西?我同意布兰登的观点,上下文很重要,但是任何解释的引用都是很好的,因为我现在的“去”书在这个话题上并不合作。

我想明确这一点,这样我就可以提高我的理解,因为即使维基百科也没有提到这种替代用法(我可以找到,无论如何)。如果我错了,我不想在使用这个术语或质疑将来这个术语的使用方面搞砸: -)

(我还看到一个顶尖的 Smalltalker 说 Smalltalk 也是“无类型的”,所以它不是一次性的,这是什么让我开始这个任务!:-))

25725 次浏览

这个问题是关于 语义学

如果我给你这个数据: 12它的类型是什么?你无法确定。可以是整数,也可以是浮点数,也可以是字符串。从这个意义上说,它是非常“非类型化”的数据。

如果我给你一个假想的语言,让你使用操作符,如“添加”,“减去”,和“连接”在这个数据和一些其他任意的数据片段,“类型”是有点不相关(我的假想语言)(例如: 也许 add(12, a)产生的 10912加上 a的 ascii 值)。

我们来谈谈 C。C 语言几乎可以让您对任意的数据片段做任何您想做的事情。如果您使用的函数采用两个 uint-您可以强制转换和传递任何您想要的-并且值将被简单地解释为 uint。从这个意义上说,C 是“无类型的”(如果你这样对待它的话)。

然而——说到布兰登的观点——如果我告诉你“我的年龄是 12”——那么 12有一个类型——至少我们知道它是数字。有上下文每样东西都有一个类型——不管语言是什么。

这就是为什么我在一开始说-你的问题是一个语义。“无类型”是什么意思?我认为布兰登说的“没有静态类型”一语中的——因为这可能就是它的全部含义。人类自然地将事物分类。我们凭直觉知道汽车和猴子之间有着本质上的区别,却从来没有人教过我们如何区分。

回到我开头的例子——一种“不关心类型”(本身)的语言可以让你“添加”一个“年龄”和一个“名称”而不会产生语法错误... ... 但这并不意味着它是一个逻辑正确的操作。

Javascript 可能会让你做各种疯狂的事情而不考虑它们的“错误”。这并不意味着你所做的是合乎逻辑的。这是开发商的工作。

在编译/构建/解释时不强制类型安全的系统/语言是“非类型化”还是“动态类型化”?

语义学。

剪辑

我想在这里添加一些东西,因为有些人似乎被“是的,但是 Javascript 确实有一些类型”所吸引。

在我评论别人的回答时,我说:

在 Javascript 中,我可以把对象设计成“猴子”,把对象设计成“人类”,有些功能可以设计成只对“人类”进行操作,有些功能只对“猴子”进行操作,还有些功能只对“有武器的东西”进行操作。无论语言是否被告知有这样一类对象,例如“带胳膊的东西”,它与汇编(“无类型”)和 Javascript (“动态”)都是无关的。这完全是逻辑完整性的问题——唯一的错误就是使用的方法没有手臂。

因此,如果你认为 Javascript 在内部有一些“类型的概念”——因此是“动态类型”——并且认为它在某种程度上“明显不同于非类型化系统”——你应该从上面的例子中看到,它在内部有的任何“类型的概念”实际上都是不相关的。

例如,要使用 C # 执行相同的操作,我需要一个名为 ICreatureWithArms的接口或类似的东西。在 Javascript 中不是这样-在 C 或 ASM 中不是这样。

显然,Javascript 是否理解“类型”是无关紧要的。

我不是一个计算机科学家,但如果“非类型化”真的被用作 CS 社区(至少在科学出版物中)“动态类型化”的同义词,因为这两个术语描述了不同的概念,我会感到相当惊讶。动态类型语言有类型的概念,它在运行时强制类型约束(例如,你不能在 Lisp 中用一个字符串除一个整数而不得到一个错误) ,而非类型语言根本没有任何类型的概念(例如汇编程序)。甚至维基百科上关于编程语言( http://en.m.Wikipedia.org/wiki/programming_language#typed_versus_untyped_languages )的文章也做出了这样的区分。

更新: 也许这种困惑来自于一些文本在某种程度上说了一些在 Javascript 中“变量没有被类型化”的事实(这是真的)。但这并不意味着语言是无类型的(这是错误的)。

非类型化和动态类型化绝对不是同义词。最常被称为“非类型化”的语言是 Lambda 微积分,它实际上是一种统一类型的语言——一切都是一个函数,所以我们可以静态地证明一切的类型都是一个函数。动态类型语言具有多种类型,但不会为编译器添加静态检查这些类型的方法,从而迫使编译器对变量类型插入运行时检查。

然后,JavaScript 是一种动态类型的语言: 可以用 JavaScript 编写程序,这样一些变量 x可以是一个数字,或者一个函数,或者一个字符串,或者其他什么东西(并确定哪一个需要解决停机问题或者一些困难的数学问题) ,所以你可以将 x应用到一个参数中,浏览器必须在运行时检查 x是否是一个函数。

我研究了一下,发现你的问题的答案很简单,而且令人惊讶的是,“是的”: 学术 CS 类型,或者至少其中一些,确实使用“非类型化”来表示“动态类型化”。例如,编程语言: 原则与实践,第三版(由肯尼斯 · C · 劳登和肯尼斯 · A · 兰伯特合著,2012年出版)说:

没有静态类型系统的语言通常称为 无类型语言(或 动态类型语言)。这些语言包括 Scheme 和 Lisp、 Smalltalk 的其他方言,以及大多数脚本语言,如 Perl、 Python 和 Ruby。但是,请注意,非类型化语言不一定允许程序破坏数据 & mash; 这只是意味着所有的安全检查都在执行时执行。[ & 救命; ]

[ 链接](注: 原文为粗体) ,并继续以这种方式使用“ untype”。

我发现这很令人惊讶(和 afrischke 和 Adam Mihalcin 给出的原因差不多) ,但是你就在那里。 : -)


编辑后添加: 你可以通过将 "untyped languages"插入 Google 图书搜索找到更多的例子,例如:

这是许多非类型化语言的主要信息隐藏机制,例如 PLT Scheme 使用生成式 struct,[ & hellip; ]

Jacob Matthews 和 Amal Ahmed,2008[ 链接]

[ & hellip; ] ,我们提出了一个非类型化函数语言的绑定时间分析[ & hellip; ]。它已经实现,并被用于 Scheme 的一个无副作用方言的部分评估器。然而,这种分析非常一般,对于 Haskell 这样的非严格类型化函数语言是有效的。[ & 救命; ]

查尔斯 · 康塞尔,1990[ 链接]

顺便说一句,在浏览了这些搜索结果之后,我的印象是,如果一个研究人员写了一种“非类型化”的函数语言,他很可能认为它和亚当 · 米哈尔辛提到的那种 λ演算语言一样是“非类型化”的。至少,一些研究人员同时提到了 Scheme 和 lambda 微积分。

当然,搜索 没有说的是,是否有研究人员拒绝这种识别,而 不要认为这些语言是“无类型的”。我找到了这个:

然后我意识到实际上没有循环,因为动态类型语言不是非类型语言ーー只是类型通常不会立即从程序文本中显示出来。

某人(我不知道是谁) ,1998[ 链接]

但显然,拒绝这种身份认证的 大部分成员不会觉得有必要明确地说出来。

我是一名专门研究编程语言的学术计算机科学家,是的,“非类型化”这个词经常在这种情况下被错误地使用。如果能把这个词留给那些不带动态类型标签的语言,比如 Forth 和汇编代码,那就再好不过了,但是这些语言很少被使用,甚至很少被研究,而且说“非类型化”比说“动态类型化”要容易得多。

Bob Harper 喜欢说,Scheme、 Javascript 等语言应该被视为只有一个类型: value 的类型化语言。我倾向于这种观点,因为它使得仅仅使用一种形式主义就可以构建一个一致的世界观成为可能。

附言。在纯 lambda 演算中,唯一的“值”是标准形式的项,唯一的标准形式的 关门了项是函数。但是大多数使用 lambda 演算的科学家会添加基本类型和常量,然后要么为 lambda 添加一个静态类型系统,要么回到动态类型标记。

附注: 对于原创海报: 当涉及到编程语言,特别是类型系统时,维基百科上的信息质量很差。不要相信它。

同意布兰登的观点,背景就是一切。

我的看法是:

我记得大约在2004年的时候我很困惑,因为当时有关于 Ruby 是非类型化的还是动态类型化的争论。老派的 C/C + + 用户(我就是其中之一)认为编译器是无类型的。

请记住,在 C 语言中,没有运行时类型,只有地址,如果正在执行的代码决定将位于该地址的任何内容视为不存在的内容,哎呀。这绝对是非类型化的,与动态类型化非常不同。

在那个世界里,“输入”完全是关于编译器的。C + + 有“强类型”,因为编译器的检查更严格。Java 和 C 更“弱类型”(甚至还有关于 Java 是强类型还是弱类型的争论)。在这个连续统一体中,动态语言是“无类型的”,因为它们没有编译器类型检查。

今天,对于实践中的程序员来说,我们已经习惯了动态语言,我们显然认为非类型化意味着没有编译器或解释器类型检查,这将是非常难以调试的。但有一段时间,这并不明显,在更理论化的 CS 世界里,甚至可能是没有意义的。

在某种深层意义上,没有什么可以无类型化(或者几乎没有什么,无论如何) ,因为您必须有某种意图来操作值来编写有意义的算法。这就是理论 CS 的世界,它不涉及如何为给定语言实现编译器或解释器的细节。因此,“非类型化”(可能,我不知道)在这种情况下完全没有意义。

这两个语句都是正确的,具体取决于所讨论的是值还是变量。JavaScript 变量是无类型的,JavaScript 值具有类型,而且变量可以在运行时覆盖任何值类型(即“动态”)。

在 JavaScript 和许多其他语言中,值而不是变量携带类型。所有变量都可以覆盖所有类型的值,可以被认为是“动态类型”或“非类型”——从类型检查的角度来看,一个没有/不可知类型的变量和一个可以采用任何类型的变量在逻辑上和实际上是等价的。当类型理论家谈论语言和类型时,他们通常谈论的是这个——带有类型的变量——因为他们对编写类型检查器和编译器等感兴趣,这些编译器操作的是程序文本(即变量) ,而不是内存中正在运行的程序(即值)。

相比之下,在其他语言中,比如 C,变量包含类型,而值不包含类型。在 Java 等语言中,变量和值都带有类型。在 C + + 中,一些值(包含虚函数的值)包含类型,而另一些则不包含类型。在某些语言中,值甚至可以更改类型,尽管这通常被认为是糟糕的设计。

是的,这是学术文献中的标准做法。为了理解它,它有助于了解“类型”的概念是在1930年代发明的,在 lambda 微积分的背景下(事实上,甚至更早,在集合论的背景下)。从那时起,一个完整的计算逻辑分支出现了,被称为“类型理论”。程序设计语言理论就是建立在这些基础之上的。在所有这些数学语境中,“类型”有一个特殊的、确定的含义。

术语“动态类型”是很久以后才发明的——面对“类型”这个词的常见数学用法,这是一个矛盾的术语。

例如,本杰明 · 皮尔斯(Benjamin Pierce)在他的标准教科书 类型和编程语言中对“类型系统”的定义如下:

类型系统是一种易于处理的证明缺失的句法方法 通过将短语根据 他们计算的各种值。

他还表示:

“ static”这个词有时是显式添加的——我们说的是 例如,“静态类型编程语言”,以区分 我们在这里考虑的各种编译时分析来自 在 Scheme 等语言中发现的动态或潜在类型(Sussman 和 Steele,1975; Kelsey,Clinger,and Rees,1998; Dybvig,1996) , 其中运行时类型标记用于区分不同类型的 像“动态类型”这样的术语是有争议的 用词不当,应该用“动态检查”代替 但用法是标准的。

在这一领域工作的大多数人似乎都赞同这一观点。

注意,这样做意味着“非类型化”和“动态类型化”是同义词。相反,后者是前者的一个特殊情况的名称(在技术上具有误导性)。

PS: FWIW,我碰巧既是一个类型系统的学术研究者,又是一个 JavaScript 的非学术实现者,所以我不得不忍受这种分裂。:)

虽然大多数研究类型的 CS 研究人员实际上只将具有语法可派生类型的语言视为类型化语言,但是我们中有很多人使用动态/潜在类型化语言,他们对这种用法感到不快。

我认为有三种类型的语言:

非类型化——只有操作符决定对值的解释——它通常适用于任何情况。示例: 汇编程序,BCPL

静态类型化的表达式/变量具有与它们相关联的类型,该类型决定了运算符在编译时的解释/有效性。示例: C,Java,C + + ,ML,Haskell

动态类型化的值具有与它们相关联的类型,该类型决定了运算符在运行时的解释/有效性。示例: LISP、 Scheme、 Smalltalk、 Ruby、 Python、 Javascript

据我所知,所有动态类型语言都是类型安全的——也就是说,只有有效的操作符才能对值进行操作。但是对于静态类型语言来说,情况并非如此。根据所使用的类型系统的功率,有些操作符可能只在运行时检查,或者根本不检查。例如,大多数静态类型的语言不能正确处理整数溢出(添加2个正整数可以产生一个负整数) ,而且出界数组引用要么根本不检查(C,C + +) ,要么只在运行时检查。此外,一些类型系统非常脆弱,有用的编程需要转义孵化器(C 和家族中的强制转换)来更改表达式的编译时类型。

所有这些都导致了荒谬的说法,比如说 C + + 比 Python 更安全,因为它是(静态类型的) ,而事实是 Python 本质上是安全的,而你可以用 C + + 打断你的腿。