语言与范式的映射
我最近读了埃里克·史蒂文·雷蒙德的文章《如何成为黑客》,他提到学习五种关键语言(他推荐Python、C/C++、Lisp、Java和Perl)是掌握当今主要编程范式的好方法。
他的建议是,程序员具体会哪些语言并不那么重要。更重要的是要了解不同的编程方法,原因有两个。
第一个原因是,一旦你掌握了处理问题的一般方法,学习一门新语言就变得很简单。
第二个原因是,没有一种语言是最好的——每种语言都有其优缺点。了解在特定问题下应该选择哪种类型的语言是最理想的。这正是我最感兴趣的,但我在区分他推荐的五种语言时遇到了困难。它们之间似乎有很多重叠。
所以我具体想问的是,关于这五种语言,它们各自的编程范式是什么?并举一个它们最适合解决的问题的例子。
一个示例答案(我不确定这个答案是否正确):
Perl
- mainly a functional language
- great for quick text substitutions in multiple files from the command line.
我发现还有一些类似的问题,但我特别想了解这五种语言。我只是想要一个起点,不需要太详细的内容。提前谢谢你!
3 个回答
ESR选择编程语言不仅仅是看它们的编程风格,还考虑它们的实际用途,每种语言都有它的代表性:
- C/C++:系统编程语言(底层)
- Lisp:函数式编程(启蒙)
- Java:面向对象(框架)
- Perl:更好的脚本语言(管理员)
- Python:因为是Python,当然啦。(乐园 -- http://xkcd.com/353/)
说得更严肃一点,Python是最好设计的语言;它的所有特性都非常协调,形成了一种干净、设计良好且易于学习的语言,不是那种玩具语言。它是一种多功能、全面的通用语言,几乎可以在任何场合使用:桌面应用、网页应用、嵌入式脚本、系统管理等等,从最简单的一行代码到成千上万行代码都有。它的亮点就是语言本身的设计。就我所知,没有其他语言能和它相提并论。
Perl代表了一类用于脚本编写或任务自动化的语言,你需要调用一系列程序,对它们的输出进行一些处理,然后将结果作为另一个程序的输入。这个类别的其他语言是bash,但bash缺乏perl那种强大的字符串处理能力(别开始说bash可以调用perl或sed或awk)。
Java代表了一类在行业中广泛使用的语言,投入了大量的时间和金钱。因为它们无处不在,所以几乎任何问题都有丰富的库和框架可以使用;如果你能想到一个问题,很可能这个问题已经被别人解决了,他们也写了相应的库。一个黑客应该了解这些语言,因为如果能避免写代码(或者少写代码),会提高工作效率。这个类别的其他语言/框架包括.NET、Django、RoR。
Lisp代表了函数式编程风格。懂得如何用函数式思维来编程有很多好处,这里就不再重复了。此外,Lisp有非常强大的元编程特性,这几乎是Lisp独有的。这个类别的其他语言(函数式,而不是元编程)包括Haskell、Scheme、Clojure、F#等。
C/C++代表了用于编写操作系统内核、设备驱动程序和对速度要求高的代码的低级语言。这类语言的语义接近底层硬件(尤其是C,C++则稍微弱一些),一个黑客应该知道CPU是如何工作的,否则他不能称自己为黑客。这个类别的其他语言是汇编语言,但我认为即使是ESR也同意汇编语言太底层,无法做任何有生产力的事情。
虽然他提到的许多语言有很多重叠之处(例如Python、C++、Perl都支持面向对象编程);但每类语言都有自己独特的亮点。
就我个人而言,如果有机会再加一种语言,我会选择PHP。网页应用越来越普遍。PHP代表了一类用于网页应用的语言,这个类别的其他语言包括JSP、ColdFusion等。
总之,一个黑客是一个:
- 了解计算机底层工作原理的人
- 懂得如何进行抽象思考的人
- 知道如何恰当地使用框架的人
- 会管理自己系统的人
- 懂得设计好语言的人
如果可以的话,去一个能让你接触多种编程语言的学校。
- Python:这是一种多范式的语言,主要关注面向对象和基于多态的通用编程。
- C/C++:这其实是两种不同的语言。把它们放在一起说是因为ESR的实用主义。
- C:经典的命令式语言。
- C++:也是多范式的,主要关注面向对象和基于模板的通用编程。
- Emacs Lisp:这个已经过时了,建议学习Haskell、Clojure、OCaml或Scheme。这是一种函数式语言。
- Java:经典的面向对象语言,设计上注重可靠性。但这对你学习其他东西没有帮助。
- Perl:为了你好,别学Perl。它没有明确的编程范式,写出好的代码很难。可以试试Awk。
ESR并不太接地气。他是个著名的哲学家,但他写过什么重要的代码呢?
想要学习现在流行的编程范式,最简单的方法就是参与任何一个现代项目。现在流行的范式最容易接触到。不过,试图“学习”像C++或Java这样复杂的语言,只会让人感到困惑。每种语言都有其深度,需要通过实际项目来掌握。你不能只是坐下来就能学会。
不过,写一些简单的项目还是很有价值的,比如:
- 一些函数式语言(我学校用的是OCaml,学起来很简单)
- 汇编代码(用一个真正的汇编器,而不是GNU
as
,因为它不适合人用)- 或者一个极其轻量的系统,比如Forth
- 一个(相对)简单的文本处理语言,比如Awk
- 一个逻辑求解器,比如Prolog(感谢@Thorbjørn!)
嗯,我能想到的就这些。总之,编程范式是用来解决问题的,重要的是要解决一个问题,这样才能引导你形成特定的思维方式,而不是找一种语言来强行把每个问题都套进一个特定的框架里。
我觉得你可能理解错了。正如esr自己所说,重要的不是语言,而是范式。所以当你说
- Perl是一种函数式语言
- 它非常适合从命令行快速替换多个文件中的文本
你其实忽略了函数式语言的一个主要特点,那就是它们非常适合用自下而上的方法构建大型系统:通过解决一系列(精心挑选的)小问题,利用设计良好的函数,直到我们拥有一个完整的系统。我们通过识别所用算法的共同点,使用高阶函数来减少代码重复。我们通过高阶函数来创造出仅在特定情况下需要的函数,从而减少(明显的)分支行为。
同样,我也可以说
- Java主要是一种面向对象的语言
- 它适合编写大型、稳健的系统,
但这也忽略了面向对象语言的一个关键点,那就是它们是用代码来建模问题领域中的概念,这样我们就能清晰地以命令式的方式解决当前的问题。我们通过识别相关概念的共同点,封装处理这些共同点的代码到一个描述它们的类中,从而减少代码重复。我们通过为一个抽象提供不同的子类,赋予它们适当不同的行为,从而减少(明显的)分支行为。
总的来说,编程语言及其相关范式的基本点在于
让你不必考虑那些不影响最终程序质量的事情。如果这不是一个(在很大程度上)理想的目标,那我们就都在写机器代码了。
这通过(其中之一)提供一套构建抽象的工具来实现。
多看看,挑一个你喜欢的,努力学好它。只要确保你了解其他语言在某些情况下能提供更好的解决方案(这可能意味着你最终也要学好它们;)。我认为“好的解决方案”主要可以理解为“代码与想法之间的清晰映射”。(当然,效率问题可能会迫使你使用像C这样的语言)