【问题标题】:How do you program differently in dynamic languages?您如何在动态语言中进行不同的编程?
【发布时间】:2023-03-10 20:49:01
【问题描述】:

真正知道如何利用动态编程语言的人与使用静态语言的人在编程方面有何不同?

我熟悉关于静态类型与动态类型的整个争论,但这不是我想要的。我想讨论在动态语言中实用但在静态语言中不实用的问题解决技术。

我见过的大多数用动态编程语言编写的代码与用静态编程语言编写的代码并没有太大区别。俗话说,你可以用任何语言写FORTRAN,很多人都这样做。但是有些人使用动态编程语言来解决问题,这种方式不容易转化为例如 C++。他们的一些技巧是什么?

有哪些很好的资源可以讨论如何使用动态编程语言?不是关于语言语法或 API 参考的书籍,而是关于利用动态语言功能解决问题的方法的资源。

编辑(2009 年 1 月 5 日):我很欣赏下面的答案,但它们似乎并没有解释动态语言倡导者所说的他们所经历的生产力的巨大提高。

【问题讨论】:

  • 为了它的价值,我写了一篇关于动态与静态类型习语主题的帖子:stackoverflow.com/questions/406760/…
  • 好问题+1!太糟糕了,它导致了乏味和无趣的答案。

标签: dynamic-languages


【解决方案1】:

我认为最显着的差异是数据结构的选择。

在 Java 或 C 中,我非常严格地定义结构或类。如果我需要添加属性,我会返回并更改定义。

在 Perl 中,我将只使用散列,并在编写代码时“发明”键。

【讨论】:

  • 如果不是因为 C++ 中的严格类型,使用 STL 映射来做到这一点是微不足道的。
  • 同样,在 Java 中您可以使用 HashMap - 但这不是一个好主意。类型检查是一个朋友。你在 Perl 中牺牲它来换取快速原型设计和语法糖。
  • @slim:我曾在 C++ 和 Perl 中广泛工作过,我认为类型检查是朋友。至少它存在于 C++ 中。
【解决方案2】:

我发现自己通常利用动态编程语言的一种方式是简化和澄清语法。例如,如果我代表一个数据库,如果我可以在数据库对象上动态加载其表的属性和方法、其列的表和行等,我用于与之交互的语法会更清晰.区别可能在于:

$row = $db->getTable('user')->getRow(27);
$row->setValue('name', 'Bob');

$row = $db->user->getRow(27);
$row->name = 'Bob';

当你做复杂的事情时,第二种形式的“视觉噪音节省”真的开始加起来了。

【讨论】:

    【解决方案3】:

    在动态语言中,我更具实验性。动态更改内容更容易,因此我可以更快地探索解决方案。

    如果我知道自己想做什么,以及通常如何去做,我喜欢 C++。如果我不知道如何做我想做的事,并且可能不完全确定我想做什么,我更喜欢 Lisp。

    【讨论】:

      【解决方案4】:

      动态语言能够执行在运行时创建的代码。如果注入恶意代码,这是非常危险的。但是,如果您可以净化环境,则非常强大。

      我认为 Javascript 人通过执行 JSON 文件来做到这一点。

      【讨论】:

      • 编程语言并非非黑即白。我可以轻松地执行在运行时使用 C# 创建的代码......但这既不是好的做法,C# 通常也不被认为是一种特别动态的语言。 Python 代码很少这样做,尽管它很容易做到这一点,但即使 Haskell 提供了动态解释器提示符,而且 Haskell 是一种比大多数语言更加静态的语言。
      【解决方案5】:

      快速迭代让程序员更快乐,而且它们的速度并不比交互式解释器快。良好的解释器开发可以同时为您提供沙盒、测试和原型设计。

      但是,请注意通过排列进行编程。我个人的经验法则是,它只是因为它有效并不意味着它已经准备好,当你能解释它为什么有效时,它就已经准备好了。

      【讨论】:

      • 请注意,静态类型的 Scala 确实有一个 REPL!
      【解决方案6】:

      我最大的收获是在数据库和对象之间的映射 (ORM)。

      如果没有类型的概念,那么将一行中的每一列分配给一个对象中的一个值就变得很容易了。当然,权衡是您认为存在的值类型与计算机执行的类型之间可能存在不匹配。

      【讨论】:

        【解决方案7】:

        更多库和更重要的更多可用库

        我的猜测是,通常与动态语言相关的“Duck Typing”有助于显着简化代码并使编写通用代码更加容易。您不受严格的类层次结构的限制,因此能够更轻松地将来自不同库的组件组合在一起。

        【讨论】:

          【解决方案8】:

          动态语言可以在运行时改变对象,可以添加方法、属性...

          动态语言魔法的一个很好的例子是这个 Groovy 代码 sn-p,它只用两行代码调用 web 服务上的方法:

          def proxy = new SoapClient("http://localhost:6980/MathServiceInterface?wsdl");
          def result = proxy.add(1.0, 2.0);
          

          这是另一个从 XML 中提取数据的 Groovy sn-p:

          def contacts = new XmlParser().parseText("<contacts><name>Bahaa Zaid</name></contacts>");
          def myName = contacts.name[0].text();
          

          您不能在静态语言中执行此操作。动态语言可以更改对象以反映实际的运行时条件。

          【讨论】:

            【解决方案9】:

            我喜欢苗条的回答。我确实在 Java 和 C++ 上花费了大量时间来制作 Python/Ruby 中免费的自定义数据结构。并制作专门的函数来处理这些自定义数据结构。是的,在 C++ 中,STL 非常好。是的,Java 中的泛型很好。它们有助于更快地创建自定义数据结构,但仍需要大量思考和考虑。

            但是,动态语言更易于使用还有一个更根本的原因。这是一个深刻的想法,称为鸭式打字。上面的一些 cmets 提到了鸭子类型,但请花时间思考一下鸭子类型是什么。这是一种完全不同的看待世界的方式。与 Java 和 C++ 等语言不兼容的视图。

            Duck 打字意味着您不会浪费时间来定义鸭子是什么。通过不必正式定义您的对象,您可以节省大量时间和精力。获得正确的定义很难。看看我的这篇博文,我举了一些例子:Formal definitions are less useful than you think

            Duck 打字已被证明非常有用。 "Must Ignore" principle in XML 是使 XML 在 Web 上如此重要和有用的原因。但这只是鸭子打字的一个例子。

            另一种表达鸭式打字的方式是网络口头禅“严格发送,接受慷慨”。这也是一个非常基本的想法。

            最后,您可能想回到我的一篇长博文,我在其中解释了鸭子类型以及它与 AI 和建模等事物的关系:Duck Typing, Artificial Intelligence and Philosophy

            【讨论】:

            • 鸭子打字!=动态打字。 OCaml 的结构类型是该语言中被低估的瑰宝之一,它或多或少是“静态类型语言的鸭子类型”。您必须不断在 Java 和 C++ 中重新实现数据结构,因为这些语言的类型系统非常糟糕(说真的,Java 中的泛型就是如此)。见en.wikipedia.org/wiki/Structural_type_system
            【解决方案10】:

            这归结为我最喜欢的比率之一:我花多少时间思考解决问题,与我花多少时间思考我用来解决问题的工具。将其视为等效于 S/N 比。

            使用鸭式语言(我认为这是最能帮助我提高工作效率的因素),我只是能够花更多时间思考我的问题及其解决方案(并编写专门解决这些问题的代码),而且我花费更少的时间来保持语言工件的正确性。

            还有很多我不写的代码,包括声明,尤其是类型转换。

            但这主要是让我的注意力集中在最佳位置。

            【讨论】:

              【解决方案11】:

              John,根据您对 09 年 1 月 5 日的更新编辑,您可能会发现 AMOP 是一本有趣的读物,还有更多您正在考虑的内容。它非常以 lisp 为中心,但毕竟许多好的动态想法都是从那里开始的。因此,如果您可以享受(或克服)该方面,作者确实讨论了需要并用于执行此类操作的动态方面。这是非常强大的东西。

              【讨论】:

                【解决方案12】:

                我没有具体的答案,只是一个建议:看看这本书“Design patterns in Ruby”:它涵盖了大多数经典设计模式(à la Gamma 等人,等等)并表达了它们,非常简洁,在 Ruby 中:)

                【讨论】:

                  【解决方案13】:

                  我现在不能引用这个(我的记忆力下降了),但我听说过一些类似的东西:

                  编程行业最接近灵丹妙药的是 托管语言——让程序员不必担心 内存管理的细节,让他们集中更多的精力 解决手头的问题。

                  所以,我可能会冒昧地猜测一下,与其说你的程序不同,你可以将更多的大脑用于“解决问题”,而不是解决方案的实现细节。

                  【讨论】:

                    【解决方案14】:

                    对我来说,这是周转速度。我使用的动态语言(目前是 Python 和一点 JavaScript)都是解释型的。这意味着我可以随时尝试。如果我想看看 API 的某些部分是如何运行的,我可以在解释器上花几分钟时间。

                    如果我想用像 C# 这样的语言做同样的事情,我必须启动 VS,创建一个项目,然后编译它。如果我想测试我正在开发的更大软件的一部分,我可能必须编译它,这可能需要很长时间。幸运的是,在 .Net 中,我可以从 IronPython 的大项目中加载程序集,并获得与解释语言相同的一些好处(即快速测试 API 的不同部分)。

                    【讨论】:

                    • REPL != 动态类型。恰当的例子:我在 F# 顶层中对我的所有 F# 代码进行原型设计,并且我喜欢使用 Haskell Prelude 来测试我的 Haskell 代码。
                    • 我确实提醒过它是 I 使用的动态语言。我可能是错的,但动态似乎通常与解释相结合。
                    【解决方案15】:

                    阅读 Mark Jason Dominus 的“Higher Order Perl”。它只讨论了 Perl,但它确实提供了对 Perl 来说很自然的技术,而在大多数静态语言中却不那么自然。

                    All languages obviously have their strengths and weaknesses and dymanic vs static 
                    

                    只是对语言进行分类的众多方法之一。我不会说动态语言作为一个整体比静态语言更好或更差。但是我觉得这本书 非常擅长展示使用 Perl 解决问题的不同方法 在大多数静态语言中很难或不可能。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-01-11
                      • 1970-01-01
                      • 2011-03-07
                      • 2021-12-13
                      • 2010-12-01
                      • 2011-06-06
                      • 2011-02-09
                      • 2021-05-24
                      相关资源
                      最近更新 更多