我正在阅读一个幻灯片,上面写着“JavaScript是无类型的”。这与我认为的真实相矛盾,所以我开始尝试去学习更多。
Is JavaScript an untyped language?的每个答案都表示JavaScript 不无类型,并提供了各种形式的静态,动态,强大和弱类型的示例,这些都是我熟悉和满意的。所以这不是要走的路。
所以我问过JavaScript的创建者Brendan Eich,他说:
学术类型使用“无类型”来表示“没有静态类型”。他们足够聪明,可以看到价值观有类型(呃!)。背景问题。
以学术为中心的计算机科学人员是否使用“无类型”作为“动态类型”的同义词(这是有效的吗?)还是有更深层次的东西让我失踪?我同意布兰登的观点,认为背景很重要,但任何解释的引用都会很棒,因为我目前的“去”书并没有在这个主题上发挥作用。
我想要明确这一点,以便我可以提高我的理解力,因为即使维基百科也没有提到这种替代用法(无论如何我都能找到)。如果我错了,我不想在未来使用该术语或质疑该术语的使用: - )
(我也看到一位顶级的Smalltalker说Smalltalk也是“无类型”,所以这不是一次性的,这就是让我完成这个任务!: - ))
答案 0 :(得分:142)
是的,这是学术文献中的标准做法。要理解它,有助于知道“类型”的概念是在20世纪30年代发明的,在lambda演算的背景下(事实上,甚至更早,在集合论的背景下)。从那以后,出现了一个被称为“类型理论”的计算逻辑的整个分支。编程语言理论基于这些基础。在所有这些数学语境中,“类型”具有特定的,完善的含义。
术语“动态打字”是后来发明的 - 面对“类型”一词的常见数学用法,这是一个矛盾。
例如,以下是Benjamin Pierce在其标准教科书 Types and Programming Languages 中使用的“类型系统”的定义:
类型系统是用于证明缺席的易处理的句法方法 通过按照分类来分类短语的某些程序行为 他们计算的各种价值。
他也说:
有时会明确添加“静态”一词 - 我们说的是 “静态类型编程语言”,例如 - 区分 我们在这里考虑的各种编译时分析 在Scheme(Sussman等)等语言中发现的动态或潜在类型 和斯蒂尔,1975年; Kelsey,Clinger和Rees,1998; Dybvig,1996), 其中运行时类型标签用于区分不同类型的标签 堆中的结构。像“动态类型”这样的术语可以说是有道理的 用词不当,应该用“动态检查”代替 但用法是标准的。
大多数在该领域工作的人似乎都在分享这种观点。
请注意,不表示“无类型”和“动态类型”是同义词。相反,后者是前者特定案例的(技术上误导性)名称。
PS:和FWIW,我碰巧既是类型系统的学术研究员,也是JavaScript的非学术实现者,所以我必须忍受schisma。 :)答案 1 :(得分:64)
我是一名专攻编程语言的学术计算机科学家,是的,“无类型”这个词经常(误)用于这种方式。保留用于不带动态类型标签的语言(例如Forth和汇编代码)的单词会很好,但这些语言很少使用,甚至更少研究,并且说“无类型”更容易比“动态打字”。
Bob Harper喜欢说像Scheme,Javascript等语言应该被认为是只有一种类型的类型语言:value。我倾向于这种观点,因为它可以使用一种类型的形式主义来构建一致的世界观。
P.S。在纯lambda演算中,唯一的“值”是正常形式的术语,而正常形式中唯一的闭合术语是函数。但是大多数使用lambda演算的科学家都会添加基类型和常量,然后你要么为lambda包含一个静态类型系统,要么你回到动态类型标签。
P.P.S。原创海报:当谈到编程语言,特别是类型系统时,维基百科上的信息质量很差。不要相信它。
答案 2 :(得分:41)
我调查了一下,发现问题的答案很简单,而且令人惊讶的是,“是”:学术CS类型,或者至少其中一些,确实使用“无类型”来表示“动态类型” 。例如,编程语言:原理与实践,第三版(作者Kenneth C. Louden和Kenneth A. Lambert,2012年出版)说:
没有静态类型系统的语言通常称为无类型语言(或动态类型语言)。这些语言包括Scheme和Lisp,Smalltalk的其他方言,以及大多数脚本语言,如Perl,Python和Ruby。但请注意,无类型语言不一定允许程序破坏数据 - 这只意味着所有安全检查都在执行时执行。 [...]
[link](注意:用原文加粗)并继续以这种方式使用“无类型”。
我觉得这很令人惊讶(与afrischke和Adam Mihalcin给出的原因大致相同)但是你有。 : - )
已编辑添加:您可以通过将"untyped languages"
插入Google图书搜索来查找更多示例。例如:
[...]这是主要的信息隐藏机制,是许多无类型语言。例如,PLT Scheme [4]使用生成
struct
s,[...]
- Jacob Matthews和Amal Ahmed,2008 [link]
[...],我们提供了一种非类型化函数语言的绑定时间分析[...]。 [...]它已经实施并在部分评估员中用于方案的无副作用方言。然而,分析足够普遍,对于非严格类型的函数语言(如Haskell)有效。 [...]
- Charles Consel,1990 [link]
顺便说一下,在查看这些搜索结果之后,我的印象是,如果研究人员写了一篇“无类型”的函数式语言,他很可能会认为它是“无类型的”,与Adam Mihalcin提到的无类型lambda演算。至少,一些研究人员同时提到了Scheme和lambda演算。
搜索不当然是说,是否有研究人员拒绝此识别,不认为这些语言是“无类型” 。好吧,我确实找到了这个:
然后我意识到实际上没有循环性,因为动态类型语言不是无类型语言 - 只是程序文本中的类型通常不会立即明显。
- 某人(我不知道是谁),1998 [link]
但显然大多数拒绝此身份证明的人不会觉得有必要明确说出来。
答案 3 :(得分:9)
无类型和动态类型绝对不是同义词。最常被称为“无类型”的语言是Lambda微积分,它实际上是一个统一的语言 - 一切都是函数,所以我们可以静态地证明一切的类型都是函数。动态类型语言有多种类型,但没有为编译器添加静态检查方法,迫使编译器在变量类型上插入运行时检查。
然后,JavaScript是一种动态类型语言:可以用JavaScript编写程序,使得某些变量x
可以是数字,函数,字符串或其他东西(并确定哪一个)需要解决停机问题或一些硬数学问题),因此您可以将x
应用于参数,浏览器必须在运行时检查x
是否为函数。
答案 4 :(得分:5)
两种陈述都是正确的,取决于你是在谈论价值观还是变数。 JavaScript变量是无类型的,JavaScript值具有类型,并且变量可以在运行时覆盖任何值类型(即动态')。
在JavaScript和许多其他语言中,值而不是变量带有类型。所有变量都可以覆盖所有类型的值,并且可以被视为"动态类型"或"无类型" - 从类型检查的角度来看,一个没有/不可知类型的变量和一个可以采用任何类型的变量在逻辑上和实际上是等价的。当类型理论家谈论语言和类型时,他们通常会谈论这个 - 携带类型的变量 - 因为他们对编写类型检查器和编译器等感兴趣,它们对程序文本(即变量)进行操作而不是在内存中运行程序(即价值观)。
相比之下,在其他语言中,如C,变量带有类型,但值不带。在像Java这样的语言中,变量和值都带有类型。在C ++中,一些值(具有虚函数的值)携带类型而其他值则不携带。在某些语言中,值甚至可以改变类型,尽管这通常被认为是糟糕的设计。
答案 5 :(得分:3)
这个问题完全是关于Semantics
如果我给你这个数据:12
它的类型是什么?你无法确定。可以是一个整数 - 可以是一个浮点数 - 可以是一个字符串。从这个意义上说,这是非常“无类型”的数据。
如果我给你一个虚构的语言,让你可以使用像“add”,“subtract”和“concatenate”这样的运算符来处理这些数据和其他一些任意数据,那么“类型”在某种程度上是不相关的(对于我的想象语言) )(例如:或许add(12, a)
产生109
,12
加上a
的ascii值。
让我们谈谈C一秒钟。 C几乎可以让你随心所欲地使用任意数据。如果你正在使用一个需要两个uint
的函数 - 你可以投射并传递你想要的任何东西 - 这些值将简单地解释为uint
s。在这种意义上,C是“无类型的”(如果你以这种方式对待它)。
然而 - 并且达到布兰登的观点 - 如果我告诉你“我的年龄是12
” - 那么12
有一个类型 - 至少我们知道它是数字。 使用上下文一切都有类型 - 无论语言如何。
这就是我在开头说的原因 - 你的问题是语义之一。 “无类型”是什么意思?当布兰登说“没有静态类型”时,我认为布兰登头上钉了一针 - 因为这就是它可能意味着什么。人类自然地将事物分类为类型。我们直观地知道汽车和猴子之间存在着根本不同的东西 - 没有被教导做出这些区别。
在开头回到我的例子 - 一种“不关心类型”的语言(本身)可以让你“添加”“年龄”和“名称”,而不会产生语法错误。但这并不意味着它是一个逻辑上合理的操作。
Javascript可能会让你做各种疯狂的事情而不考虑它们的“错误”。这并不意味着你所做的事情在逻辑上是合理的。这是开发人员可以解决的问题。
系统/语言是否在编译/构建/解释时强制类型安全“无类型”或“动态类型”?
语义。
修改强>
我想在这里添加一些内容,因为有些人似乎陷入了“是的,但是Javascript确实有一些”类型“”。
在我对其他人的回答的评论中,我说:
在Javascript中我可以拥有我构建为“猴子”的对象和我构建为“人类”的对象,而某些功能可以设计为仅在“人类”上运行,其他功能仅在“猴子”上运行“,还有其他人只关注”武器之物“。无论语言是否被告知存在这样一类对象,如“带武器的东西”与汇编(“无类型”)和Javascript(“动态”)无关。这都是逻辑完整性的问题 - 唯一的错误就是使用那种没有武器的东西。
所以,如果你认为Javascript在内部有一些“类型的概念” - 因此“动态类型” - 并认为这在某种程度上“与无类型系统明显不同” - 你应该从上面看到例如,它内部的任何“类型概念”都是无关紧要的。
例如,要使用C#执行相同的操作,我需要一个名为ICreatureWithArms
的接口或类似的接口。在Javascript中不是这样 - 在C或ASM中不是这样。
显然,Javascript是否完全理解“类型”是无关紧要的。
答案 6 :(得分:2)
虽然大多数关于类型的CS研究人员确实只考虑具有语法可导类型的语言作为类型语言,但是我们中有更多的人使用动态/潜在类型的语言,这些语言在这种情况下会受到不满。 / p>
我认为有3种类型的[SIC]语言:
无类型 - 只有运算符确定值的解释 - 它通常适用于任何事物。示例:汇编程序,BCPL
静态类型 - 表达式/变量具有与之关联的类型,该类型在编译时确定运算符的解释/有效性。示例:C,Java,C ++,ML,Haskell
动态类型化 - 值具有与之关联的类型,并且该类型在运行时确定运算符的解释/有效性。示例:LISP,Scheme,Smalltalk,Ruby,Python,Javascript
据我所知,所有动态类型语言都是类型安全的 - 即只有有效的运算符才能对值进行操作。但对于静态类型的语言来说,情况并非如此。根据所使用的类型系统的功率,可能仅在运行时检查某些运算符,或者根本不检查某些运算符。例如,大多数静态类型语言不能正确处理整数溢出(添加2个正整数可以产生负整数),并且根本不检查超出范围的数组引用(C,C ++)或仅在运行。此外,某些类型系统非常弱,以至于有用的编程需要使用转义符号(C和系列中的转换)来更改表达式的编译时类型。
所有这些都导致了荒谬的主张,例如C ++比Python更安全,因为它是(静态类型的),而事实是Python本质上是安全的,而你可以用C ++射击你的腿。
答案 7 :(得分:1)
我不是计算机科学家,但如果“无类型”真的被用作CS社区中“动态类型”的同义词(至少在科学出版物中),我会感到非常惊讶,因为这两个术语描述了不同的概念。动态类型语言具有类型的概念,并且它在运行时强制执行类型约束(例如,您不能将整数除以Lisp中的字符串而不会出现错误),而无类型语言则没有任何类型的概念全部(例如汇编程序)。甚至维基百科关于编程语言的文章(http://en.m.wikipedia.org/wiki/Programming_language#Typed_versus_untyped_languages)也做出了这种区分。
更新:也许这种混淆来自于一些文本在Javascript中说“变量没有输入”的事实(这是真的)。但这并不意味着语言是无类型的(这将是错误的)。
答案 8 :(得分:1)
同意布兰登 - 背景就是一切。
我的看法:
我记得大约在2004年感到困惑,因为有关于Ruby是无类型还是动态类型的争论。旧学校的C / C ++人(我是其中之一)正在考虑编译器,并说Ruby是无类型的。
请记住,在C中,没有运行时类型,只有地址,如果正在执行的代码决定将该地址处的任何内容视为不是,那就是哎呀。这绝对是无类型的,与动态类型非常不同。
在那个世界里,“打字”就是编译器。 C ++具有“强类型”,因为编译器的检查更加严格。 Java和C更“弱类型”(甚至有关于Java是强类型还是弱类型的争论)。动态语言在这个连续统一体中是“无类型的”,因为它们没有编译器类型检查。
今天,对于练习程序员,我们已经习惯了动态语言,我们显然认为无类型意味着没有编译器或解释器类型检查,这将是非常难以调试。但在那里有一段时间并不明显,而在CS的理论世界中甚至可能没有意义。
从某种深层意义上讲,没有任何东西可以无类型(或者几乎没有任何东西),因为你必须有一些操作值来编写有意义的算法。这是理论CS的世界,它没有涉及如何为给定语言实现编译器或解释器的细节。因此,“无类型”(可能,我不知道)在这种情况下完全没有意义。