想找一个统计工具

有这个想法很长时间了。

主要是工作中有一些分析表格数据的工作,如果人工的在 Excel 里面用眼睛去看,实在不是一个健康的活。于是我自然的用上了计算机。需要用的操作其实很简单,就是计数、Excel 的 VLOOKUP 功能找出对应的数值再求乘积、求和,我写过几个程序来自动统计。

不过这也不能完全解决问题。一方面,这样的应用我一般通过 Ruby 来完成,但Ruby在Windows系统上不方便。而且我们公司的电脑只练了公司的内网,有些需要的组件、以及要查找的资料,都不是很方便。但我要处理的数据都只能在公司的内网才能访问的网站导出,我又不能用我的 MacBook Pro 完成所有的工作。所以只能在公司的电脑上将文件导出,然后通过部门邮箱(这个可以给外网邮箱发邮件)发到我自己的邮箱里,再从自己的电脑上收取邮件,然后还需要进行转码,将 GB2312 编码转换为 UTF-8 编码,再继续操作。后来,我觉得这样实在是麻烦,就把我的 Ruby 程序移植成了 Java 程序,在公司的电脑上也能够运行。不过程序的体积就变大了几倍,一些本来简单的列表操作还要弄个迭代器,写程序的时候能把人烦死。

另一方面,成型的程序毕竟死板,有时领导要求别的什么结果,就需要修改程序。而我的程序成为了 Java 版的,我为了一个比较简单的功能,就修改了几次才完成。我是一点都不想在碰那些代码。

还有一些其他的缺陷,让我觉得苦恼。比如公司系统导出的数据,都是 Excel 的,要用程序来处理,需要我先手工转换成 CSV 的格式。这也挺麻烦。我通过查找文档,会了用 Java 语言操作 Excel 文件的方法,但这实在是繁琐,要一个单元格一个单元格的读取或写入,而不能以行为单位来操作,所以需要很多的代码来操作。而 Ruby 下对 Excel 的操作,我还刚开始看。

总之,这些不足让我觉得它们对我目前来说都不怎么方便。我想要一种快速处理的工具,要有一个 REPL,可以维护一张或多张表格,通过条件来筛选数据,并对数据进行统计,最好还能将指令保存下来,形成宏,留着以后使用。这么一看,也许我需要的是数据库?

这可是个让我比较惊讶的发现。在写这篇文章的时候,我心里想的是类似 R 语言之类的统计工具。其实我也只是听说了这么个名,实际上如何统计,是否符合我的要求,我还真不清楚。还有一个想法是 LISP,我在上厕所的时候想了一下,能否实行还有待实验。结果写到了这里,数据库自认从我脑海里浮现出来了——也许我在公司的电脑上安装一个 SQLite 就能解决问题?当然这还有待实际测试。

计划重新配置 Emacs

Emacs 是我最喜欢用的编辑器。最早我是在大约 2005 年从王垠的网站上知道它的,同时听说的还有 VIM,后来经过尝试,我觉得 Emacs 更加符合我的口味,用起来更为自然,因此从很早起我就用 Emacs 来写程序。

我最早的 .emacs 配置文件的内容也是从王垠的文章中获得的,王垠为此写过两篇文章,一篇是基础的配置,另一篇是讲各种好用的 Elisp 包,我从两篇文章中选取了我需要的内容,放进了我自己的配置文件中。这个配置文件我用的非常久,中间也经历了我从 Windows 到 Linux 到 Mac OS X 这个操作系统替换的过程。

后来我得知了有 Emacs Starter Kit 这么一个 Emacs 配置的项目后,立马对其动心了。主要原因是它使用 Org Babel 来把配置文件写成了 Literate Programming 的形式,可以在配置文件中大段的写入对于某一部分代码的想法,而 Org Babel 会在启动时自动提取出所有配置的代码,非常方便。Starter Kit 还有一个好处,就是它把很多相关的配置提取出来,放进了不同的文件中。我过去的 .emacs 是一个大文件,所有的东西都在里面。Starter Kit 则不是,它给了很多模块,需要的时候可以调用。这样的配置文件更加的清晰了。

不过 Starter Kit 也有让我不满意的地方。首先它对我来说有点大,很多配置在我看来有些过了,反而让我一下子有点措手不及。在我看来 Emacs 主要还是一款编辑器,写项目的时候可以有些项目管理的功能,但并不意味着它就要做一个 IDE。我更喜欢比较简单的东西,够用即可,过犹不及。另外就是它的效率问题,它让我的 Emacs 启动速度减慢了许多,今天我又往里面加入了一些 Ruby 相关的配置,速度又一次变慢了。今天我也看到了这篇文章,讲优化 Emacs 配置的,对我很有启发,里面很多的东西在我的配置文件中还没有被用上,于是我计划要整理一下这些配置。

我开始的想法是采用 Starter Kit 的思想,但不要直接用它的代码。首先我很喜欢文学编程,尤其是对于 Emacs Lisp 这种我不能完全掌控的语言来说,有了相关的文字解释可以省去我很大的功夫。另外,这样做的好处是我可以真正的掌控 Emacs 的配置,目前 Starter Kit 中又好多代码我不知道是做什么用的,但又不敢胡乱修改,只好让它们运行。这次借着重写的机会要好好筛选了解以下。

不过 Starter Kit 有一些好的设计,我还没有把握能自己实现出来。比如说它对于第三方插件的管理,我还需要看一下它的代码。另外,Starter Kit 自己也在演进中,我自己配置就意味着要与 Starter Kit 社区断裂,不知道是好是坏。总之目前我有这个想法,但是否能实现出来,我还有些惴惴。

升级了 tweets-page

前几天偶尔上 Twitter 的时候看到别人的一条推,说是 Twitter 可以导出自己过去发布的所有消息了。这是我一直想做的,原因之一是 Twitter 自己限制了它是一个快速更新的消息发布集中地,而已经发布了的消息就不是它所关注的了。所以过去你要是在 Twitter 页面上不断的点“上一页”,能看到的页面是有效的,印象里好像回退到 20 几页就不能再往前看了,不知道现在有没有改进。因此我很早之前就有把我所有的 Twitter 条目都导出来的想法,可惜 Twitter 的 API 也有类似的限制,因此这个想法一直没有实现。

第二个原因是让我在国内的父母可以看到我的推。由于我经常发推,因此从我的 Twitter 记录中可以看到我的生活。这样我父母能更放心一些。

我写 tweets-page 是从 2009 年 7 月开始的。那个时候我刚刚回国,Twitter 已经被封锁了。当时我和家人在北京的饭店住着,父母正好有假期,准备带我在北京转转,看看鸟巢等新建设的地方。我因为时差关系到凌晨三点多就睡不着了。自己住在一间客房里没事干,又不想看电视,于是就想解决从国内上 Twitter 的问题。一开始时我用 ssh -D 给自己开个通道用,一会后嫌麻烦,因为代理的速度不高,一些国内的页面用代理会更慢,而且每次开代理还麻烦(那时我还不会 screen)。所以我就自己写了一个程序,让我可以浏览 Twitter 并发布新推。当时的代码怎么写的我早就忘了,好像也没有备份。浏览了一下当时的推特记录,说是用的 Perl 调用 curl 来用官方的 API 来更新,印象里时一个 CGI 小程序,非常简陋,还有不少的问题,当时仅仅是临时用用。

然后回加拿大后,我用 Ruby 写了一个小程序,通过 twitter4r 来获取我的 tweets,保存在数据库中,然后用程序生成页面浏览。API 在那时已经不支持 since 参数了,我只能从某个时间段开始抓取,之前的内容就只好放弃。程序最终写成了,不过我当时对服务器的知识太少,用的还是 Dreamhost 共享主机,最终用 Crontab 让程序定时运行的时候,发现无论怎么样都找不到我用 gem 安装的 twitter4r。如果程序不能定时运行,我每天要登陆到主机上手动执行一遍程序?非常不现实。所以最后我只好放弃,最后的生成结果部分我也懒得弄了。

印象里之后还试过几次,好像都没有成功。

到了 2012 年 5 月,我重新写了一次,结果弄成了。这次用了 Twitter 库和 Sequel,在服务器上我也不再用 SQLite 了,而是用 MySQL。除了保存到数据库之外,它还能在刷新后立即生成输出页面。输出的页面是一个比较大的 HTML 静态文件,我曾经想写一个分页功能的,后来一直没有兴趣碰它。在解决了 Crontab 的问题后,它就一直在我的服务器上工作着,一直到了现在。

当我看到了 Twitter 可以导出的消息后,我就导出了我的记录。看着一个几兆大小的 CSV 文件,我有了把它们添加进我的数据库的想法。于是就尝试了一下,中间也遇到了一些小问题。

开始时我觉得 CSV 文件没有什么难度的,于是就直接读取一行,用逗号拆分。但输出的时候我发现了几个空行,查看了一下原来 CSV 文件并不是严格的每行是一条记录的。记录中有的值有换行符,体现在 CSV 文件中就是直接的换行,我按行处理就会出错。我当时的想法是不要这些有问题的条目了,不过它们太多、太分散,我没有完成。之后我用了 CSV 库,它没有任何问题处理了换行。

第二个问题是时区。导出的 CSV 文件中的发布时间是用的 UTC 时间,看上去是这样的 2013-03-12 01:35:28 +0000。我要把它转换成我所在的时区,于是就做了各种尝试。或许由于 Rails 太火的原因,我搜索到的很多条都是如何在 Rails 里完成的,而不是 Ruby。最后经过尝试,我找到了解决方法。

第三点是如何插入数据库的问题。我开始的想法是直接在 CSV 文件中把我已经保存了的条目删除,然后运行一遍我的程序。现在想想这种方法其实也行,弄进数据库中再排一下序就可以了。不过我当时是直接新建了一个表,导入到这个表后检查结果正常后,就把表改名,跟过去用的表换过来,然后我就有了一个比较大的数据表了。

这次我不想生成静态页面了,为了练习,我改用 PHP 写了一个动态页面。我过去从来没有写过 PHP 程序。之前有想过要学一下 PHP,当时的想法是读别人写的代码,反正 PHP 的语法也不难。但是我悲剧的选了 WordPress,因为它是最流行的 PHP 软件之一。我现在对 PHP 的了解不深,对于 WordPress 的代码写的好坏没什么发言权。不过我觉得 WordPress 的代码非常非常非常不适合初学者用来学习模仿,非常不清晰,几下子就能把人绕晕了。所以我到现在都没有认真学习过 PHP。不过 PHP 在我印象中不难,当然不包括它面向对象的部分。我从网上找了一些它跟 MySQL 合作的介绍,选择了 PDO 方式来操纵数据库,写出了不到一页的代码,很容易的就完成了任务。

新的页面在:http://liuf.net/tweets/

当然这个页面目前其实是比较糟糕的。动态页面每次都要生成,这么多条目导致了这个页面的速度比较慢,要将近 10 秒才能完成。所以有机会我一定会给它安上分页功能,或许加点 JavaScript 来动态载入。

旧的代码我还没有修改,其实我想把它生成页面的部分去掉,单独的干刷新数据库功能。等有机会再说吧。

生成的代码我还没有往 Github 上传,因为当中我直接把数据库的用户名和密码写进代码里了,估计从 git 里回滚几下就能看到。虽然我的数据库仅限 localhost 访问,但还是再考虑一下吧。不过代码库的链接在这里

浏览器还有什么不能干的吗?

过去我对 JavaScript 非常不感冒。原因估计是刚开始学的时候的心理阴影。

最开始在我的印象中,JavaScript 是一种给网页提供动态效果的工具,这跟我一向的“内容最大”的观点相冲突。由于我开始上网后有好几年都只能用慢速的电话线拨号上网,为了节约流量,提升速度,我特别讨厌网页上的花里胡哨的效果,重点关注的只有内容。早期的一些国内的网页,尤其是新浪、搜狐提供的 blog,很多人非常烂俗的在里面添加各种效果,比如动态背景、背景音乐等等,这些在像我这样用慢速网络上网的人来说,绝对是一种灾难,从那时我就对这些东西深恶痛绝。连带着对 JavaScript 的观感也不好了。后来出国后有了高速的互联网连接,但我这种“抠门”的习惯是改不了了。现在我的浏览器也一直用着 NoScript 插件。

我在大学里有一门课,名字叫 Distributed Programming,是讲 web 编程的。讲到 JavaScript 的部分时,老师简单的介绍了一下,并没有像 C 语言之类的深入来讲,让我门自己去看文档。然后布置了一个作业,用 JavaScript 写一个类似 task manager 的程序。我之前从来没有写过 JavaScript 程序,HTML、PHP 等也只是略有接触,最多修改一下 WordPress 插件的水平,于是这次作业写的我简直要吐血,HTML 中每个标签的 attribute 等属性都需要手动试验。而且一个只在浏览器中运行的程序,数据该存在哪里,老师让用 XML,怎么存取,我完全没有概念。

从那以后,我直接绝了自己做前端的想法。本来我对美工就一点不在行,和别人合伙作项目的时候,我都主动要求做服务器端,毕竟只涉及到逻辑方面,至少对我来说很清晰。

因为对 JavaScript 不感冒,我对近年来的一些相关技术都处于比较排斥的态度。比如 NodeJS,我看了它主页上的例子后就觉得它应该是一个用 JavaScript 写的 web.py,里面到底有什么东西我就没看。还有 jQuery,都说它多么多么好,我自己就一次也没有用过。而偏偏最近看的一些开发方面的新闻,这些方面的产品越来越多,所以我开始决定要学 JavaScript。

我现在在看 Crockford on JavaScript 系列的视频,也搜索了一些其它方面的文字资料。

今天在网上偶然发现了 Cloud 9 IDE,让我有种惊讶的感觉。这是一个用 JavaScript 写出来的在线版的 IDE。它不光有编辑器的很多功能,比如语法高亮等、还有自动保存,还可以在线运行 NodeJS、Python、Ruby 程序,甚至还有一个终端,也可以马上看到效果。这一切都做的非常漂亮,界面比如菜单什么的,跟本地的浏览器没什么两样

我不是不知道 JavaScript 可以做这些,但之前的经历让我觉得这些一定要花费非常大的经历,一点一点的来写。所以有这么一个功能让我感觉非常惊讶。这个 IDE 本身是用 NodeJS 写的,Github 上有源代码,我没有深入研究,不过看样子量似乎并不是很大。

近年来浏览器内的软件发展迅速,渐渐的开始形成趋势,Chrome OS 和 Chromebook 就是体现。在移动设备上,很多人用 HTML5 + JS 等来写程序,而不是传统的重型开发语言如 Java 和 Objective C。JavaScript 也显得越来越重要,如果继续排斥它估计我会更加落伍吧。

Logo 语言竟然和 LISP 语言有渊源

前几天看 LISP 资料的时候看到有文章提到 LISP 的分支有 Logo。我当时十分怀疑这个 Logo 是不是我小学时计算机课上讲的用于绘图的 Logo 语言。今天专门看了一下维基百科的介绍,发现这竟然是真的:

Logo的原型来自另一个计算机语言LISP,派普特(Logo 的发明人)修改了LISP的语法使得他更易于阅读。Logo通常被称作没有括号的Lisp

这个事实直让我惊呼“天啊”,没想到我过去一直觉得非常神秘的 LISP 语言,我在小学的时候就有过接触了。当然这个接触距离远了一点,从直观上来看,Logo 和 LISP 有很大的不同,不过如果给每一条 Logo 指令都加上小括号,把里面的中括号也改成小括号,我想它应该跟 LISP 的 S-exp 很像了。

在上世纪九十年代的中国的广大的小学中计算机课的语言竟然跟 LISP 有关,听上去挺天方夜谭的,我想这跟 Logo 简单的构造有很大关系;另外 Logo 是用于绘图的语言,每个实现都包括一个解释环境,并且可以立马在屏幕上把图形绘制出来,这也让 Logo 更加直观、易学。我在小学四年级的时候学校开设了计算机课,刚开始是基础知识和在 WPS 中打字,现在回忆起来接触 Logo 的部分要么是在四年级下学期,要么是在五年级了。当时的印象是 Logo 开始的时候很简单,到后来画一些复杂的图形的时候让我觉得有些吃力。当时老师在课堂上让我们画一些多边形,让我们不要用量角器量角度,要自己推算夹角。小学的时候哪接触过几何啊?所以当时我比较怕这部分,好在考试的时候不考。

印象里是小学的时候我参加了当地少年宫的计算机班,现在记不清有没有在那里继续学 Logo 语言了,不过当时参加了当地的一个小型竞赛,项目包含了 BASIC、Logo 等语言,还有其它的什么东西,我应该是报了这两项。BASIC 的部分是用 BASIC 语言来放音乐,就是 PLAY 命令,要求把一首歌的第一句——“我们是共产主义接班人”用喇叭放出来。Logo 语言让用循环命令加上变量,从小到大并不断修改夹角的画正方形,最后形成一个蜗牛的形状。这些在课上都有讲过,我觉得非常容易,在竞赛场内还很容易的就做出来了。竞赛的时候有电视台来摄像,当我运行用 Logo 画蜗牛程序的时候被记者看到了,还要求我再运行一次让他拍,到后来我还从电视上看到了这个画面。可惜等我第二次去上课的时候老师说找不到我的程序,我的程序就这么丢了。具体原因我现在记不清了,总之跟我们用的 Logo 程序载入程序的错误有关。似乎 Logo 只能载入同一张软盘上的程序,我换了软盘后就没法正常运行。为了解决这一点我在赛场搞来搞去结果莫名的把程序给删除了,我自己也不知道就把程序软盘交上去了。后来我总结应该把 Logo 程序和我自己的程序放在一张软盘里,大概就是这么个情况。由于没有我的程序,我到最后只拿了三等奖。

现在我对 Logo 都忘得差不多了,下载了一个伯克利的 Logo 发行版重新体验了一下简单的绘图,感觉也没什么意思了,我也没有兴趣深入研究。小时候用的 Logo 挺原始的,好像也没有什么输出的概念,也不知道现在的实现能不能导出成类似 ps 的格式,如果可以的话倒是可以当作简单的 METAPOST 来用。

中译版的 SICP 好难读啊

我最早是在上高中时,从王垠的网站上知道了 Scheme 这门编程语言,后来洪峰的一些文章也提到了不少 Scheme 的功能。那时我比较迷恋 Scheme,一方面因为我从来没有接触过函数式编程语言,Scheme 这种用小括号堆砌出来的代码,比起过程式编程语言来说新奇了许多;另一方面也有 LISP 光环带来的效应。所以当我得知了有一本书,名为 Structure and Interpretation of Computer Programs,中文名为《计算机程序的构造和解释》,堪称 Scheme 语言的“圣经”,并且是麻省理工学院计算机系的初等课程教材后,我就一直像一窥这本书的风貌。

那时我似乎就已经听说这本书在网络上有全文可以阅读,但一来我没有自己的计算机,使用网络也不方便;二来我当时的英文水平来阅读这类科技书籍还有些不足,所以我一直没敢深入接触这本书,转攻字数更少的 R5RS——一共 50 页,描述了 Scheme 语言的方方面面,我把它打印了下来,装钉起来慢慢的查字典一个单词一个单词的啃。当时我的感觉是当我看到有不确定含义的词语时,查字典,用笔标记上含义,等积攒了几句话后,整体读下来还是一头雾水。文章的含义都没有吃透,更别提 Scheme 语言本身了。所以这项工作我也没有坚持很久,最后只是在蹲厕所的时候拿上看两眼里面的程序,揣摩语言的含义罢了。

所以当我听说,SICP 这本书被裘宗燕翻译了之后,我心里非常激动。有一次我去一家计算机书籍比较多的小书店,找不到这本书,于是问售货员,被告知这本书因为太冷门,没有存货,不过可以预定。我当然选择预定啦。不久后家里接到书店的电话通知,说是有货了,我于是在一个周末和朋友去把书买了回来。这已经是我上大学后的事情了。

这本书到手后,我阅读后得到一个结论——SICP 果然非常难读。因为我除了一些注释中的小故事外,其它的都看的云里雾里。当时我也没有时间,于是只把这本书当作休闲读物,磨损我自己的脑力。

我出国的时候没有带任何计算机方面的书籍或文章,出国后我还比较想念几本书,其中就包括 SICP。我还特地请母亲从车库里找出这本书,让回国的同学帮我带过来。后来使用英语更多了,阅读一些科技文章也不是那么困难了。于是也渐渐的从网站上看了原版的 SICP。这时我又觉得不对劲了。按照我的经验,这本书开始时我就读的云里雾里,那么就应该从开始往后读啊,可怎么读着读着就觉得这么无聊呢?仔细一看原来这些知识我都知道了啊,于是我就往后翻,翻了很大一部分之后还是觉得简单。当然,中间夹杂了一些数学定理什么的,还有一些题目什么的确实需要一些时间思考,但主题部分绝对不是什么艰深晦涩的东西,那为什么读中文版给我的压力这么大呢?

我仔细的看中文的译文,发现可以用这么一句话来形容:每个字每个词都认识,但练成一句话就是不懂什么意思。或许这话夸张了点,但却给了我类似的感觉。或许文字还算流畅,但就是无法让我理解 Scheme 这门语言。一种说不出的感觉。反之,看了英文原版之后,很多东西都清晰明了了。中国人讲究翻译的境界是信达雅,在这里我觉得差距就在雅上。有些词语是严格翻译过来的,从计算机角度上就非常晦涩。这搞的我都想买一本原版的书了。后来看了亚马逊上的售价,考虑再三我放弃了。这类书我更希望能弄到硬皮本的,也不负它 Wizard Book 的名号了,可惜上百加元的书在我看来完全不可接受。普通版本的要 40 多,我因为有了电子版的全文,因此觉得这也有些不划算。

我之前有时间也翻译过一些东西,当然还没到技术文档的水平,只是一些故事,比如 Python 语言的创始人 Guido van Rossum 写的 Python 历史的一系列文章。今天看来,翻译的相当稚嫩。当然每个词语都翻译好了,句子也算通顺,但整体读下来就是觉得有那么些别扭。因为我不是专业做翻译工作的,那时只是在课余时间来翻译一部分,因此翻译完了就完了,从来没有做过事后调整工作,导致文章仅仅是中学生作文水平的可读性罢了,我自己觉得作为业余历史性质的文献也算是勉强合格了。所以我觉得 SICP 这本中译版应该还有改进的空间。

当然我不是否认老裘的工作。人们普遍认为 SICP 难翻,裘宗燕的译文成果,无论怎么样,也算是里程碑式的成就了。我还买过裘宗燕的另一本书,是 C++ 语言的创始人写的一本官方的教程,我现在对它唯一的印象就是很厚重了,书名我也记不清了。当然那本书我也没有读多少,现在也想不起来译文的质量如何了。说起来我最喜欢的一本中译计算机程序语言类书籍是 Learning Perl,那本书实在是让我觉得妙趣横生、手不释卷。书的厚度也非常优秀,作为入门书籍既精炼、清晰、明确,又有足够的深度,文字也非常吸引人。要不是现在 Perl 不再流行了,我一定随时带着它。

10 分钟写一个 blog 系统

和很多人一样,我第一次听说 Ruby on Rails 的时候知道了“10 分钟内写一个 blog 系统”的视频。Rails 的创始人 David Heinemeier Hansson 边讲边做,七搞八搞,伴随着一声声 “whoops”,一个简单的 blog 就完成了。

我在看这段视频的时候,因为之前没有怎么搞过网络程序,因此可能没有感觉到什么革命般的震撼,但已经挺吃惊了。在当时的我看来 blog 是一个相当复杂的系统了,如果我学会了 Rails 是不是也可以在短时间内写一个 blog 呢?

那之后我有几次想学习 Rails,但一直没有成功。一方面我对 Ruby 还是一知半解。我有 Perl 和 Python 的基础,因此 Ruby 代码对我来说很简单;但同时 Perl 和 Python 的基础又阻碍我学习 Ruby,每次拿起镐头书,看了没几页我就厌烦了。Rails 也是,我可以按照书上的例子在本地上运行程序,但我当时很执着于把程序部署到远程服务器上。那时候我只有一个 Dreamhost 共享空间,后来有了一个 Site 5 的共享空间,在这种环境下一个新手部署 Rails 程序的困难可想而知。几次部署失败后,我就对 Rails 失去了耐心。

几次失败后,我依然十分像学好 Ruby 和 Rails。因为 Confreaks 的关系,我感觉 Ruby 社区非常活跃,而我没法参与进去,让我觉得挺遗憾的。不过我一直没有什么需求,因此也没有什么动力去学习 Rails。这也让我对 Rails 这种稍微有些大的框架有些恐惧的感觉。去年暑假我们要做的项目,我就用 web.py 这种超轻量级的框架而不是 Rails 这种中大型的框架。

这个学期我们软件工程课的学期项目要做一个网络程序,我正好趁着这个机会来把 Rails 重新拾起来。于是这次我扎扎实实的从头开始看《Agile Web Development with Rails》,当然一些基础的东西我扫一眼直接掠过,等到看到讲 MVC 的时候我已经比较清楚了这种网络程序框架的原理了。顺着理解了书上的例子程序后,一切顿时感觉豁然开朗了。不仅仅是 Rails,同类的框架都是有共性的。我之前也试过 Django,和 Rails 一样最后也是无疾而终。但这次理解了 Rails 之后,我感觉 Django 框架也十分明了了。

从我一开始听说 Rails 到现在已经过去了几年时间了,我对网络程序的了解也有了很大的变化,远不是当初的自己可以比的。blog 系统对我来说也早已失去了神秘感,不过是一堆面向用户的对数据库进行操作的借口罢了。给我一定的时间和耐心,写一个 blog 系统是很简单的。而像 Rails 这样的框架可以自动生成框架代码,写一个 blog 系统就更是迅速了。

后来我们根据投票,确定了用 web2py 而不是 Rails 来完成项目。我一开始把 web2py 错当成 web.py 了,觉得是很简单的系统,所以就没怎么在意。后来发现错误后我还一度很惊慌,等静下心来看文档之后菜发现原来 web2py 就是 Rails 的Python 移植。明白了 Rails 的原理后 web2py 就没有什么神秘感了。当然我觉得 web2py 的官方书 写的不如《Agile Web Development with Rails》易读,可能是个人习惯的原因。

按照 web2py 的官方书里的例子弄了一下,我发现用 web2py 写程序相当容易。有了设计之后,把数据库定义输入进去之后基本上程序的框架就有了。然后添加 controller 和 view,其实就是函数和调用,不知不觉中程序就出来了。当然这些只是最基本的功能,更高深的功能我还没有看到,不过都是以这些为基础的。

按照这种思路想了一下,我那时就有了用 web2py 来创建一个简单的 blog 系统的想法,算是验证自己的学习进度。之后又托了一段时间,刚刚我正好没事,就这么弄了一下,也就弄成了,差不多也就 10 到 20 分钟的功夫。当然这个 blog 系统和 WordPress 可没法比,Trackback 和 RSS 输出都没有添加,但 blog 的核心功能都有了。我没有做什么美化工作,目前看上去是这个样子的:

Simple blog

有了这个经验之后,我对于我们的学期项目比较有信心了。不过我对这种程序的未来的信心又减少了。本来我觉得 Rails 这种东西既然这么火,那一定相当了不得,不过弄懂了之后觉得也不过如此,它不会是一个值得深入进行科学研究的方向,那么未来究竟在哪里呢?

用 Emacs LISP 写程序

Mac OS X 下我常用的终端程序中,Terminal.app 和 iTerm 都有一个 command+k 的快捷键,作用是清除终端里的字符,回到只显示一个 shell 提示符的状态。这个操作是终端软件自己的,而不是执行 clear 命令,因此效率上会高一些,在远程终端里尤其明显。而且按两个键远比输入五个字符再按回车要舒服,因此我很快就习惯了这个快捷键了。

我平时喜欢用 emacs 来编辑东西,因此 emacs 经常开着。有时需要使用终端时,我回直接在 emacs 执行 M-x shell 打开一个终端来用。这样一方面方便快捷,另一方面可以像操作 emacs buffer 那样来用 emacs 快捷键移动光标,编辑命令,用起来反而更顺。

但在 emacs 中就没有了 command+k 快捷键可以用了。不仅如此,在 emacs 的shell 里执行 clear 命令也不会清空 shell buffer。所以唯一的办法就是选中全部的文字,然后执行 yank,不过这样也太麻烦了一点。今天我终于觉得忍无可忍,于是就像给 emacs 添加这么个功能。

之前我看过 Xah Lee 写的关于 emacs lisp 的一些文章,Xah 对 elisp 比较推崇,说是用它来做字处理等操作十分方便。原话我找不到了,但 Xah 的意思好像是 elisp 比 Perl 还来得好用。我也看过一些相关的文档,但我自己没有实际用 elisp 写过东西。

我要的功能其实很好实现,在 .emacs 里面加一个 shell-mode 的 hook,设定一个快捷键 M-k,绑定一个清空 buffer 的函数就好了。然后就是这个函数了。我本来以为 emacs 应该有个类似 clear-buffer 之类的函数,但我没有找到,于是就上网找了一个,也放在 .emacs 文件里面。我找的那个函数只是把 buffer 内容都清空了,勉强符合要求。我希望在清空了 buffer 之后还要显示 shell 的提示符。虽然清空后按一下回车键或者直接输入命令也无所谓,但我还是希望稍微完美一些。

在 emacs 中写操作 elisp 的程序很方便。emacs 的操作是由一个一个的 elisp 函数组成的,因此只要把相关的函数给找出来加到 clear-buffer 函数中就行。要找按键对应的函数,用 C-h k 就可以办到了。很容易的,我就得到了最后的结果,也就是在 .emacs 中加入如下代码就达到要求了:


;; M-k clear buffer of shell-mode like Terminal.app
(defun clear-buffer()
  "Kill all of the text in the current buffer."
  (interactive)
  (clipboard-kill-region 1 (point-max))
  (comint-send-input)
  (previous-line)
  (kill-line)
  (end-of-buffer))

(add-hook 'shell-mode-hook
          (lambda ()
            (local-set-key (kbd "M-k") 'clear-buffer)))

我感觉这个 clear-buffer 函数有些琐碎,像为了要实现清空 buffer 后显示 shell 的提示符,我让函数执行一次回车,然后回到上一行,删除这一行,再回到 buffer 的结尾,感觉上做了很多琐碎的工作似的,不知道对于效率有没有影响,不过我测试了之后感觉可以接受,而且我也不知道有没有更好的方式来解决这个问题。

几个星期前我看 RubyConf 2010 的时候,有个视频探讨了用 Ruby 来写一个 Ruby 编辑器的,当中提到用一门语言来写这种语言的编辑器的好处。emacs 就是一个典型的例子,用 elisp 来完成各种操作,用 elisp 很简单的就可以完成各种配置,而且不用重启编辑器,写完了代码后 eval 一下就好了。估计也只有 LISP 可以做到这种效果了吧。

编程语言喜好

一个人对于编程语言也有自己的倾向,我最近和同学一起完成学期项目时,有了深刻的体会。

我们的学期项目是网络课上要求的,让我们写一个socket程序,让几个客户端可以通过服务器来玩NIM游戏。我们第一次小组讨论的时候决定用C来做。我同时修一门计算机组成的课,作业是用C语言写虚拟机。我看了老师给的答案后,感觉有豁然开朗的感觉,一扫以前对C语言的恐惧心理,所以也信心满满的做了起来。

但从开始写到现在,总感觉一些细小的部分在阻挠我。而且一些socket交互相关的问题,比如进程、线程、select函数之类的小问题,也让我相当头疼。因此本来看上去很简单的程序,写到现在还在继续弄。

我之前也写过,我对C语言还没有建立起一种“体系”。我在过去写BASIC和Pascal程序的时候,哪怕不能解决问题,都有一种掌控全局的清晰感觉。而对于C语言,我现在还不行。总有一些小地方,一不注意就会出问题。比如结构体中的字符串,今天也费了我不少功夫才搞清楚,原因是之前我写程序从来不用结构体,因此也不知道C语言具体怎么给里面的字符串分配内存。Pascal没有C语言里的指针这么深刻的概念,所以我对这类问题掌控不明确。

我曾经考虑过:是什么让我过去对BASIC、Pascal等语言有掌控全局的感觉?我写了多少程序才建立起了这种感觉?能不能从这些程序里找出一个最小的必要集合,学新语言的时候就用那种语言把这些问题实现几遍,就能摸透语言的关键并形成习惯呢?可惜我一直没有时间深刻去思考这个问题。在有了答案之前,唯有像无头苍蝇一般,看到什么就练什么,直到哪一天把必要的知识点都“撞”全了。

相反,我对一些不那么流行的语言倒是有挺浓厚的兴趣。之前我们学了Prolog、LISP、我们老师发明的fp、J,这学期我们又接触了Jess。去年冬季我有一门课,名为Programming Language Concepts,专门讲各种编程语言,也用它们来写程序,我就做的不错。和我一起做项目的组员这学期也修这门课,就觉得这门课很难,觉得那些奇怪的语法让他转不过弯来。可他对C语言倒挺熟练的,所以项目里困难的部分,就让他去做了。

今天中午他在复习下午的考试时,问了我几个相关的问题,我都觉得挺简单的,他却一脸迷茫。一些稍微复杂一点的Prolog程序,比如归并排序里的merge,我觉得很容易理解,他却觉得已经难到天了。所以我看编程语言,还是要和人的性格相合啊。

Jess新体会

jess-in-action-cover我们这学期的一门课是专家系统,在课上我们用Jess作为编程语言。我们的老师也算大方,把Jess的作者写的一本书《Jess in Action》全书影印下来给我们看,又把另外一本《Building Expert Systems: Principles, Procedures, and Applications》借给我们看。前几个星期,我因为第二本书是借的,就在一个周末把全书浏览了一遍,写了一篇文章。这个周末,我把第一本书带到学校,看了几章。

我之前其实是不大看重这本书的。因为从书名上看来,这本书主要讲的是Jess语言。而另外一本书题目中有专家系统,显得更大观一些。Jess语言的一些内容是我们课程的前半部分的主要内容之一,因此Jess语言的一些语法之类的东西我们早就在课上学到了。Jess本身对我来说不是难学的语言,因为之前用LISP、Prolog和J写过作业,因此我相信除了Brainfuck一类的语言外,不会再有让我很难接受的语法了。

不过今天扫完了书的前8章后,感觉比之前又有了不同。

首先是一些语言的细节。我们之前对语言的介绍有些“功利”的感觉──主要讲的是专家系统、关于知识的一些概念,Jess只不过是一个辅助的语言。学这门课的人都有用Prolog写作业的经历,因此我一度觉得为什么不用Prolog而是要用Jess来做专家系统呢?而这本书把语言的基石,以及fact、rule相关的一些东西分别细说出来后,对于Jess语言的感觉就更明显了。原先是整个是一团混沌,只知道要做成一样东西需要怎么做;现在则是把这团混沌条理化了。

另外就是也看了在课上老师没有讲的一些东西,比如Rete network之类的属于语言实现的底层的内容。还有JVM的地址空间大小导致Java垃圾回收的效率对Jess程序执行速度的影响等。

看这本书的另一个收获就是Jess的价值。世界上专家系统的外壳很多,知名的除了Jess外,还有public domain的CLIPS。CLIPS是用C语言来实现的,其实抛开一些细节上的改良之外,Jess只不过是用Java把CLIPS再实现一遍罢了。与人工智能仍在实验室之内不同,专家系统则早已被人们用在了各种商业领域(填写报税表、操控仪器、驾驶地铁等)。而涉及到商用领域的编程,Java则明显的比C语言有了很大的优势。

就好比JRuby比CRuby对JVM更友好一样,Jess可以很容易的与Java互动。本来我只是以为Jess由于是用Java实现的关系,可以调用编译成字节码的Java函数。结果没想到两者间的互动远比我想象的深刻,除了函数外,连Java的类都可以在Jess中使用。这样就相当于Java的数据类型可以和Jess互通了,而且书上也有代码展示了在Jess中创建一个Java的HashMap对象,然后往里面hash东西,就和在Java中一样。这样一来,Jess和Java的关系,就不只是我过去想的代码互相调用、通过JDBC操控数据库那么简单了。实际上,书上说用Jess来编写专家系统可以有两种大的方向:一是用Java来写,并调用Jess来完成专家系统部分的运算;二是用Jess来写,并在适度需要的时候调用Java代码。而Java作为一个纯面向对象的语言,用它来写大型商用程序,自然比C语言来的得心应手。

在掌握了Jess的语法后,我总是觉得不如Prolog来得顺手。当然抛开两个语言的底层的不同(比如Jess是forward chaining而Prolog是backward chaining,意味着Jess中几乎不能的递归,而这在Prolog中却是家常便饭)外,主要原因还是Jess的LISP语法有些繁琐。在Jess中添加一个fact,需要放在deffact中,在Prolog中则直接写就行了;定义rule也是如此。不过相比起Jess和Java的关系,Prolog的语法实在是太“惊世骇俗”了。因此Prolog几乎不是一个流行的语言,即使有人用Java实现了jPrologProlog Cafe,但毕竟因为没有完整的模拟Prolog,也没有流行起来。

专家系统领域并不如何开放。现在专家系统方面的顶尖技术都掌握在一些公司手中,研发了新技术后并不公开,因此在学术领域的发展是很落后的。所以我现在也不知道Jess在专家系统领域中处于一个什么地位。不过我估计应该不会很差,因为Jess并不是开源软件。用户需要向开发者付费购买许可证才能把Jess应用到商业软件中(Jess其实就是一个不到700KB的jess.jar文件),学术使用也需要联系开发者申请学术许可证。我们用的Jess都是老师给我们的,而不是我们从网上下载的。我今天中午给开发者写了封邮件,看看能不能申请下载到源代码来研究一下。不过半小时前收到邮件,说我可以获得用于学术的二进制代码,可以使用一年。只能长叹一声:其实我从老师那里得到的版本已经比它多很多了,我要的其实是源代码啊。

最近听说了不少关于编程语言的项目。比如Google的Go,还有VIM作者的Zimbu。不过这群大牛好像没有研究专家系统的,要是能设计个开源的专家系统外壳就好了。