刚接触C语言的时候,很多程序员都犯过这样的错误:误将 if (i == 1) 写成 if (i = 1)。即使是老手,也可能在熬夜加班的时候写出很多这样的错误代码。
这种错误最可怕的地方在于,它不会直接导致程序宕掉,而是产生错误的结果。
为了避免这样的错误,有些程序员养成了一种习惯——在比较表达式中把左右两边的form调换过来。例如 if (1 == i)。如果不小心把==打成了=,编译器会报错,告诉你无法给常量赋值。如果比较表达式两边都是变量时,这种小技巧就不起作用了。
除了试图绕过这个坑,我们还应该更深入地理解这个坑。在我看来,这个错误的根源在于C的设计问题:
赋值语句不应该返回一个有意义的值(主要问题);if 不应该接受bool之外的类型(主要问题);==确实很容易被误写成=(次要问题);一些程序员认为问题1是C语言的“特性”,并写出大量使用这种“特性”的代码(习惯问题/社区问题)。
作为对比,Scheme也有一些问题。
Scheme的赋值不返回一个有意义的值,而是一个特殊的表示unspecified的东西,我们通常不会去使用它;但是,if 接受任意类型的值,当然也包括了这个表示unspecified的东西(设计问题);Scheme程序员很难把=和equal?误写成set!;Scheme程序员不会写出(if (set! x ...) ...)这样的代码。
所以,Scheme语言本身的设计并没有完全避免C的这个坑,代码风格保证了Scheme程序员基本上不会遇到这个坑。但不是100%保证。