语言之争: 编程语言 vs. 自然语言

程序猿与作家与翻译家

Posted by kissg on August 20, 2016

有人的地方就有江湖, 有江湖的地方就有恩怨, 人就是江湖. ——任我行

程序猿的江湖, 有没有恩怨, 我不知道. 我知道的是, 程序猿有流派之分, 喜好之争.

有人用 Linux, 有人用 Mac, 有人用 Windows, 这是操作系统之争; 有人用 Vim, 有人用 Emacs, 有人用其他现代编辑器, 这是编辑器之争; 有人用 C, 有人用 Java, 有人用 Python, 有人用其他编程语言, 这是编程语言之争.

程序猿相轻, 就同文人相轻一样, 自古而然. 大家都是各自使用的操作系统/编辑器/编程语言的拥趸, 难免会有争执, 都想证明自己的选择是最好的. 我的看法是: 没必要争锋相对, 都是优秀的产品, 我自喜欢我所喜欢的, 如果你也喜欢, 那么谢谢你的认可; 如果你不喜欢, 也请你不要随意贬低它们.

本文意不在讨论这些, 而是想写一些我个人关于编程语言与自然语言的思考.


我在大学里接触过不少编程语言, 包括课内学的 C++, Java, 汇编语言, C#, 和课外的 HTML5 (严格来讲, H5 是标记语言而不是编程语言), JavaScript, Python, C. 现在在用的是 Python, 也想用 C. 接触过这些编程语言, 一个很明显的感受是: 不同语言真的很不同. 抽象程度不同, 语法不同, 程序的执行方式不同, 入门的门槛不同, 代码量不同, 编写代码的难易程度不同, 代码的执行效率不同...

如下所示, 是 HelloWorld 程序的不同编程语言实现. (代码选自维基百科 Hello World 程序样例, 未修改, 算是各语言的 Hello World 的比较标准的写法.)

# Python 代码
print("Hello, World!")

// C 代码
#include <stdio.h>
int main(void)
{
    printf("Hello, world!\n");
    return 0;
}

// Java 代码
public class Hello
{
    public static void main(String[] args)
    {
        System.out.print("Hello, world!");
    }
}

; 汇编语言代码
[BITS 16]
org 0x7c00
     mov ax,cs
     mov ds,ax
     mov es,ax
     call DispStr
     jmp $;End Hear
DispStr:
     mov ax, BootMessage
     mov bp, ax
     mov cx, 16;How long is the String
     mov ax, 0x1301
     mov bx, 0x000c
     mov dl, 0
     int 0x10
     ret
BootMessage: db "Hello, world!"
times 510-($-$$) db 0x0
dw 0xaa55; Bootable Mark

如你所见, 这些不同编程语言的代码做的都是同一件事: 在屏幕上打印”Hello, World!”. 计算机内部的执行过程可能不同, 暂且不去管它. 很明显地, 不同编程语言对同一个操作的描述各有不同. 这跟我们用不同的自然语言来表达同一概念是一个意思, 比如中文的”你好”, 用英语说就是”Hello”, 用日语说就是”こんにちは”.

在学习用汇编语言做进制转换的时候, 我的老师告诉我: 你要清楚的一点是, 不管用哪种进制表示, 不变的是数目. 十六进制的 A, 十进制的 10, 二进制的 1010, 它们都是那个数目的表示而已, 再怎么转换, A(16) 不会变成 11(10). 编程也是同理. 虽然语言不同, 表达方式不同, 但概念是同一个概念, 操作是同一个操作, 万变不离其宗.

程序, 科学的定义是: 算法 + 数据结构. 大可以不必这么讲究, 程序它就是特定的一系列动作, 行动或操作. 而所谓的编程, 就是将我们设计好的动作序列用编程语言的方式描述给计算机看, 告诉计算机如何操作.

最近, 我翻译了几篇文章, 越来越感受到编程语言与自然语言的共通之处: 笔者用文字(自然语言)表达想法, 写给人看, 程序猿用编程语言表达想法, 写给计算机看, 表达的都是想法; 翻译人员的职责是将一种自然语言转换成另一种自然语言, 程序猿的"翻译"则是将一种编程语言转换成另一种编程语言, 描述的是同一回事.

所以, 广义上, 程序猿也算是”作家”和”翻译家”吧. Eric S. Raymond 在 How to Become A Hacker 一文中写到, 很多黑客都是好的作家, 应该有触类旁通的意思. 写作/翻译能锻炼一个人的表达能力, 考量程序猿优秀与否的一个标准是编程能力, 其实也是表达能力, 比如说, 普通程序猿一股脑儿用嵌套的方式写逻辑判断或循环结构, 优秀的程序猿用逻辑操作符(and, or 等)写不嵌套的逻辑判断, 用抽象方法写不嵌套的循环结构(关于这一点, 可参看我的这篇译文).

而为什么算法和数据结构对编程这么重要? 还是拿写作类比的话, 算法是句型句式, 数据结构是词藻, 而写作不就是遣词造句, 程序不就是算法加数据结构吗?


编程语言, 从最初的只有 0 与 1 的机器语言, 到后来的符号语言——汇编语言, 再到高级语言的 C 语言, 抽象程度更高的 Python 等语言. 可以看出, 这其实是一个越来越人性化, 编程语言越来越向自然语言靠拢的过程.

虽然说, 计算机实际只能读懂 01 代码, 随着编程语言的抽象程度越来越高, 程序猿编辑的代码转换成机器真正执行的机器代码的中间步骤越来越多, 程序的效率是变低了, 但编程的门槛变得更低了, 程序开发的效率变得更高了. 这意味着, 全民编程的时代越来越近了, 编程可以像说话写作一样容易, 也可以所想即所得 (What You See Is What You Get). 以后的程序开发, 可以将更多的精力投入在构思, 而不是实现上. 亦即逻辑越来越复杂, 功能越来越强大, 但代码并没有变得更复杂.

至于程序效率的问题, 软硬件的方式都可以适当缓解. 说是缓解, 因为中间翻译解释造成效率变低, 是不可挽回的.

另外, 若非要写机器级的代码, 可以用高抽象层次的编程语言(比如 Python), 作为到最终的编程语言(比如 C 语言)之间的过渡, 先写出原型, 在将整个业务逻辑理清理顺之后, 再对代码用 C 语言进行重构.

最后, 用一句不太正确的话结尾:

存在的即是合理的

编程语言越来越自然语言化的发展, 自有其道理.