首页 文章

动态类型语言与静态类型语言

提问于
浏览
200

与静态类型语言相比,动态类型语言的优点和局限是什么?

See alsowhats with the love of dynamic languages(一个更具争议性的话题......)

9 回答

  • 0

    解释器推断类型和类型转换的能力使开发时间更快,但它也可能引发运行时故障,而这些故障是您无法在编译时捕获它们的静态类型语言中获得的 . 但是这些天(以及很长一段时间以来)在社区中热烈讨论哪一个更好(或者即使总是如此) .

    关于这个问题的一个很好的解决方案是来自微软的Erik Meijer和Peter Drayton的Static Typing Where Possible, Dynamic Typing When Needed: The End of the Cold War Between Programming Languages

    静态类型的倡导者认为静态类型的优点包括早期检测编程错误(例如,防止向布尔添加整数),以类型签名的形式提供更好的文档(例如,在解析名称时合并参数的数量和类型),更多编译器优化的机会(例如,当静态地知道接收器的确切类型时通过直接调用替换虚拟调用),提高运行时效率(例如,并非所有值都需要携带动态类型),以及更好的设计时开发人员体验(例如,了解接收器的类型后,IDE可以显示所有适用成员的下拉菜单 . 静态打字狂热者试图让我们相信“打字好的程序不会出错” . 虽然这听起来确实令人印象深刻,但这是一个相当空洞的陈述 . 静态类型检查是程序运行时行为的编译时抽象,因此它必然只是部分完整和不完整 . 这意味着程序仍然可能出错,因为类型检查器没有跟踪属性,并且有些程序虽然不会出错但却无法进行类型检查 . 使静态类型不那么局部和更完整的冲动导致类型系统变得过于复杂和异国情调,如“幻影类型”[11]和“摇摆类型”[10]等概念所证明的那样 . 这就像试图跑马拉松,球和链绑在你的腿上,胜利地喊着,即使你在第一英里后拯救出来,你几乎已经成功了 . 动态类型语言的倡导者认为静态类型过于僵化,动态语言的柔和性使它们非常适合具有变化或未知需求的原型系统,或者与其他不可预测变化的系统(数据和应用程序集成)交互 . 当然,动态类型语言对于处理真正动态的程序行为是不可或缺的,例如方法拦截,动态加载,移动代码,运行时反射等 . 在所有关于脚本的论文的母亲[16]中,John Ousterhout认为静态类型系统与动态类型的脚本语言相比,编程语言使代码更易于重用,更冗长,更安全,更不具表现力 . 许多动态类型脚本语言的支持者从字面上看这个论点 . 我们认为这是一个谬论,并且与声明声明性编程的本质是消除任务有关 . 或者正如John Hughes所说[8],通过省略特征使语言更强大是不可能的 . 捍卫将所有类型检查延迟到运行时这一事实是一件好事,正在玩鸵鸟战术,因为错误应尽可能早地在开发过程中被捕获 .

  • 2

    静态类型系统试图静态地消除某些错误,检查程序而不运行它并试图在某些方面证明健全性 . 某些类型系统能够捕获比其他系统更多的错误 . 例如,如果使用得当,C#可以消除空指针异常,而Java没有这种能力 . Twelf有一个类型系统,实际上是guarantees that proofs will terminate3041911 .

    但是,没有类型系统是完美的 . 为了消除特定类别的错误,他们还必须拒绝某些违反规则的完全有效的程序 . 这就是为什么Twelf没有't really solve the halting problem, it just avoids it by throwing out a large number of perfectly valid proofs which happen to terminate in odd ways. Likewise, Java'类型系统拒绝Clojure的 PersistentVector 实现,因为它使用了异构数组 . 它在运行时工作,但类型系统无法验证它 .

    因此,大多数类型系统提供“转义”,即覆盖静态检查器的方法 . 但是对于大多数语言来说,这些都采用了铸造的形式一些(如C#和Haskell)具有标记为“不安全”的整个模式 .

    主观上,我喜欢静态打字 . 正确实现(提示:不是Java),静态类型系统可以在错误消除 生产环境 系统之前清除错误 . 动态类型语言往往需要更多的单元测试,这在最好的时候是乏味的 . 此外,静态类型语言可能具有某些功能,这些功能在动态类型系统中是不可能的或不安全的(implicit conversions spring to mind) . 这都是要求和主观品味的问题 . 我不会在Ruby中构建下一个Eclipse,而不是尝试在Assembly中编写备份脚本或使用Java修补内核 .

    哦,有人说“在很多情况下,x打字比y打字_3041925感觉”快10倍,但是一旦你真正尝试让你的花哨的应用程序运行,它就会失去理智 . 同样,静态类型可能看起来像是完美的安全网,但是看一下Java中一些更复杂的泛型类型定义会让大多数开发人员为眼罩而烦恼 . 即使使用类型系统和 生产环境 力,也没有银弹 .

    最后注意事项:在比较静态和动态类型时,不要担心性能 . 像V8和TraceMonkey这样的现代JIT正在危险地接近静态语言性能 . 此外,Java实际上编译成一种固有的动态中间语言这一事实应该暗示,在大多数情况下,动态类型并不是某些人成功实现的巨大性能杀手 .

  • 44

    嗯,两者都非常非常非常被误解,也有两个完全不同的东西 . that aren't mutually exclusive .

    静态类型是语言语法的限制 . 严格地说,静态类型语言可以说不是无上下文的 . 简单的事实是,在数学中没有说出语境的语境中表达一种语言是不方便的,这是因为它的类型理论 .

    因此,从理论的角度来看,静态类型不是一种方法,它们是语法的限制 . 实际上,假设3和区间具有通常的设定理论定义,如果我们删除类型系统 3 + [4,7] 具有非常明确的结果's a set. '运行时类型错误' theoretically do not exist, the type system'的实际用途是防止对人类的操作毫无意义 . 当然,操作仍然只是转移和操纵位 .

    对此的关注是类型系统无法决定是否允许运行此类操作 . 就像在,将所有可能程序的集合完全划分为那些将出现“类型错误”的程序,以及那些不具有“类型错误”的程序 . 它只能做两件事:

    1:证明类型错误将在程序中发生
    2:证明它们不会出现在程序中

    如果它在2处不能成功,这可能看起来像是错误的'它会发生,它不会发生,它只是意味着它可以被编译器证明 . 一个简单的例子是 if(1) a = 3; else a = "string"; ,当然,因为它以一般方式证明了这些情况,所以在你不需要它的情况下它也必然受到保护 .

    但是,与普遍认为的相反,也存在按原则1工作的静态类型语言 . 它们只是拒绝所有可以证明它会导致类型错误的程序,并且通过所有不能执行的程序 . 所以它们可能允许在其中包含类型错误的程序,一个很好的例子是Typed Racket,它是动态和静态类型之间的混合 . 有些人会说你在这个系统中得到了两全其美 .

    静态类型的另一个优点是类型在编译时是已知的,因此编译器可以使用它 . 如果我们在Java中做 "string" + "string"3 + 3 ,最后文本中的 + 标记都表示完全不同的操作和数据,编译器知道从单独的类型中选择哪个 .

    现在,我将在这里发表一个非常有争议的声明,但请耐心等待: 'dynamic typing' does not exist .

    听起来很有争议,但确实如此,动态类型语言是从理论角度来看的 . 它们只是静态类型语言,只有一种类型 . 或者简单地说,它们是在实践中通过无上下文语法确实语法生成的语言 .

    为什么要't they have types? Because every operation is defined and allowed on every operant, what'确切地说'runtime type error'?来自于理论上的例子纯粹是副作用 . 如果执行 print("string") 打印字符串是一个操作,那么 length(3) ,前者有将 string 写入标准输出的副作用,后者只是 error: function 'length' expects array as argument. ,就是这样 . 从理论的角度来看,没有动态类型语言这样的东西 . 他们是无类型的

    好吧,“动态类型”语言的明显优势是表达能力,类型系统只不过是表达能力的限制 . 一般而言,如果类型系统被忽略,具有类型系统的语言确实会为所有那些不允许的操作定义结果,结果对人类没有意义 . 应用类型系统后,许多语言都失去了图灵的完整性 .

    明显的缺点是可能发生的操作会产生对人类无意义的结果 . 为了防范这种情况,动态类型语言通常会重新定义这些操作,而不是产生无意义的结果,而是将它重新定义为具有写出错误的副作用,并可能完全停止程序 . 这根本不是'error',事实上,语言规范通常暗示这一点,这与语言的行为一样,从理论的角度来打印字符串 . 类型系统因此迫使程序员推断代码流,以确保不会发生这种情况 . 或者实际上,它确实发生的原因在某些方面也可以派上用手进行调试,显示它是's not an '错误' at all but a well defined property of the language. In effect, the single remnant of '动态类型' that most languages have is guarding against a division by zero. This is what dynamic typing is, there are no types, there are no more types than that zero is a different type than all the other numbers. What people call a '类型'只是数据的另一个属性,如数组的长度,或者第一个字符一个字符串 . 许多动态类型语言也允许你写出像 "error: the first character of this string should be a 'z'" 这样的东西 .

    另一件事是动态类型语言在运行时具有可用的类型,通常可以检查它并处理它并从中做出决定 . 当然,理论上它与访问数组的第一个字符并查看它是什么没有什么不同 . 实际上,你可以创建自己的动态C,只使用一个类型,如long long int,并使用它的前8位来存储你的'type'并相应地写函数来检查它并执行浮点或整数加法 . 您有一种静态类型语言,只有一种类型或动态语言 .

    在实践中,所有显示,静态类型语言通常用于编写商业软件的上下文中,而动态类型语言倾向于在解决某些问题和自动化某些任务的上下文中使用 . 用静态类型语言编写代码只需要很长时间并且很麻烦,因为你不能做你知道的事情会好转,但类型系统仍会保护你免受你自己的错误 . 许多程序员甚至没有意识到他们这样做是因为它在他们的系统中,但是当你用静态语言编写代码时,你经常会解决类型系统不会让你做出不会出错的事情的事实,因为它无法证明它不会出错 .

    正如我所指出的,“静态打字”通常意味着案例2,在被证明无罪之前有罪 . 但是有些语言根本没有从类型理论中推导出它们的类型系统使用规则1:无辜者直到被证明有罪,这可能是理想的混合体 . 所以,也许Typed Racket适合你 .

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

  • 24

    也许动态打字的单一最大"benefit"是较浅的学习曲线 . 没有要学习的类型系统,也没有类型约束等极端情况的非平凡语法 . 这使得动态类型可以被更多人访问,并且对于许多人来说是可行的,对于那些复杂的静态类型系统是不可及的 . 因此,动态类型在教育的背景下(例如麻省理工学院的Scheme / Python)和非程序员的领域特定语言(例如Mathematica)已经流行起来 . 动态语言也在他们很少或没有竞争的利基(例如Javascript)中流行起来 .

    最简洁的动态类型语言(例如Perl,APL,J,K,Mathematica)是特定于域的,可以是比它们设计的利基中最简洁的通用静态类型语言(例如OCaml)更简洁 .

    动态类型的主要缺点是:

    • 运行时类型错误 .

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

    • 没有经过编译器验证的文档 .

    • 性能不佳(通常在运行时但有时在编译时,例如斯大林方案)和由于依赖于复杂的优化而导致的不可预测的性能 .

    就个人而言,我是在动态语言中长大的,但除非没有其他可行的选择,否则不会用40英尺杆作为专业人士 .

  • 11

    来自Artima的Typing: Strong vs. Weak, Static vs. Dynamic文章:

    强类型可防止不匹配类型之间的混合操作 . 为了混合类型,您必须使用显式转换弱类型意味着您可以在没有显式转换的情况下混合类型

    在Pascal Costanza的论文Dynamic vs. Static Typing — A Pattern-Based Analysis(PDF)中,他声称在某些情况下,静态类型比动态类型更容易出错 . 某些静态类型语言会强制您手动模拟动态类型以执行"The Right Thing" . 它在Lambda the Ultimate讨论过 .

  • 118

    这取决于背景 . 有很多好处适用于动态类型系统以及强类型系统 . 我认为动态类型语言的流程更快 . 动态语言不受类属性和编译器思考代码中发生的事情的约束 . 你有一些自由 . 此外,动态语言通常更具表现力,并且导致更少的代码,这是好的 . 尽管如此,它更容易出错,这也是值得怀疑的,更多地取决于单元测试覆盖 . 这是一个简单的原型与动态lang但维护可能成为噩梦 .

    静态类型系统的主要优势是IDE支持和肯定静态的代码分析器 . 每次代码更改后,您都会对代码更有信心 . 维护是这种工具的和平蛋糕 .

  • -3

    静态和动态语言有很多不同之处 . 对我来说,主要区别在于动态语言中的变量没有固定类型;相反,类型与值相关联 . 因此,在运行时之前,确定的执行代码是不确定的 .

    在早期或天真的实现中,这是一个巨大的性能拖累,但现代JIT与优化静态编译器所能达到的最佳接近 . (在某些边缘情况下,甚至比那更好) .

  • 0

    这一切都是关于工作的正确工具 . 100%的时间都不会更好 . 这两个系统都是由人创造的并且有缺陷 . 对不起,但我们很糟糕,做得很好 .

    我喜欢动态类型,因为它不受我影响,但是运行时错误可能会升级,我没有计划 . 静态类型可以解决上述错误,但驱动新手(在类型语言中)程序员疯狂尝试在常量字符串和字符串之间进行转换 .

  • 136

    Static Typing: Java和Scala等语言是静态类型的 .

    必须在代码中使用变量之前定义和初始化变量 .

    对于前int x; x = 10;

    的System.out.println(X);

    Dynamic Typing: Perl是一种动态类型语言 .

    在代码中使用变量之前,无需初始化变量 .

    Y = 10;在代码的后半部分使用此变量

相关问题