在动态语言中,你如何进行不同的编程?

30

如果真正了解动态编程语言的人与使用静态语言的人相比,他们会如何处理编程问题?

我熟悉整个静态和动态类型之争,但这不是我的重点。我想讨论实用于动态语言而非静态语言的问题解决技巧。

我看到的大部分动态编程语言代码与静态编程语言编写的代码并没有太大区别。俗话说,在任何语言中都可以编写FORTRAN,很多人都是这样做的。但有些人使用动态编程语言来解决问题,这种方法不容易转换成例如C++等语言。他们的技巧是什么?

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

编辑(2009年1月5日):感谢以下答案,但它们似乎没有考虑到动态语言倡导者所说的生产力大幅提高。


1
说句实话,我写了一篇关于动态与静态类型语言惯用法的帖子:https://dev59.com/qnRC5IYBdhLWcg3wG9Rb#407415 - Juliet
1
很好的问题+1!很遗憾,它得到了平庸和乏味的答案。 - Dan Rosenstark
15个回答

9
我喜欢Slim的回答。在Java和C++中,我花费了大量时间来构建自定义数据结构,而这些数据结构在Python/Ruby中是免费的。并且构建专门的函数来处理这些自定义数据结构。是的,在C++中,STL非常好用。是的,在Java中的泛型也很好用。它们可以更快地创建自定义数据结构,但仍需要大量的思考和考虑。
然而,有一个更根本的原因,为什么动态语言更容易使用。这是一个深刻的想法,被称为鸭子类型。上面的一些评论提到了鸭子类型,请花些时间反思一下鸭子类型是什么。这是一种根本不同的看待世界的方式。这种观点与Java和C++等语言不兼容。
鸭子类型意味着你不需要浪费时间定义鸭子是什么。通过不必正式定义你的对象,你节省了大量的时间和精力。准确地定义对象是困难的。看看我的这篇博客文章,我在里面举了一些例子:正式定义比你想象的要少用 鸭子类型已被证明非常有用。XML中的“必须忽略”原则是使XML在Web上如此重要和有用的原因。但这只是鸭子类型的一个实例。
表达鸭子类型的另一种方式是通过Web口号“发送时严格,接收时宽松”。这也是一个非常基本的想法。
最后,您可能希望回到我长篇博客文章中,我在其中解释了鸭子类型以及它与人工智能和建模等事物的关系。

鸭子类型并不等同于动态类型。OCaml的结构化类型是该语言中被低估的宝藏之一,它更像是“静态类型语言的鸭子类型”。你必须在Java和C++中不断重新实现数据结构,因为这些语言有一个非常糟糕的类型系统(说真的,Java中的泛型就是非常模拟的)。请参见http://en.wikipedia.org/wiki/Structural_type_system - Juliet

4

我通常利用动态编程语言来简化和澄清语法。例如,如果我要表示一个数据库,与之交互的语法可以更加简洁,如果我能够动态地加载属性和方法到数据库对象上,对于其表格,表格和行的列等等。这将使得代码的区别可能在于:

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

并且

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

第二种形式的“视觉噪音节省”在处理复杂任务时真正开始累积。

3

动态语言可以在运行时更改对象,您可以添加方法、属性等。

一个很好的动态语言魔法示例是这段Groovy代码片段,它只需要两行代码就可以调用Web服务中的方法:

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

这是另一个从XML中提取数据的Groovy代码片段:
def contacts = new XmlParser().parseText("<contacts><name>Bahaa Zaid</name></contacts>");
def myName = contacts.name[0].text();

在静态语言中无法完成此操作。动态语言可以改变对象以反映实际运行时条件。


2

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

如果没有类型的概念,将每个行中的列分配给对象中的值就变得非常容易。当然,这样做的代价是可能存在您认为存在的值类型与计算机实际类型不匹配的情况。


2

我认为最显著的区别在于数据结构的选择。

在Java或C中,我非常严格地定义结构体或类。如果我需要添加一个属性,我会回去修改定义。

在Perl中,我只需使用哈希表,并在编码时“发明”键。


如果不是C++中的严格类型限制,使用STL map轻松实现该功能。 - derobert
同样,在Java中,你可以使用HashMap - 但这并不是一个好主意。类型检查是一个朋友。你在Perl中为了快速原型设计和语法糖而牺牲了它。 - slim
@slim:我曾经在C++和Perl两种语言中进行了大量的工作,我对类型检查是一种好东西提出了异议。至少在C++中现有的类型检查是如此。 - derobert

2
在动态语言中,我更喜欢尝试实验。这样可以更容易地即时改变事物,因此我可以更快地探索解决方案。
如果我知道我想做什么,并且大致知道如何做,我喜欢使用C ++。 如果我不知道如何做我想做的事情,并且可能不完全确定我想做什么,我更喜欢Lisp。

2
快速迭代使程序员更加愉快,而交互式解释器就是最快的迭代方式。优秀的解释器使用可以同时提供沙盒、测试和原型设计。
然而,请注意避免通过排列组合进行编程。我的个人经验法则是:仅仅因为它能工作并不意味着它已经准备好了,当你能够解释它为什么能工作时,它才准备好了。

请注意,静态类型的Scala确实有一个REPL! - thSoft

2
这涉及到我最喜欢的一个比率:我花在思考解决问题的时间,与我花在思考用来解决问题的工具的时间之间的比率。可以将其视为等同于S / N比率。
对于鸭子类型语言(我认为这是提高生产力最有帮助的因素之一),我只需花更多时间思考我的问题及其解决方案(并编写针对这些问题的代码),而不必花费太多时间来保持语言结构的清晰。
然后还有很多我不需要编写的代码,包括声明和特别是类型转换。
但主要是保持我的注意力在甜点区域。

2
我现在无法引用这句话的来源(我的记忆正在衰退),但是我听说过类似以下的话:
编程行业最接近银弹的技术是托管语言——让程序员不必担心内存管理等细节,使他们能够更多地专注于解决问题。
因此,我猜测问题不在于你编写代码的方式有所不同,而在于你可以将更多的大脑精力集中于“解决问题”而不是实现细节上。

1

更多的库,更重要的是 更易用的库

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接