代码一定要用等宽字体么?

至少Niklaus WirthAlan KayRob PikeBjarne StroustrupDon Knuth都没有把这当成理所当然的事1

Niklaus Wirth的Oberon Niklaus Wirth的Oberon

Alan Kay的Smalltalk Alan Kay的Smalltalk

Rob Pike的Acme,Dennis Ritchie和Russ Cox也是Acme的使用者 Rob Pike的Acme,Dennis Ritchie和Russ Cox也是Acme的使用者

Stroustrup《The C++ Programming Language 3rd》 《The C++ Programming Language 3rd》

Knuth《Computers & Typesetting, Volume A: The TeXbook》2《Computers & Typesetting, Volume A: The TeXbook》

「等宽字体(Monospaced Font)」最初为打字机设计,因为在敲击按键后它只能移动固定的距离。早期的计算机显示设备也使用等宽文字,数码管仅能显示单个字符,以等宽字符显示的早期显示器结构也更简单。在纯文本文档中展示表格数据,使用等宽字体更容易做到对齐——这也是我们在排版代码时看重的,因为相同等级的代码需要保持一致的缩近距离。

但拉丁字母的宽度原本就不相同,「比例字体(Proportional Font)」更符合人们长久以来形成的阅读习惯。相对于等宽字体,它的可读性(Readability)更强。

有没有可能既享受到比例字体易于阅读的优点,同时又保持代码拥有一致的缩进?

Nick Gravgaard 2006年提出了一种名为「Elastic Tabstops」的方案,目前已能应用在一些编辑器中。它重新定义了tab的行为——每个tab代表一条垂直线,将代码分隔成不同逻辑列单元,其宽度由单元中最宽行决定。下面的动态图片显示了它的效果。

假如解决了对齐问题,是否我们就可以在代码中放心地使用等宽字体呢?

也没有这么简单。据说过去的出版行业中,作者提交比例字体文稿曾被认为是「失礼的」,因为等宽字体的可辨识性(Legibility)更胜一筹,更易于编辑和估计字数。这一点上,与需要反复编辑的代码非常类似。

或许一种合适的方案是:在编辑器中使用等宽字体,而在印刷品中不妨考虑试试比例字体3


  1. 除了《The TeXbook》和《The C++ Progromming Language》其他截图有些古老。 另外因为文章涉及了较多自己不熟悉的领域,希望对字体排印熟悉的朋友能指出文章存在的问题。 

  2. 第一次对这个问题的答案产生疑惑,就是因为看到Knuth《Computers & Typesetting》这一套书的代码都使用了比例字体。 

  3. 对于汇编语言,可能需要总是使用等宽字体。 

Emacs下的中文校对mode

每个月编辑文稿的过程中都需要处理大量文字问题,其中相当部分是反复出现的。检查它们很花时间,注意力不集中时又容易遗漏。

因而逐渐将这半年交叉审稿过程中,同事发现但自己容易忽略的问题整理出来,为Emacs写了一个minor mode——Proofreadr。目前它可以提示以下几类问题:

  • 常见错别字,目前积累了一百来个。
  • 中英文间多余的空格,可能有问题的英文标点。
  • 连续重复的中英文字或词。
  • 并非错别字但不符合杂志规范的文字、术语。

因为工作中与本文打交道的时候多,所以专为写作设计的Scrivener、iA Writer、Byword都忍不住买来尝试了一把,但真到开始编辑和写作文字,还是觉得离不开Emacs的光标移动,字、词、句、段的选择,大小写转换,正则替换,字数统计,配合Marked预览Markdown文档这些操作。

为什么要学习多种编程语言——《七周七语言》笔记

《程序员》杂志有一个“读书”版块,一本书读过之后,能够不掺商业利益,不杂个人恩怨地写一些读者觉得值得记录和愿意分享的话题。谈不上书评,因而不负有指导读者、教训作者的重大使命,可以看成是写在页眉页脚上的文字。

Peter Norvig曾谈到他在编程上成功的秘诀之一:

至少要学会六门编程语言。一种面向对象语言, 如Java或C++; 一种函数式语言, 如Lisp或ML; 一种支持语法抽象的语言, 如Lisp; 一种声明式语言, 如Prolog; 一种支持协同式编程的语言, 如Icon或Scheme; 还有一种支持并行的语言, 如Sisal。”

Eric Raymond也表达过相似的观点:

Python、C、Perl和Lisp除了是最重要的四种基本语言,它们还代表了四种非常不同的编程方法,每种都会让你受益匪浅。”

编程语言会影响你思考问题方式,因为每种语言所包含的一系列特性——静态类型和动态类型、早期绑定与延迟绑定——都会鼓励你采用某种特定的解决方案。Raymond甚至认为,即使你并不真的使用Lisp,单是学习它就会让你成为更好的程序员——假如你只使用命令式语言,但只要头脑中思考着函数式方案,写出的代码也许就会不同。John Carmack在“用C++进行函数式编程”中就谈到过他的体会。

维特根斯坦曾说“语言的界限就是我与世界的界限”,当你新学会一门编程语言,才有可能领略由这门语言搭建起来的软件世界的精妙。松本行弘曾经谈到,他在设计Ruby时,Emacs带给他极大的灵感,假如他不曾深入研究Emacs Lisp,我们看到的Ruby不会是今天的样子。

《七周七语言》中介绍了Ruby、Io、Prolog、Scala、Erlang、Clojure、Haskell,与Norvig给出语言列表覆盖的范围相近,而且语言更“现代”,是一本了解编程范型的入门书1

但光单看菜谱成不了好厨师,真正学好编程是个复杂的活儿,只靠书本和课程都做不到。几乎所有的编程好手都是自学成材,真正能起作用的就是去亲自读代码、写程序。

如今寻找代码已经变得很容易,无论你对其中哪种语言好奇,总能很方便地在GitHub上按照分类找到有趣的应用。

读完这本书,如果你对编程语言这个话题本身感兴趣,还可以阅读探讨编程语言特性的进阶书,比如《程序设计语言:实践之路》。此外,一些语言中极有用但更高阶的技巧,在这本书中并没有探讨。假如你想见识Clojure中宏的威力,可以阅读Paul Graham的《On Lisp》,网络上还可以找到将这本书示例用Clojure改写的版本。

《程序员修炼之道》的作者David Thomas鼓励程序员每年学习一门新语言,所以在读完这本书之后,请不要停下你继续学习其他编程语言的脚步。


  1. 作者坦言在写书之时有几门语言尚并不熟悉。 

保留更大的Margin

几次看到有读者反映《数学之美》《浪潮之巅》的margin(边界)过大,觉得这样浪费纸张。

《数学之美》样章1

以往拿「绿地空间」类比解释这个问题,感觉不是很有说服力。

I Love Typography有一篇文章讨论了margin大小的话题,呼吁书籍应该在文字四周保留更多空间。

文章提到15世纪的古书往往保留了更大的margin,而现代书籍基于纸张成本考虑,不断缩减。作者认为更大的margin有3个好处:

  1. 更美观,建立起文字的边界,保留呼吸的空间,margin是有意留下的,而不是剩下的;
  2. 符合人因工程学,平放手握两相宜;
  3. 鼓励读者与作者交流,留下笔记。

Robert Bringhurst的观点是:

页面空间一半留给文字,另外一半应该留给margin。2


  1. 图片来自豆瓣样章试读。 

  2. Perhaps fifty per cent of the character and integrity of a printed page lies in its letterforms. Much of the other fifty per cent resides in its margins. 

《Designing with the Mind in Mind》书评

这本书并没有提供具体的UI设计细则可以供设计师们按图索骥(这种类型的书市面上已经不少),而是揭示了这些原则背后的原理,在UI设计和认知心理学研究成果之间架起一道桥梁。使读者在了解这些心理学背景知识之后,能够运用它们解决实际工作中可能遇到的不同问题。从许多方面看,这本书很像一本UI设计领域的《Brain Rules》,它们都架起了两个领域的桥梁,让心理学/脑科学指导我们的工作和生活,甚至规则都同为12条。

《Designing with the Mind in Mind》篇幅短小,12个章节平均每章只有十页出头。从这点看,作者似乎在写作时就考虑到了「我们的大脑不是为阅读设计的」,以及「我们的注意力有限,记忆力也不完美」。另一方面,我相信一本书应该用80%的篇幅来探讨一个领域中最有趣的20%的主题,我觉得这本书做到了。通过阅读这本书,读者们应该已经能够对附录中给出的经典设计原则给出自己的初步解读。

《Designing with the Mind in Mind》运用了许多新的心理学研究成果,在这本2010年出版的著作的七十多份参考文献中,有近1/3是2005年之后的研究成果。比如书中提到上世纪七十年代教育研究者们认为从上而下语境驱动的阅读,要比从下而上特征驱动的阅读更快更有效,并基于这个假设产生了许多速读方法。然而这却是个谬误,新的研究表明基于语境的阅读大多是较差的阅读者在缺乏构造句子含义能力时不得已采用的方式。由此联想到自己读英文时还是该把生词的含义都弄懂,直到能下意识反应出来才是正道,凭猜则不大靠谱。

这本书从心理学的角度出发写作还有一个好处,就是内容并不那么容易过时。计算机科学领域的书籍,总避免不了因为技术的进步导致内容快速更替,而从更本质的角度出发,探讨原理层面,则能历久弥新,不必随着软件的变化立刻更新案例。也能有更广的适用范围,不被限定在移动软件或是Web应用。

读完一本书,尤其是某个自己尚不熟悉领域入门好书之后1,最有趣的地方在于:当你知道了这些原理,就像为自己打开了许多扇窗户,开始观察到以前不曾发现的景象(虽然它们一直都在)。想起自己读过第一本关于字体排印的书之后,每一页纸都不再仅仅是文字和留白,字与字、行与行、段与段之间都嵌进了许多变化的参数——「顿觉全牛骨隙宽」。

读这本书也是如此,比如上个月Visual Studio 11的界面变化引发超过800条讨论(多数开发者的反馈是负面的)便可以从「经验影响感知」这个角度解读。近来颇为流行的色彩主题Solarized也能从「视觉是为边缘反差而不是为亮度优化的」的角度解释它的原理2。我自己开始刻意从Alfred启动应用程序或者执行脚本,希望能在短时间把对这种「概念模型」的操作变成下意识进行。而我在Emacs的Markdown-mode下总是把握不好Tab的行为则可能是这个mode下的「一致性」没有处理好,或者跟自己长期使用的OmniOutliner行为有冲突。


  1. 其实我觉得一个领域至少读过两本书之后才有资格写书评。 

  2. Solarized值得单独写一篇文章介绍,它的灵感得自印刷品质出色的书页在阳光明媚日子里的树荫下所呈现的宜人对比度,适合在电子显示器下长时间阅读。使用者可以根据自己的喜好来简单或充分地使用。它基于Lab色彩空间等更为复杂的原理,并经过了广泛的实践测试。 

文字中的括号嵌套

这里讨论的不是程序代码中的括号嵌套,代码中的多层括号嵌套,一方面能通过不同缩进或风格加以区分,另一方面代码本身最终是交给机器执行的,即使程序员理解困难些,程序运行并不会受到影响。当然,对于LISP程序员肯定不是问题1

而自然语言(比如中文)就不同了,文字首先要便于人类理解。连续出现多个括号,影响美观倒是其次,如果不能区分嵌套层次(比如这种(都用小括号表示(到底是谁解释谁))情况),会妨碍读者对文字内容的理解。

偶然在《字体设计应用技术完全教程》读到下面这段文字,第一层解释使用方括号,第二层使用小括号,直观地表示出了不同层次。

对应段落的原文为:

原文层次相对简单,并没有出现嵌套,这样的处理方式是编辑在中文版中采用的。


补充twitter上的讨论

@liruyi说:比較贊同 @lianghai 的建議:(比如這種 [都用小括號表示 {到底是誰解釋誰} ]情況),可以保證外層括號統一(即一級括號永遠是圓括號)。

@lianghai说:之前我和 @liruyi 的讨论结果是:对于偶尔出现的短小括号嵌套(比如英语(English)原文加注),其实全用圆括号就挺好(不必说花括号,方括号[square bracket]就已经很突兀了)。


  1. LISP被戏称为Lost In Stupid Parentheses或者Lots of Irritating Superfluous Parentheses 

喜欢The Feynman Lectures on PhysicsBeautiful Evidence 的版式。遵循简洁的规则1,既能满足展示不同尺寸的图片,又不会影响正文阅读的连贯,空白的部分适合读者做笔记。


  1. 两者相比,The Feynman Lectures on Physics的一致性还要更好些,Tufte的作品中有时候会做一些变化。 

你正在解决错误的问题

1959年英国实业家Kremer设置奖金,奖励第一个制造人力飞机飞越英吉利海峡的人10万英镑。但10年过去,所有的尝试都以失败告终,在另一个10年又将结束之时,故事的主角MacCready登场。他说以往人们都在解决错误的问题,“问题在于我们没有理解问题本身”。

MacCready发现几乎每个试图解决这个问题的人,都基于假设或未经证实的理论,花一年时间打造他们的飞机,完工之日郑重地举行一场测试,飞行几分钟然后坠地失败。他们只能依靠一次短暂测试获取有限数据开始下一轮建造,过程非常缓慢,但人们却依旧希望于通过这样的方式实现目标。

他认识到需要解决的问题并不是如何依靠人力飞行(至少这不是首要问题),而是由于对挑战的认识不足,糟糕的开发过程阻碍了人们看清目标。他重新定义应该首先被解决的——如何制作在几小时内就能完成的飞机。他做到了,重新建造、测试、学习的过程从数年变成了几小时或几天。

MacCready 1979年得到了Kremer奖。故事告诉我们,当试图解决一个难题时,可能需要重新定义问题,让方案可以帮助你加快学习,找到一个快速改进的方法,然后不断尝试。尤其当你正尝试创造一个惊世杰作,此时很可能正在解决错误的问题。

Alan Kay在「Normal Considered Harmful」演讲中讲到了这则故事:http://bit.ly/ULNSBE