第一门语言告诉你Hello World怎么说,第二门语言告诉你Hello World为什么这么说

1天前

文/一个学过七八门语言但都不精通的人

我学第一门编程语言的时候,写Hello World只是为了确认”环境配好了”。照着教程把代码敲进去,编译运行,看到输出,然后继续往下学。整个过程里,我对那行代码本身没有任何疑问——它就在那里,教科书上有,照着写就行。

但到了学第二门语言的时候,我开始注意到一些不一样的东西。这门语言的Hello World写法跟第一门不一样,它多了一些东西,又少了一些东西。我开始想:为什么这门语言要这么写?为什么这门语言必须要有这个东西而另一门不用?

后来每学一门新的编程语言,我都会先盯着它的Hello World看一会儿,试图从那几行字里”读”出这门语言的性格。看得越多,越觉得Hello World其实是一篇很短的语言宣言——它在一句话里,暗示了这门语言的设计哲学。

最简短的宣言:Python

print("Hello, World!")

就一行。没有头文件,没有类定义,没有主函数,没有分号,没有大括号。你看到它的时候,第一反应是”这也太短了”。

Python的Hello World在说:事情可以很简单。你不需要为了做一件小事而先写一堆仪式性的代码。你想打印一句话,那就只写打印这一件事。其他的都是噪音。

这句话也暗示了Python的受众——它想吸引那些不想被语法细节纠缠的人。数据科学家、运维工程师、刚入门的初学者、任何想快速实现想法的人。它用这一行代码告诉你:学我,你不需要先成为一个”正经程序员”。

Python的Hello World没有说出口的话是:复杂的事情你也可以做,但你必须自己管理那些复杂性。我不替你做,我也不拦着你做。但如果你只是为了打个招呼,那就直接打,别废话。

最官僚的宣言:Java

public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }

七行。类名要大写开头,文件必须跟类同名,main方法必须是public static void,参数必须是String数组。少一个都不行。

Java的Hello World在说:这个世界是有规矩的。按规矩来,你就能活得好。不按规矩来,我连门都不让你进。这些规矩看起来繁琐,但它们是让一万人在一起写代码而不互相踩脚的前提。

Java诞生的时候,面向对象编程正在成为主流。它想让所有人都遵守同一套规则,这样代码就能在各个平台上一致运行。那七行Hello World里的每一行,都是为了确保”一致性”而设的护栏。代价是你得多敲几行,换来的是你跟别人合作的时候,不会因为风格差异而翻车。

Java的Hello World没有说出口的话是:你按我的规矩来,我保你一生安稳。但前提是——你得先认我这一套。

最沉默的宣言:C

#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }

六行。你包含了头文件,你声明了主函数,你调用了标准库的函数,你显式地返回了一个整数。每一行都在说”我知道我在干什么”。

C的Hello World在说:你得对自己负责。没有隐式的依赖,没有自动的帮你做决定,没有”你不说我也知道”。你写什么,我就执行什么。你忘了写那个return 0,程序照样能跑,但它的退出状态是未定义的,你自己承担后果。

C语言诞生的时候,计算机还是稀罕物。写C的人通常也懂汇编,离硬件很近。这种”透明”是C的基因——它不帮你掩盖底层的东西,因为它的用户不需要被保护,他们需要的是控制权。

C的Hello World没有说出口的话是:我不想替你决定任何事情,你自己做决定。但我得提醒你——你真的知道自己在干什么吗?

最务实的宣言:Go

package main import "fmt" func main() { fmt.Println("Hello, World!") }

五行的同时,你能感觉到一种”恰到好处”的分寸感。有包声明、有导入、有函数入口,但是省掉了类、省掉了分号、省掉了复杂的花括号排版。它要的东西都在,它不要的东西一个都没有。

Go的Hello World在说:我要解决问题,但我不搞形式主义。我不像Python那么随意,也不像Java那么繁琐。我就在中间,够用就好。

Go诞生于Google内部,那帮人写多了C++和Java,烦了。他们要一个编译快、部署简单、写起来不累的语言。Go的Hello World折射出这种”务实”——它不追求漂亮,它追求够用。你看到它的时候不会说”好美”,你只会说”行,那就这样吧”。

Go的Hello World没有说出口的话是:我不废话,你也别废话。把事办了,然后下班。

最谨慎的宣言:Rust

fn main() { println!("Hello, World!"); }

看起来跟Go差不多。但Rust的编译器在你运行这个程序之前,已经做了大量的检查——检查了变量的生命周期、检查了内存的所有权、检查了是否有可能的内存安全问题。你看不到这些检查,但它们一直在运行。

Rust的Hello World在说:你的代码安全,由我来守护。你可以放心大胆地写,出了任何内存问题,那一定是我搞错了。这行的代价是编译时间会长一点,但换来的是运行时不会莫名其妙地崩溃。

Rust的受众是对内存安全有执念的系统级开发者。它的Hello World暗示了它的立场:功能可以少,安全不能少。

Rust的Hello World没有说出口的话是:你放心,我不会让你写出那种”不知道为什么能跑”的代码。我会让你写出”不知道为什么不能跑”的代码。

我学一门语言,先看它的Hello World

现在每当我接触一门新的编程语言,我已经不看它的语法教程了,我先找它的Hello World示例。那个示例会告诉我:这门语言把自己定位成什么,它的设计者觉得”最重要的事情”是什么,它想吸引什么样的人来用。

如果一个语言的Hello World只有一行,我猜它想取悦效率主义者。如果一个语言的Hello World有七八行,我猜它想取悦结构主义者。如果一个语言的Hello World什么废话都没有,我猜它想取悦务实的人。如果一个语言的Hello World藏了一堆隐式行为,我猜它想取悦那些”相信工具会帮自己干活”的人。

这些”猜想”不一定对,但它们能让我在学这门语言之前,先跟它建立一种直觉上的默契。我知道它想让我怎么对待它,我也知道我该怎么跟它相处。

那句问候,是一张名片

我后来觉得,Hello World其实是一张名片。一张语言递给你的时候,在说”这是我的名字,这是我的风格,这是我的态度”。你接过那张名片,读一遍,就知道你接下来要面对的是一个什么样的人。

Python像一个随和的朋友,见面就说”嗨”。

Java像一个西装革履的律师,见面先递一份格式规范的文件。

C像一个不苟言笑的老师,见面就问你”你带课本了吗”。

Go像一个话不多的同事,见面点个头就坐下干活了。

Rust像一个严谨的工程师,见面先掏出一叠安全声明让你签字。

你第一次见一个人的时候,他跟你说的第一句话,就能透露很多关于他的信息。你跟一门新语言第一次见面的时候,它说的Hello World,同样是那句”第一句话”。

我把所有学过的语言的Hello World都存在一个文件里,按时间排序。从头扫到尾,能看到一段简史——从C到Java到Python到Go到Rust,每一门语言的出现都带着它那个时代的印记。它们的Hello World,就像一句句来自不同年代的问候,站在同一条时间线上,对着同一个”World”打招呼。

内容都一样,语气各不相同。