dynamictypes语言与静态types语言

与静态types语言相比,dynamictypes语言的优点和局限性是什么?

另请参见 : 什么是dynamic语言的爱 (一个更有争议的线程…)

解释器推导types和types转换的能力使得开发时间更快,但是它也可能引发运行时失败,在编译时你无法获得静态types的语言。 但是哪一个更好(或者哪怕总是这样)在当今社区(以及很长一段时间)都受到热烈的讨论。

这个问题很好解决

静态types的支持者认为,静态types的优点包括更早的编程错误检测(例如,防止向布尔值添加整数),以types签名的forms更好的文档(例如在parsing名称时包含参数的数量和types),更多编译器优化的机会(例如,当接收器的确切types被静态地知道时,通过直接调用来replace虚拟调用),增加的运行效率(例如,不是所有的值都需要携带dynamictypes)以及更好的devise时间开发者经验接收者的types,IDE可以显示所有适用成员的下拉菜单)。 静态打字狂热者试图让我们相信“精心打造的程序不会出错”。 虽然这听起来令人印象深刻,但这是一个相当空洞的声明。 静态types检查是程序的运行时行为的编译时抽象,因此它只是部分声音和不完整的。 这意味着程序仍然可能因为没有被types检查器跟踪的属性而出错,并且有程序在不能错误的情况下不能被types检查。 由于“幻像types”[11]和“抖动types”[10]等概念的出现,使得静态types更加局部和更完整的冲动导致types系统变得过于复杂和异乎寻常。 这就好比试图用一个绑在你腿上的球和链子跑马拉松,然后高兴地大声说,即使你在第一英里之后,你已经保释了,你几乎可以做到这一点。

dynamictypes语言的倡导者认为,静态types过于僵化,dynamic语言的柔和性使其非常适合于具有变化或未知需求的原型系统,或者与其他不可预测变化的系统(数据和应用程序集成)进行交互。 当然,dynamictypes语言对于处理真正的dynamic程序行为是必不可less的,如方法拦截,dynamic加载,移动代码,运行时reflection等。在所有关于脚本的论文[16]中,John Ousterhout认为静态types系统编程语言使得代码不像dynamictypes的脚本语言那样可重复使用,更加冗长,不是更安全,expression力也更弱。 这个论点是由许多dynamictypes脚本语言的支持者字面上的parroted。 我们认为这是一个谬误,属于同一类别,认为声明式编程的本质就是取消分配。 或者如约翰·休斯(John Hughes)所说[8],通过省略特征使语言变得更加强大是不可能的。 捍卫延迟所有types检查到运行时间的事实是一件好事,是玩鸵鸟的策略,错误应该在开发过程中尽早捕捉的事实。

静态types系统试图静态地消除某些错误,在不运行的情况下检查程序,并试图在某些方面certificate正确性。 一些types系统能够比其他types捕获更多的错误。 例如,C#在正确使用时可以消除空指针exception,而Java则没有这种function。 Twelf有一个types系统实际上保证certificate将会终止 ,“解决” 停止问题 。

但是,没有一个types系统是完美的。 为了消除一类特定的错误,他们还必须拒绝某些违反规则的完全有效的程序。 这就是为什么Twelf不能真正解决暂停问题的原因,它只是通过抛出大量完全有效的certificate,而这些certificate恰好以奇怪的方式终止,从而避免了这个问题。 同样,由于使用了异构数组,Java的types系统拒绝了Clojure的PersistentVector实现。 它在运行时工作,但types系统无法validation它。

出于这个原因,大多数types系统提供了“转义”,这是覆盖静态检查器的方法。 对于大多数语言来说,这些都采用了铸造的forms,虽然有些(如C#和Haskell)具有标记为“不安全”的整个模式。

主观上,我喜欢静态打字。 如果执行得当(提示: 不是 Java),静态types系统可以在错误消除生产系统之前清除错误。 dynamictypes的语言往往需要更多的unit testing,在最好的时候是单调乏味的。 另外,静态types语言可以具有某些在dynamictypes系统中不可能或不安全的特征( 隐式转换可以放在心上)。 这是一个需求和主观品味的问题。 我不会在Ruby中构build下一个Eclipse,而是尝试在Assembly中编写备份脚本或使用Java修补内核。

噢,那些说“ x打字比打字十倍”的人只是吹烟。 dynamic打字在许多情况下可能会“感觉”更快,但是一旦你真的试图让你的应用程序运行 ,就会失去动力。 同样,静态types可能看起来就像是完美的安全网,但是看一下Java中一些更复杂的genericstypes定义会让大多数开发人员都为眼花缭乱而忙碌。 即使是types系统和生产力,也没有银弹。

最后说明:比较静态和dynamictypes时,不要担心性能。 像V8和TraceMonkey这样的现代JIT正在危险地接近静态的语言performance。 而且,Java实际上编译成一种内在dynamic的中间语言的事实应该暗示,在大多数情况下,dynamictypes并不是一些人所认为的巨大的性能杀手。

那么,这两个都是非常非常非常非常被误解,也是两个完全不同的东西。 这不是相互排斥的

静态types是对语言的语法的限制。 静态types的语言严格来说可以说是不是上下文无关的。 简单的事实是,在上下文无关的语法中理性地expression一种语言会变得不方便,因为它不会将所有的数据简单地视为位向量。 静态types系统是语言语法的一部分(如果有的话),它们只是限制它超过上下文无关的语法,因此语法检查发生在源代码的两次传递中。 静态types对应于types理论的math概念,math中的types理论只是限制了一些expression式的合法性。 就像我在math中不能说3 + [4,7] ,这是因为它的types理论。

因此,静态types不是从理论的angular度来“防止错误”的方法,它是语法的一个限制。 事实上,假设+,3和区间具有通常的集合理论定义,如果我们删除types系统3 + [4,7]有一个相当明确定义的结果集合。 “运行时types错误”在理论上是不存在的,types系统的实际使用是为了防止对人类的操作是没有意义的。 当然,操作仍然只是移位和操纵位。

这个问题的答案是,一个types系统不能决定这样的操作是否会发生,如果允许运行的话。 如在,精确地分割所有可能的程序中的那些将有“types错误”,那些不是。 它只能做两件事:

1:certificatetypes错误将在程序中发生
2:certificate他们不会发生在一个程序中

这可能看起来像我自相矛盾。 但是C或者Javatypes的检查器所做的是拒绝程序为“非语法的”,或者如果程序在2时不能成功,则称之为“types错误”。它不能certificate它们不会发生,这并不意味着他们不会发生,只是意味着它不能certificate这一点。 很可能是一个没有types错误的程序被拒绝,因为它不能被编译器certificate。 if(1) a = 3; else a = "string"; if(1) a = 3; else a = "string"; ,因为它总是正确的,else-branch将永远不会在程序中执行,并且不会发生types错误。 但是不能以一般的方式来certificate这些情况,所以被否决了。 这是很多静态types语言的主要弱点,为了保护你免受自己的侵害,在不需要的情况下,你也必须受到保护。

但是,与普遍认为的相反,也有一些静态types的语言按原则1工作。他们只是拒绝所有可以certificate会导致types错误的程序,并且通过所有不能使用的程序。 所以有可能他们允许在其中有types错误的程序,一个好的例子是Typed Racket,它是dynamic和静态types之间的混合体。 有些人会说,你在这个系统中得到两全其美的好处。

静态types的另一个优点是types在编译时已知,因此编译器可以使用它。 如果我们在Java中做"string" + "string"或者3 + 3 ,那么最后文本中的两个+标记代表一个完全不同的操作和数据,编译器知道从哪个types中select哪一个。

现在,我要在这里发表一个非常有争议的声明,但是却没有提到: “dynamicinput”不存在

听起来很有争议,但确实如此,dynamictypes语言从理论angular度来看是无types的 。 它们只是一种types的静态types语言。 或者简单地说,它们是在实践中由上下文无关语法在语法上确实生成的语言。

为什么他们没有types? 因为每个操作都是在每个操作符上定义和允许的,所以“运行时types错误”到底是什么? 这纯粹是一个副作用的理论范例。 如果print("string")是一个操作,那么length(3)length(3) ,前者有写string的副作用标准输出,后者只是error: function 'length' expects array as argument. , 而已。 从理论上讲,没有dynamictypes的语言。 他们是无types的

好的,“dynamicinput”语言的明显优势是performance力,一种types系统无非是performance力的限制。 一般来说,如果types系统被忽略,那么具有types系统的语言确实会对所有那些不被允许的操作有一个定义的结果,结果对人类来说是没有意义的。 许多语言在应用types系统后会失去图灵的完整性。

显而易见的缺点是操作可能发生,这会产生对人类无意义的结果。 为了防止这种情况发生,dynamictypes语言通常会重新定义这些操作,而不是产生这种无意义的结果,而是将其重新定义为具有写出错误的副作用,并可能完全停止该程序。 这根本不是一个“错误”,事实上,语言规范通常暗示了这一点,从理论的angular度来看,这与语言打印string的行为一样多。 因此,types系统迫使程序员推理代码的stream程,以确保不会发生这种情况。 或者的确,理由使得它确实发生也可以在debugging的某些方面得心应手,表明它不是一个“错误”,而是一个明确定义的语言属性。 实际上,大多数语言所具有的“dynamicinput”的单一残留是防止零分。 这是什么dynamictypes是,没有types,没有更多的types比零是一个不同于所有其他数字的types。 人们称之为“types”只是数据的另一个属性,如数组的长度或string的第一个字符。 许多dynamictypes的语言也允许你写出"error: the first character of this string should be a 'z'"

另一件事是dynamictypes的语言在运行时具有可用的types,通常可以检查它并处理它并从中作出决定。 当然,从理论上说,访问数组的第一个字符并查看它是什么并没有什么不同。 事实上,你可以创build自己的dynamicC,只使用long longtypes的一个types,并使用它的前8位来存储你的'types',并相应地写入相应的函数来检查它,并执行浮点或整数加法。 你有一种types的静态types语言,或者一种dynamic语言。

在实践中,静态types语言通常用于编写商业软件,而dynamictypes语言通常用于解决某些问题和自动执行某些任务。 用静态types语言编写代码只需要很长的时间,而且很麻烦,因为你不能做那些你知道会好的事情,但是types系统仍然可以保护你免受你自己犯的错误的困扰。 许多编程人员甚至不知道他们这样做,因为它在系统中,但是当你使用静态语言编写代码时,你经常会考虑types系统不会让你做不会出错的事情,因为它不能certificate它不会出错。

正如我所指出的,“静态types”一般意味着情况2,直到certificate无罪才有罪。 但是一些语言,从types理论中根本不能派生出他们的types系统,使用规则1:无辜的,直到certificate有罪,这可能是理想的混合。 所以,也许types球拍是给你的。

另外,对于一个更荒谬和极端的例子,我目前正在实现一种语言,其中“types”是真正的数组的第一个字符,它们是数据,“types”,“types”一个types和数据,唯一的数据本身就是一个types。 types不是有限的或者是静态的,但是可以基于运行时信息生成新的types。

也许dynamic分类的最大“好处”是更浅的学习曲线。 没有types系统可以学习,也没有types约束等angular落案例的非平凡语法。 这使得更多的人可以访问dynamic打字,对于那些复杂的静态types系统遥不可及的人来说,这种打字是可行的。 因此,dynamictypes在教育(例如MIT的Scheme / Python)以及非程序员(例如Mathematica )的领域特定语言的情况下已经得到了应用。 dynamic语言也已经在很less或者没有竞争的领域(比如Javascript)中占据一席之地。

最简洁的dynamictypes语言(例如Perl,APL,J,K, Mathematica )是领域特定的,并且可以比最简洁的通用静态types语言(例如OCaml ) 。

dynamictypes的主要缺点是:

  • 运行时types错误。

  • 要达到同一水平的正确性,并且需要大量的testing,可能非常困难甚至几乎不可能。

  • 没有编译器validation的文档。

  • 性能差(通常在运行时,但有时在编译时,例如斯大林计划),由于依赖于复杂的优化,性能不可预知。

就我个人而言,我是在dynamic语言的基础上成长起来的,但是除非没有其他可行的select,否则他们不会像专业人士那样用40英尺的杆子来触摸它们

从Artima的打字:强与弱,静态与dynamic文章:

强打字可防止不匹配types之间的混合操作。 为了混合types,您必须使用显式转换

弱types意味着你可以混合types而不需要明确的转换

在Pascal Costanza的论文“ Dynamic vs. Static Typing – 基于模式的分析” (PDF)中,他声称在某些情况下,静态types比dynamictypes更容易出错。 一些静态types的语言迫使你手动模拟dynamicinput,以做“正确的事情”。 这是在最终的Lambda讨论。

这取决于上下文。 有很多好处,适合dynamictypes系统以及强types。 我认为dynamictypes语言的stream动更快。 dynamic语言不受类属性和编译器对代码中发生的事情的限制。 你有一些自由。 而且,dynamic语言通常更具performance力,导致代码less,效果好。 尽pipe如此,它更容易出错,这也是有问题的,更多地取决于unit testing覆盖。 dynamic朗易于原型,但维护可能会变成噩梦。

静态types系统的主要收益是IDE支持和可靠的静态代码分析器。 每次更改代码后,您对代码更有信心。 用这些工具维护是蛋糕的安宁。

关于静态和dynamic语言有很多不同的东西。 对我来说,主要的区别是在dynamic语言中variables没有固定的types; 相反,这些types是与价值联系在一起的。 正因为如此,直到运行时才确定执行的确切代码。

在早期或幼稚的实现中,这是一个巨大的性能拖延,但现代JIT非常接近于通过优化静态编译器所能获得的最佳效果。 (在一些情况下,甚至比这更好)。

这是所有关于这个工作的正确工具。 100%的时间都不是好的。 这两个系统都是由人创造的,有缺陷。 对不起,但我们吮吸和制作完美的东西。

我喜欢dynamic打字,因为它不在我的方式,但是运行时错误可以爬起来,我不打算。 静态types可以解决上述错误,但是驱动一个新手(用types语言)程序员疯狂地试图在一个常量字符和一个string之间进行转换。

静态types: Java和Scala等语言是静态types的。

variables必须在代码中使用之前进行定义和初始化。

例如。 int x; x = 10;

的System.out.println(X);

dynamicinput: Perl是一种dynamicinput语言。

variables在用于代码之前不需要初始化。

Y = 10; 在代码后面的部分使用这个variables