【问题标题】:Uses for Dynamic Languages动态语言的用途
【发布时间】:2010-10-04 09:14:30
【问题描述】:

我现在的主要语言是 D,我正在学习 Python,因为它是我正在学习的课程所必需的。虽然我理解为什么动态语言对于在没有类型推断或模板的情况下使用静态语言进行编程的人们来说是一股新鲜空气(恕我直言,模板在很大程度上是编译时的鸭子类型),但我很好奇动态语言有什么好处即使你有这些。

最重要的是,如果我要学习 Python,我希望以一种真正改变我对编程的想法的方式来学习它,而不仅仅是用 Python 编写 D。我没有使用过动态语言,因为我是一个相当新手的程序员,无法欣赏它们应该提供的灵活性,并且现在想学习充分利用它们。什么可以在动态类型的解释语言中轻松/优雅地完成,而在静态语言中却很尴尬或不可能,即使使用模板、多态性、静态类型推断,也许还有运行时反射?

【问题讨论】:

  • 如果你想改变你的想法,试着学习一门函数式编程语言。想到 Haskell/Lisp/Erlang。

标签: python programming-languages language-design dynamic-languages duck-typing


【解决方案1】:

看看这个e4x JavaScript 示例:

var sales = <sales vendor="John">
    <item type="peas" price="4" quantity="6"/>
    <item type="carrot" price="3" quantity="10"/>
    <item type="chips" price="5" quantity="3"/>
  </sales>;

alert( sales.item.(@type == "carrot").@quantity );
alert( sales.@vendor );
for each( var price in sales..@price ) {
  alert( price );
}

特别是看一行:

alert( sales.item.(@type == "carrot").@quantity );

在典型的静态语言中,您不会编写 sales.item,因为直到运行时您才能知道 item 是 sales 的属性。 这不仅限于 e4x。在编写 SOAP 客户端或任何其他直到运行时才知道的底层类型时,您可以在连接时以类似的风格进行编程。 在静态语言中,您通常需要运行一个以非常冗长的方式生成存根类或程序的工具。然后,如果 Web 服务发生变化,您需要重新生成存根。看一下java DOM代码:

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

public class Foo {

    public Document createDocument() {
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement( "root" );

        Element author1 = root.addElement( "author" )
            .addAttribute( "name", "James" )
            .addAttribute( "location", "UK" )
            .addText( "James Strachan" );

        Element author2 = root.addElement( "author" )
            .addAttribute( "name", "Bob" )
            .addAttribute( "location", "US" )
            .addText( "Bob McWhirter" );

        return document;
    }
}

绝对比您的动态代码详细得多。而且,当然,它不是静态类型的。在运行之前,无法检查您是否将“作者”拼写为“作者”。所有这些冗长的内容本质上是为了让您以静态风格捕捉本质上是动态的东西。

我认为这是动态语言的优点之一。

【讨论】:

    【解决方案2】:

    Python 示例:

    def lengths(sequence):
        try:
            return sum(len(item) for item in sequence)
        except TypeError:
            return "Wolf among the sheep!"
    
    >>> lengths(["a", "b", "c", (1, 2, 3)])
    6
    >>> lengths( ("1", "2", 3) )
    'Wolf among the sheep!'
    

    你认为这花了我多长时间,以及多少个编译-运行-调试周期?

    如果您认为我的示例微不足道,我可以回答说动态语言使许多编程任务变得微不足道。

    【讨论】:

      【解决方案3】:

      我想说的是闭包,但发现 this thread...(不是说我理解它在“静态”语言中是如何工作的)

      相关概念是functions-as-first-class-objectshigher-order procedures。 (例如,将函数作为输入和/或返回函数作为输出的函数)

      编辑:(这里的挑剔者)我会回应我在@David Locke 的帖子上发表的评论。动态解释的语言可以将现有的软件程序/项目与临时创建的小功能或类结合使用,以交互方式探索某些东西。最好的例子可能是函数图。如果我用 graph(f,xmin,xmax) 函数编写了一个函数图形对象,我可以用它来探索像 x2 或 sin(x) 之类的函数。我一直在 MATLAB 中这样做;它被解释并具有匿名函数 (@(x) x^2),可以在解释器提示下构造这些函数以传递给高阶函数(图形函数、导数运算符、根查找器等)。

      【讨论】:

      • 绝对可以用静态类型语言(例如 Haskell、ML)完成。
      • 嘿,我从来没有说过他们不可能做到。 :( 阅读 OP 的帖子,他问什么可能很尴尬。静态类型也只是问题的一部分,解释与编译是另一半。
      • 这个答案更倾向于提到函数式编程语言的特性,可以是动态的也可以是静态的。
      • 这与解释/编译无关。您可以在任一实现中使用闭包。而且它们在静态类型语言中并不尴尬。是的,它们在 C# 中很尴尬,但这不是一种函数式语言。查看 Haskell/ML 了解真正的函数式编程。
      【解决方案4】:

      关键是,在动态语言中,您可以比在静态类型语言中更快地实现相同的功能。因此,生产率通常要高得多。

      原则上,模板或多态之类的东西给了你很大的灵活性,但你必须编写大量代码才能使其工作。在动态语言中,这种灵活性几乎是免费的。

      所以我认为您以错误的方式看待差异,生产力确实是这里的重点(就像垃圾收集提高生产力一样,但实际上并不能真正让您做新的事情)。

      【讨论】:

      • 将“通常”替换为“可以说”,我可能会同意这个论点。具有良好类型系统和推理的静态类型语言不会为编写代码增加太多开销,根据我的经验,花在类型设计上的时间比不花时间跟踪类型系统可以弥补的错误还多避免。以及编译器辅助重构。
      【解决方案5】:

      使用对象时动态类型化的一大优点是,当您希望多个类具有相同的接口时,您不再需要使用类层次结构 - 这或多或少就是所谓的鸭子打字。糟糕的继承很难在之后修复 - 这使得重构通常比使用 Python 之类的语言更难。

      【讨论】:

        【解决方案6】:

        “我很好奇有什么好处 即使你有动态语言 那些。”

        与 D 编程语言相比:

        • Python 是一种更紧凑的语言。它允许您表达与 D 一样多的内容,但它使用更少的不同概念来实现它——少即是多

        • Python 有一个强大的标准库——包括电池

        我不知道 D 是否有交互式提示,但在 Python 中,ipython 等交互式 shell 是开发过程的一个组成部分。

        【讨论】:

        • 虽然“少得多”在技术上应该是“少得多”,但要挑剔:)
        【解决方案7】:

        当效率和类型安全是优先事项时,往往会使用编译语言。否则我想不出任何人不使用 ruby​​ 的任何理由 :)

        【讨论】:

          【解决方案8】:

          我发现像 Perl 这样的动态语言以及在较小程度上 Python 允许我为我需要做的事情编写快速而肮脏的脚本。动态语言的运行周期要短得多,并且通常需要编写的代码比使用静态类型语言要少得多,这提高了我的工作效率。不幸的是,这是以可维护性为代价的,但这是我用动态语言而不是它们本身的语言编写程序的方式的错误。

          【讨论】:

            【解决方案9】:

            我实际上为此写了一篇博文:linky。不过那篇帖子基本上可以这样概括:

            您会惊讶于不必在编译时命名您的变量是什么类型是多么令人费解的事情。因此,python 往往是一种非常高效的语言。

            另一方面,即使有好的单元测试,你也会对你允许自己犯的愚蠢错误感到惊讶。

            【讨论】:

            • 我有点粗心和健忘,所以我的动态语言脚本容易出错。其他有内部纪律不犯这些错误的人可能不同意。
            • @MarcusDowning 我是同一类型。我曾经是一名 C# 程序员,在那里我发现很难做一些神奇而棘手的事情。 C# 属性看起来类似于 Python 装饰器,但很难使用。不能为这些目的使用反射。在我转向 Python 之后,我就像“哇!”然后我意识到我花了更多的时间来调试我的愚蠢错误。许多错误被带到了运行时。我们有相当好的单元测试,但仍然..uugh
            【解决方案10】:

            理论上,动态语言无能为力,而静态语言则无能为力。聪明人为制作非常好的动态语言付出了很多努力,导致目前人们认为动态语言领先而静态语言需要迎头赶上。

            随着时间的推移,这将转向另一个方向。各种静态语言已经有:

            • 泛型,通过让静态类型在传递对象时选择正确的类型来减少静态类型的愚蠢,从而使程序员不必自己进行强制转换

            • 类型推断,无需浪费时间编写应该显而易见的内容

            • 闭包,其中许多有助于将机制与意图分开,让您将复杂的算法从大部分现有成分中整合在一起。

            • 隐式转换,可让您模拟“猴子修补”,而没有通常涉及的风险。

            • 代码加载和对编译器的轻松编程访问,因此用户和第三方可以编写您的程序。谨慎使用!

            • 更有利于在其中创建领域特定语言的语法。

            ...毫无疑问还有更多。动态运动催生了静态语言设计的一些有趣发展,我们都从竞争中受益。我只希望这些功能能够成为主流。

            有一个地方我没有看到主要的动态语言被替换,那就是浏览器中的 Javascript。现有市场有太多需要替代,因此重点似乎是让 Javascript 本身变得更好。

            【讨论】:

            • 顺便提一下,ECMA 希望在未来的 JavaScript 版本中实现一些静态功能。
            • 不错。遗憾的是,这些功能需要这么多年才能过滤到已安装浏览器的空间中。
            【解决方案11】:

            在动态语言中,您可以以您认为正确的方式使用值。在静态类型语言中,您只能以编译器知道正确的方式使用值。你需要你提到的所有东西来重新获得被类型系统带走的灵活性(我不是在抨击静态类型系统,灵活性经常被带走是有充分理由的)。如果您想以语言设计者未预料到的方式使用值(例如,将不同类型的值放入哈希表中),那么您不必在动态语言中处理这些复杂性。

            所以并不是说你不能在静态类型语言中做这些事情(如果你有运行时反射),只是更复杂。

            【讨论】:

              【解决方案12】:

              Here's Steve Yegge 关于这个主题。

              Guido van Rossum 在his take of Scala 中也与该演讲相关。

              【讨论】:

                【解决方案13】:

                使用动态语言,拥有命令行解释器要容易得多,这样您就可以在命令行上进行测试,而不必担心编译步骤来查看它们是否有效。

                【讨论】:

                • 或与编译的东西交互,例如写一个你一时冲动输入的快速函数,并将其作为参数传递给将函数作为输入的东西。图表就是一个很好的例子。
                • OCaml 和 F# 为原型代码提供了 REPL,两者都是静态类型语言。这也很整洁:ffconsultancy.com/products/fsharp_for_visualization/demo2.html
                猜你喜欢
                • 2011-04-15
                • 1970-01-01
                • 2011-01-13
                • 1970-01-01
                • 2011-05-13
                • 2011-02-10
                • 2010-10-05
                • 1970-01-01
                • 2021-12-10
                相关资源
                最近更新 更多