我希望我这篇回答能给新 Tcl 玩家一些指导!
对我来说,和 Tcl 的第一次接触当在《UNIX 编程艺术》中,这本书中为了说明所谓的 UNIX 之道,列举了不少实例,当然,来自 UNIX 文化的 Tcl 也在其中。当时初入编程领域,更是 *NIX 界的一介菜鸟,扑棱翅膀乱飞,口中叽叽喳喳 C 语言的好处,怎会把 Tcl 放在眼里?所以就此错过。尔后摸爬滚打不少时间,玩起了 Common Lisp,感觉比之前觉得有趣的 Ruby 更有趣。后来凑巧在 OSChina 上碰见了一个 Tcl 程序,我当时依旧不屑。直到有人为了黑 Lisp 而宣传 Tcl 好处(实际上那人并不用 Tcl,只是为了教训 Lisp 的脑残粉),我才稍微正视它,不知是不幸还是幸运,我从此踏上了 Tcl 的“不归路”。
当然,我要说这些,不是为了感慨时光荏苒,而是为了对比。
初见 Tcl 代码,觉得凌乱实属正常。如今新式语言层出不穷,语法糖比比皆是,Tcl 代码实在是相形见绌,不过我想说的是,如果布局良好,Tcl 代码不会不能入目,也可以是一种享受,尤其如果有关键字高亮时。现存的很多代码都很乱,因为许多人觉得那些程序写一遍就不会再碰了,所以写得不是很认真,但还有不少代码本身是为了长期维护而写的,所以很整洁。
如果跨过了第一关,感觉代码很乱的心理关,下面会遇到另外一个问题。初来 Tcl 的玩家,可能马上会被一些知道 Tcl 的人打击一番,「Tcl 是很老的语言,不堪一用」「Tcl 已死」等言论甚嚣尘上,但事实上,Tcl Core Team 依然在持续不断地改良Tcl和Tk。这些人确实可能在很久之前使用过Tcl,但已经很久没有关注过它了,所以其言论只能作为参考,不能据信。
Tcl的确是个很老的语言,但Tcl仍然很新,《诗三百》说「周虽旧邦,其命维新」,周朝八百春秋,而Tcl到现在不过30年,又怎么不能新呢?拿Tk来说,很多人都用过它(Tk包括在Python等流行语言中),并指责它不支持现代的主题,但事实上,Tcl/Tk 8.5就已经有Themed Tk的支持,在Mac OS X和Microsoft Windows下都有相当不错的支持。
Tcl又是一个很有个性的语言。与其他语言不同,Tcl的灵魂是「Everything is a string」原则,简称EIAS,这点也饱受争议,因为这会使Tcl变成弱类型,从而不适合大型程序的开发(不过真的有大型纯Tcl写成的程序),但又有人觉得很爽,所以说这是见仁见智的问题。但有一点需要指出,虽然一切都是字符串,但这只是从脚本的层面去说,在核心中,依然是类型分明,如果细致编码,可以达到不错的性能。
语法上,Tcl类似于shell脚本和C语言。但和C不同,Tcl是旗帜鲜明的动态语言,动态性足以与以宏为傲的Lisp家族媲美。顺嘴说句,自8.6开始,Tcl在核心中支持了面向对象编程。
我们都知道动态语言部署成可执行文件不太容易,我还记得当时在Python中的惶惑,惊恐于SBCL生成的巨型文件,最后不得不不情不愿地放弃这种企图(Lisp社区似乎从来不在意这种事情)。但Tcl与他们不同,它非常小巧,整个runtime打包起来不过1MiB左右(这样的runtime叫做TclKit),这使得Tcl非常适合部署成单个文件。Tcl不仅适合,更有一套工具,用以生成StarKit和StarPack。
Tcl天生与Tk结合,编写GUI程序如同切黄瓜一样简单,而且最棒的是,它是完全跨平台的!你可能会说Python的tkinter也跨平台,嗯,你真的不知道tkinter就是Tk的封装吗?加上Tcl小巧的身躯,打包成可执行文件实在是惬意。
Tcl还天生支持事件驱动编程。此外,Tcl把线程支持「做对了」(引自他人语),Tcl没有其他语言普遍有的GIL。Tcl支持coroutine,做一些特殊的程序很方便(我在GUI里面用这个当数据生成器),还支持tailcall,这使递归变得容易(虽然由于Tcl特殊的体质,不得不显式调用)。
再说几个有趣的事情。Tcl的EIAS使得Lisp那样的宏在Tcl中毫无用武之地,因为普通的proc(过程)就可以实现,只需小心地安排好upvar之类的特殊命令,即可笑傲江湖。因此玩元编程,Tcl甚至比Lisp更爽(Ruby元编程真的不值一提了)。更好玩的是,Lisp中就地展开一个列表只能在宏内实现,而Tcl可以直接使用{*}实现,随时随地,没什么特殊限制。这甚至成了推荐的替代eval的方法。曾经和人谈论写Fibonacci数列,这个是大家都熟悉的,也应该知道缓存版本速度很快。有人说C++11可以不改代码(无尾调用的递归版本)实现缓存版本,但是最后写出的代码有人不服,因为他用了lambda,不符合题目要求。此时我默默写了个Tcl代码,只需拿原来的函数当参数调用一次,就能实现缓存,原来的代码没有丝毫变动!秒杀全场。
喜欢Tcl的理由?把上面那些优点全部加起来,就是我喜欢它的理由。:-)
另外,你知道吗?如今非常流行的迷你数据库SQLite本来就是为Tcl编写的!
-- 更新:
文中提到的代码: