《Fluent Python》这本书非常值得读,此书不仅讨论Python,经常结合其他编程语言讨论一些语言设计上的问题。读此书就和一位经验老道的开发者聊天一样,非常尽兴。
今天在书上(16章协程)看到这样一段话,很震撼:
对编程语言来说,关键字的作用是建立控制流程和表达式计算的基本规则。
语言的关键字像是棋盘游戏中的棋子。对国际象棋来说,关键字是王、后、车、马、象兵;对围棋来说,关键字是●。
国际象棋的棋手实现计划时,有六种类型的棋子可用;而围棋的棋手看起来只有一种类型的棋子可用。可是,在围棋的玩法中,相邻的棋子能构成更大更稳定的棋子,形状各异,不受束缚。围棋棋子的某些排列是不可摧毁的。围棋的表现力比国际象棋强。围棋的开局走法有 361 种,大约有 1e+170 个合规的位置;而国际象棋的开局走法有 20 种,有 1e+50 个位置。
如果为国际象棋添加一个新棋子,将带来颠覆性的改变;为编程语言添加一个新的关键字也是如此。因此,语言的设计者谨慎考虑引入新关键字是合理的。
Scheme 继承了 Lisp 的宏,允许任何人创建特殊的形式,为语言添加新的控制结构和计算规则。用户定义的这种标识符叫作“句法关键字”。Scheme R5RS 标准声称,“这门语言没有保留的标识符”(标准的第 45页),但是MIT/GNUScheme这种特殊的实现预定义了 34 个句法关键字,例如 if、lambda 和 definesyntax(用于创建新关键字的关键字)。
Python 像国际象棋,而 Scheme 像围棋。
现在,回到 Python 句法。我觉得 Guido 对关键字的态度过于保守了。关键字的数量应该少,添加新关键字可能会破坏大量代码,但是在循环中使用 else 揭示了一个递归问题:在更适合使用新关键字的地方重用现有的关键字。在 for、while 和 try 的上下文中,应该使用 then 关键字,而不该妄用 else。
在这个问题上,最严重的一点是重用 def。现在,这个关键字用于定义函数、生成器和协程,而这些对象之间的差异很大,不应该使用相同的句法声明。
引入 yield from 句法尤其让人失望。再次声明,我觉得真的应该为 Python 使用者提供新的关键字。更糟的是,这开启了新的趋势:把现有的关键字串起来,创建新的句法,而不添加描述性的合理关键字。恐怕有一天我们要苦苦思索 raise from lambda 是什么意思。
这段文字很有意思,作者抱怨的是,该引入新的关键字的时候却不引入,过于保守。
比如 for-else 语句就很让人困惑—— “for循环跑完了,这段else会不会执行呢?” 我每次看 for-else 代码,都得在心里来回算几遍。因为 else 表示转折,但是这里并没有转折的意思——“如果循环正常结束,就直接执行这段代码。” 我的方法是将这个 else 当成是 “then” 来理解,显然如果改成 “then”,就一点歧义也没有了。“循环结束,then 执行这个”。对于 “try…expect…else”来说,换成 then 更是好理解的多,“try…except…then”。
将人们已经熟悉的内容重复赋予新的意义,甚至组合一些关键字来使用,会更加让人困惑。
不过好在现在Python已经引入了async/await来定义协程(PEP 492),好的多了。
贴一下书中推荐的两个链接,很有意思:
- The Value Of Syntax? 这个讨论组叫做lambda-the-ultimate,是编程语言极客的聚集地
- What color is your function?
是时候发动了新关键字革命了!(双手高举且奋而疾呼状