如何学习所有编程语言

发表信息: by Creative Commons Licence

我应该从哪个编程语言开始学起?1

许多新手刚开始学编码时都会问这个问题。

最好的编程语言是什么?

在获得一些实际的开发经验后,开发者便产生了这样的问题。

这种类型的问题能够引发无休止的争论,而根本不会有标准的答案。

相反,我想要分享的更重要的东西是:如何精通学习新语言的技巧。

对于熟练的开发者来说,学习新的语言应该是一件简单的事情。花费一个周末的时间甚至几个小时就使用新的编程语言写代码是很平常的事。更熟练的开发者只需要看一眼手册,完成任务的过程中就能掌握该语言。

精通学习所有语言的技巧无需天资,只需知道编程语言的核心知识并多加练习就可以达成。

当然,我们不需要学会所有类型的编程语言,但掌握更多的编程语言能够让我们选择更适合的编程语言完成特定的任务。

如果编程语言是一辆车

世界上有成千上万种编程语言,在 IT 领域种被广泛应用的只有大约20种。

进一步研究会发现所有编程语言都共享一些特性。

拿汽车举例子,世界上有不同的车,有小而动力足的车,也有大而慢的车;不同品牌的车有不同类型的驾驶体验。

如果一个人会开一辆车,那么他也会开大部分的车;即使是一辆其它牌子的新车。

为什么?因为不同的车有许多相同的东西,从根本上来说,它们都是在发动机和轮胎的基础上制造出来的。汽车被设计出来用于相同的目的:送你到目的地。

bctt 的推特:“设计编程语言的目的:表达程序员的思想。”

为什么有这么多的编程语言

在计算机的世界里,编程语言扮演两种角色:

  • 程序员利用它们发送指令给计算机,告诉计算机我们需要什么,从而得到我们想要的东西。
  • 传递想法给其他程序员,分享我们的经验和观点。

因此,代码只是传递给其他程序员或计算机的“消息”。而在编程语言进行设计与实现时就需要进行权衡。

主要原因应该是:

  • 硬件和计算机理论是逐渐发展而来的,通常来说,编程语言被设计的更简单易用的同时具有更强的表现力。
  • 计算机被应用在许多领域,针对不同领域有不同的编程语言。
  • 不同的编程语言有不同的设计方法和哲学。

语言有不同类型的语法或特性,但归根结底它们都是图灵完整的(Turing complete)

简洁地说,这意味着:所有的编程语言都能够用来实现任意算法。

编程语言的基本要素

几乎所有的编程语言都包含这些类型,事实上,它们全都是关于“抽象的“:

  • 数据类型和数据抽象
  • 控制流和控制抽象
  • 低级别的抽象
  • 特定领域额外的抽象

这就是我们可以掌握所有的编程语言的原因:语言的概念是有限的,经常被用到的只有不到15种。

  • 过程式
  • 面向对象
  • 指针
  • 递归
  • 异常
  • 静态类型
  • 动态类型
  • 类型推断
  • 匿名函数(Lambda function)
  • 垃圾回收
  • 程序剩下的部分(Continuation)
  • 宏指令和元编程

和设计原则一样,编程语言概念趋于固定。

编程语言设计者彼此借鉴想法,通过不同的实现方式实现出来。所以有时我们可能会说语言 PL_C 是语言 PL_A 和语言 PL_B 的孩子,语言 PL 家族树类似于这样:

理解这些概念不仅帮助我们更快速的学习语言,同样能够帮助我们写出更好的代码。例如过程式编程语言和面向对象编程语言有着不同的编码风格和范式。

如果你不明白它们之间的区别,实践中将不可避免的写出糟糕的代码。

关注编程语言概念而不是语法

如何开始学习编程语言的概念呢?

要完全理解编程语言的概念,首先需要我们回答几个关于它的问题。

为什么要发明编程语言的概念?

需要解决的问题是什么?

有什么好处和弊端?

如何实现?

拿垃圾回收为例,第一个问题是:什么是垃圾回收?

在谷歌上面进行搜索,来到 维基百科垃圾回收页面可以看到:发明垃圾回收是为了解决内存管理问题,它能减少程序中的内存错误;有了垃圾回收机制,写起代码会更加简单,因为无需再手动管理内存。代价是会损耗性能,因为会有额外的代码分配和释放内存;因此在使用有垃圾回收机制的编程语言时,要注意垃圾回收机制对程序性能的影响。

使用一段时间后,就需要知道垃圾回收是如何工作的,使用了什么算法?垃圾回收有多种不同类型的实现,各有优缺点。

学习一种新的编程语言时,就是学习编程语言概念最好的时机。

举个例子,假如 Ruby 是你学习的第一种编程语言,那么这同时也是你学习理解面向对象编程优缺点的最好时机。

理解了面向对面编程的概念再学其它面向对象的编程语言就会简单许多。

实现或创建编程语言

别害怕,解释器和编译器只是一种特殊类型的程序。它们接收你的代码,之后运行你的代码或者是把你的代码编译为字符码或字节码。

实现或创建编程语言可以帮助你战胜内心深处对编程语言的恐惧。

这是学习所有编程语言的又一个秘密。

如果你的编程语言语法不是很复杂,实现起来并不费事。

看一下这个项目:写一个Lisp语言

任何语言都可以用来实现一个Lisp,Lisp/Scheme 有清晰的语法,很容易被解析;编程语言教育广泛采用Lisp。

8cc 是 C 语言的编译器,如果你意在写一个编译器,它将是一个很好的参考。

一些好的编程语言实现的数据对你学习同样是有帮助的:

EOPL 是一本教科书,包含许多可以拿来玩儿的编译器。

Programming Language Pragmatics 同样是本编程语言教育性的书籍。

学习新语言的步骤

按以下步骤学习编程语言的概念会更高效:

#1 明白该语言的设计哲学和语言特性

例如,如果开始学习 Ruby,先看看它有什么特别的地方。

然后看官网的介绍,更深一步进行了解:http://www.ruby-lang.org/en/about/

在开始学习之前,试着总结出需要理解的主要特性:

  • 简单、高效率、代码可读性高
  • 自带解释器,因此有垃圾回收机制,同样意味着对于某些任务,性能可能会受到影响
  • 一切皆对象,属于面向对象编程语言,甚至完全是面向对象的。
  • 灵活,语言的很多部分都能够被重新定义。

了解语言最重要的特性,包括它的优缺点,在你使用新的语言写代码时会很有帮助,它就是你的路线图。

#2 学习语法,按照教程或书籍进行实践

你需要掌握语言基础的部分,包括语法、基础的IO、debug 工具、单元测试工具等。

如果你是个新手,试着找一些该语言权威的书籍,如该语言作者写的或在 Amazon 上面搜索该语言的名称,找那些评分高的书籍。

记着,在你没有成为专家前最好自己手写代码,不要只是复制粘贴。

exercism.io 上面练习新语言,会有导师免费检查你的代码并给予你建议,棒极了。

如果你是编程语言的专家,只需找一些该语言简单的手册甚至只需要一些代码示例。

看一下这个网站 learnxinyminutes.com

#3 读、写更多新语言的代码

是时候用新语言、相关知识、工具或库写一个项目了。

开始可以写些简单的项目,例如写一个猜数字的游戏或一个简单的书籍商店,又或者是一个待办事项应用。

Github 上有许多类似的项目。

#4 理解更多语言实现细节

这不是必须的,如同我在 成为一个程序员 中说的那样,一个有追求的程序员对语言的细节和实现是充满兴趣的。

有时 bug 的出现仅仅是由于我们不清楚该语言的实现细节导致的。

如何选择你的第一个编程语言?

根据你的目标和自身条件:

  1. 有人指导你或你需要在学校学习一门编程语言吗?

    如果老师告诉你做练习使用 C 语言,这是开始学习 C 语言的一个绝好机会,因为你有人指导(你的老师),也有同学;有利于开展学习。

  2. 你的目标是什么?

    如果你想开发一个 Web 应用,学习 Javascript/Python/Ruby 就可以了。

    如果你想开发游戏, C++ 是个不错的选择。

    如果你的目标是处理数据,Python/R 都可以。

    如果你想创建一个安卓应用,可以使用 Java/Kotlin。

    只需要在你选择的领域里挑选出被广泛使用的语言就可以了。如果你不清楚,可以请教有经验的开发者。

  3. 你是为了申请一份需要特定语言的工作吗?

    你只需要学习工作描述中提及的语言就可以了。

    不要花费太多时间选择第一个编程语言。

    先快速上手,获取一定的经验,之后如果你不喜欢或你涉及的领域有所改变,你可以很容易地学会并使用另一种编程语言。

哪一个编程语言是最好的?

这同样取决于你涉及的领域,编程语言各有所长。

没有任何一种编程语言能适用于所有场景,如果存在,我们只需要学习一种编程语言就可以了,不是吗?记得,没有银子弹2

几乎所有的程序员由于各自不同的体验都有自己偏爱的程序语言。

一些人声称他们喜欢的语言是最好的,别信;他们喜欢的不代表就是最好的。

就个人的体会而言,我喜欢的语言包括 C/Ruby/Lua/OCaml;我能使用这些语言产出东西,但可能不是你喜欢的,你应该尝试不同的语言找到自己喜爱的。

有人说至少掌握5种程序语言才是一个合格的程序员。

正如我上面说的那样,你不应该执着于学习越来越多的语言;而应该学习更多的语言思想和设计原理。

如果你日常的工作中使用的是过程式语言,为什么不学习一种面向对象的语言呢?

如果你使用动态语言,可以学习一种静态类型的语言。

这些就是我学习编程语言的技巧。

  1. 如何学习所有编程语言,没错!是所有! 

  2. 没有银子弹:指没有万能药的意思。(译者注)