-- MySQL dump 10.13 Distrib 5.1.37, for debian-linux-gnu (i486) -- -- Host: localhost Database: test -- ------------------------------------------------------ -- Server version 5.1.37-1ubuntu5.1 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES latin1 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Dumping data for table `comments` -- LOCK TABLES `comments` WRITE; /*!40000 ALTER TABLE `comments` DISABLE KEYS */; INSERT INTO `comments` VALUES (1,'Cherry',NULL,'http://cherrychuxinyun.spaces.msn.com','期待下一个完美之夜,我们又可以新的完美之旅了~~~','2006-07-07 02:54:00',1),(2,'agentzh',NULL,NULL,'\0\0\0\0','0000-00-00 00:00:00',1),(3,'咩咩',NULL,'http://rebeccanewworld.spaces.msn.com','{\"email\":null,\"body\":\"你是第一个读到我心情短文的朋友,谢谢你的支持呢!加油加油,再加油!即立志,后面一句话怎么说的来着? 总之就是要坚持的意思的啦!:) 我看了你对TUIT的解释,很受用,记下了,而且可以在适当场合小炫一下哦!我保准我周围没有什么人知道呢!嘿嘿... 对了,告诉我一下,空间的版面颜色如何更改吧,虽然绿色心情不错,但是我更希望颜色能温婉一些呢! 还有,沈同学的工作快完成了,他现在去上海学习,也正好可以再思考一下如何做的更完善呢,你看到他做的东西了吗,有什么好的建议和意见,可千万不要保守哦! 好像我都把这个本应做评论的地方当成写电邮的地方了,不过,言及其意就好了','0000-00-00 00:00:00',2),(4,'laye',NULL,'http://layesuen.spaces.msn.com','Learning by copying,\nMaybe I should try, :=D\n\nMy special field now is Natural Language Process (NLP),\nThis field utilizes Perl much as a powerful tool, maybe it\'s a good chance for me to get familiar with Perl :-)','2006-07-22 15:44:00',3),(5,'agentzh',NULL,NULL,'{\"email\":null,\"body\":\"Woot! NLP is a charming area...\\n\\n','0000-00-00 00:00:00',3),(6,'bobby',NULL,'http://bobby316.spaces.live.com/','{\"email\":null,\"body\":\"后来怎么样了','0000-00-00 00:00:00',6),(7,'光磊','guanglei9@yahoo.com.cn',NULL,'{\"email\":\"guanglei9@yahoo.com.cn\",\"body\":\"你好,请问您是不是对CLIPS比较熟悉。我也是刚开始学习这门语言,可是资料非常少,从网上搜索,发现学习这门语言的人也不是太多,希望与你交流一下。如果可能','0000-00-00 00:00:00',11),(8,'光磊',NULL,NULL,'{\"email\":null,\"body\":\"我的邮箱是','0000-00-00 00:00:00',11),(9,'李鲁',NULL,'http://lvbuzhang2000.spaces.live.com/','{\"email\":null,\"body\":\"感觉你','0000-00-00 00:00:00',12),(10,'agentzh',NULL,NULL,'{\"email\":null,\"body\":\"李鲁,真的消极么?不会吧?\\n\\n我一直觉得这才是一个人静下心来*应该*去思索的东西。;-)\\n\\n 激情、快乐,欢笑大多是留给学习、工作、以及身边的朋友和亲人的;\\n至于严肃的人生课题和深入的冥想,那应该是属于自己的。呵呵。\\n\\n好,下回再写几篇激情似火的,哈哈。\\n\\n别忘了我是','0000-00-00 00:00:00',12),(11,'agentzh',NULL,NULL,'沈 Jack 推荐的 MPlayer 比 RealPlayer 好多了(RealPlayer 在播放时很不稳定,经常崩溃),尽管 MPlayer 的解码器和显卡驱动的配置花了我不少额外的工夫,呵呵。','2007-04-18 05:58:00',22),(12,'Anonymous',NULL,NULL,'OMFG. I was getting so frustrated trying to set this up on my own. Thank you very much.','2007-08-09 01:02:00',50),(13,'lobatt',NULL,'http://www.perlfect.org/','{\"email\":null,\"body\":\"过来回拜:)\\n关于你负责测试这个事情,我是在YAPC上获得的信息...不准','0000-00-00 00:00:00',62),(14,'agentzh',NULL,'http://blog.agentzh.org','呵呵,谢谢你的留言 :)','2007-11-27 12:43:00',62),(15,'xinglan',NULL,'http://i.cn.yahoo.com/shi_xinglan','非常好的一篇文章。期待下次崩溃 :)','2007-12-03 03:09:00',65),(16,'cnhackTNT',NULL,'http://wanghui.org','太COOL了!有才。。。','2008-02-19 01:17:32',70),(17,'laye',NULL,'http://layesuen.spaces.live.com','Wow, now I see it fully works,\ncool~','2008-02-20 13:02:23',70),(18,'laye',NULL,'http://layesuen.spaces.live.com',' laye wanna has his blog like this, too @@','2008-02-20 13:06:56',70),(19,'laser','laser@henry',NULL,'0\n \n: \"laser@henry\", \"body\": \"还','0000-00-00 00:00:00',67),(20,'秦歌','8\nr@henry\0\0\0\0ؕ\Z','http://dancewithnet.com','\0\0\0\0d\n\0\0\0?\0\0\0url\0\0\"bo!\0\0\00j\n\n\0\0\0M@`\0\0\0id\0\0a\0\0\0关于利用ajax时解决I','0000-00-00 00:00:00',73),(21,'cnangel','cnangel@126.com','','关注中','2008-04-30 03:28:46',79),(22,'qingyan','qyliu81@sina.com','','good','2008-04-30 03:42:50',79),(23,'shan','wei_san@live.cn','','thank you,i have download it!','2008-05-05 01:20:14',78),(24,'Good','goog@google.com','','Cool!','2008-05-06 11:28:13',79),(82,'della','zdndd@126.com','','so what?','2008-05-09 03:19:16',80),(83,'haha','zdndd@126.com','','haha','2008-05-09 03:31:54',80),(84,'della','zdndd@sohu.com','','ie ','2008-05-09 03:36:06',80),(85,'王承石','2012728@qq.com','http://www.myued.com/','web应用不大现实\n1,javascript开发代价太大\n2,seo\n3,你觉得这种用户体验很好吗?我不这么认为.\n桌面应用还有可能\n1,把页面存到桌面还不如存url,反正也不能离线.\n2,不知以后是否免费提供服务,那样这个东西可能会变成有一个免费的数据库空间而已.\n如果强迫我去使用我宁可用另一个服务器端去做代理处理数据然后控制业务,最后再输出.','2008-05-10 06:20:37',80),(86,'agentzh','agentzh@yahoo.cn','','王承石:\n\n关于 1, 如果是去年的这个时候我或许会赞同你的说法。但现在 Jemplate + jquery.js + openresty.js 已经使得纯 JS 开发变得简单而又充满乐趣 ;) 更何况,JS 本身就是一门非常优美非常强大的语言(当然,也是被误解最深的语言之一了)。\n\n关于 2, 更多的是现有的搜索引擎爬虫的技术限制,而不是我的问题,呵呵。不过有趣的是,Google 的 crawlers 可以通过 OpenResty RSS 爬到我的纯 JS 站的内容,呵呵。\n\n关于 3, 这个 blog 就是用这种技术实现的,不觉得用户体验差到哪儿去(除非用户的浏览器不支持或者禁用了 JS,呵呵)。\n\n关于未来提供免费服务,是一定的。目前如果想在我们yahoo的服务器上注册 openresty 帐号进行试用,可以发电子邮件给我(agentzh@yahoo.cn):)','2008-05-12 02:36:16',80),(96,'doudou586','doudou586@gmail.com','','local test of OpenResty ','2008-05-25 06:22:08',81),(97,'doudou586','doudou586@gmail.com','','One Word Only: Cool !','2008-05-25 06:23:04',81),(98,'Gao Feng','vipeak@gmail.com','','just try.','2008-05-25 12:20:30',80),(99,'ch','chuanwen.chen@alibaba-inc.com','陈','擦色大大地','2008-05-28 03:45:14',81),(100,'色彩地方色彩地方','从现在色彩','层层层','小阿斯对地方','2008-05-28 03:46:31',81),(101,'cnangel','cnangel@yahoo.cn','','good job','2008-05-30 03:16:17',82),(102,'agentzh','agentzh@yahoo.cn','','Just a test','2008-06-01 03:44:47',79),(103,'unique_zxs','zhao_xshg47@126.com','','牛人!!','2008-06-02 03:40:34',81),(104,'cnangel','cnangel@yahoo.cn','','ha, wd4','2008-06-12 02:41:27',83),(105,'倪','xniz@live.cn','','I don\'t know whether you will see it,but I\'d like to tell you that I have always been blieving you are so terrific and strange\nsince I was a child.\nI really hope you can follow your dream and enjoy\nit.------your younger cousin','2008-06-16 05:09:35',43),(106,'Ni Min','nxiz@live.cn','','我必须在每篇看过的你的文章上发表评论,以表示我已认真品读过.\n谢谢你的教导,我一直都很相信并且支持你.','2008-06-16 05:42:39',6),(107,'gfgfgfg','zhao_xshg47@126.com','','haoa','2008-06-16 11:42:03',78),(109,'agentzh','agentzh@yahoo.cn','','Ni Min: thanks, my dear little sister! :)','2008-06-18 05:11:37',6),(110,'agentzh','agentzh@yahoo.cn','','倪: surely I can see your comments :) It is *my* blog site after all *grin* thanks so much :)','2008-06-18 05:13:24',43),(111,'倪','xniz@live.cn','','Thank you for answering me.\nFrankly,I\'m glad to appreciate your passages.By the way,I wonder whether you\'ve seen my e-mail,and I sent it to you on 16th.Bye!','2008-06-18 16:29:10',43),(112,'Ni Min','xniz@live.cn','','我觉得很奇怪,为什么好文章抑或独特的思想没有评论,鄙人生平无他好,惟崇怪才,文章很不错,微微的宣泄中,三分是张扬,剩下七分是无奈,\n个人认为,这是我看的四篇文章中的共性,若有偏颇,望指正并海涵.罢了,我困了,Bye!---倪','2008-06-18 16:52:56',10),(113,'agentzh','agentzh@yahoo.cn','','哈哈,谢谢妹妹的点评,真是算遇上“知音”了,哈哈','2008-06-19 00:44:36',10),(114,'agentzh','agentzh@yahoo.cn','','my dear little sister: i\'ve just found your mail in my gmail\'s spam box...sigh. i\'ve replied to you. hopefully gmail won\'t do the nasty thing again ;)','2008-06-19 00:54:33',43),(115,'Ni Min','xniz@live.cn','',' 这篇文章不禁让我想起你的\"宁舍身命,终不违犯\"中的一句话,这或许是你成功的一要素(个人管见),但这却是我最受益匪浅的,你说,你踏入校园前就已有宏伟的计划,并最终完成了;如今这儿,应该是你在雅虎工作后的新计划吧?(不知是否完成)\n的确,计划很重要,但我想,更重要的应是之后的汗水(这自然是不言而喻的)祝福我有你那份执着吧!Bye!','2008-06-19 05:20:41',54),(116,'agentzh','agentzh@yahoo.cn','','呵呵,好妹妹,最大的成功其实就是每天做自己喜欢做的事情哦 ;) 不要太累了,哈哈,执着也是病。。。','2008-06-20 02:38:26',54),(117,'chen ran','ranhappy1983@yahoo.cn','','看不懂。','2008-07-17 05:32:28',87),(118,'agentzh','agentzh@gmail.com','blog.agentzh.org','Here is the second yahoo.cn application powered by OpenResty:\n\n http://one.cn.yahoo.com/s?p=功夫熊猫&v=web&pid=hp\n\nThe first item in the result list is read from an OpenResty (private) account :)','2008-07-17 09:25:24',86),(119,'agentzh','agentzh@gmail.com','http://blog.agentzh.org','呃。。。好吧。。。','2008-07-17 09:30:51',87),(120,'agentzh','agentzh@gmail.com','','The PL/Perl backend is now stalled since adding functionalities is more important at the moment ;)','2008-07-24 06:17:12',88),(121,'Audrey Tang','audreyt@audreyt.org','','I\'m *very* delighted to see you mature as a Haskell/Perl/Web hacker.\n\nEsp. when you get to put quasiquotes into ~production use before Pugs does! :-)\n\nHappy hacking,\nAudrey ','2008-09-17 03:53:38',92),(124,'agentzh','agentzh@yahoo.cn','http://blog.agentzh.org','Thank you, Audrey! :D\n','2008-09-22 11:58:36',92),(127,'chaoslawful','chaoslawful@gmail.com','','说的太好了,要向agentzh大牛学习!','2008-10-13 06:15:50',96),(128,'agentzh','agentzh@yahoo.cn','','哈哈,谢谢哲大拿的鼓励!','2008-10-13 06:35:38',96),(129,'luoluo','luoluonet@yahoo.cn','','你们两个在互相恭维么…','2008-10-13 07:29:09',96),(130,'RainX','china_1982@163.com','http://rainx.cn','很同意agentzh的看法.. 比如:‘可惜的是,许多人的心是浮动的,而研究和探索需要绝对宁静的心’,‘宁静的心’这样的状态对我来说已经很有难度了.. ','2008-10-13 07:35:12',96),(131,'luyan','yan.lu@alibaba-inc.com','','e688 91e6 98af e69d a5e5 8da0 e6a5 bce7 9a84\n:))','2008-10-13 07:54:37',96),(132,'mallory','grep@yahoo.cn','','学些啦 ','2008-10-13 08:06:56',96),(133,'laruence','laruence@yahoo.com.cn','http://www.laruence.com','附议.','2008-10-13 09:09:16',96),(135,'nb','werewr@gerwr.com','','nb','2008-10-13 09:24:21',96),(136,'junier','zhu_zhu2778@yahoo.com.cn','','果然跟我对agentzh的评价一样,突然想用一个词来概括研究的心态:淡定','2008-10-23 01:04:14',96),(139,'boheling','boheling@hotmail.com','','很有道理,对于现在研究的浮躁和功利深有体会','2008-11-12 11:18:17',96),(140,'ddung','tang.juan@alibaba-inc.com','','good','2008-11-19 07:26:59',96),(141,'ddung','tang.juan@alibaba-inc.com','','good guy','2008-11-19 07:33:00',96),(143,'su27','damn.su@gmail.com','','great, it\'s cool~','2008-12-01 05:34:05',99),(144,'alan','shi_xinglan@yahoo.com.cn','','alan: 发了一封邮件,谢谢你给surfer做了一件好事\nagent: 汗。。。原来只是略微带过啊。。。\nagent:我以为是专题表扬呢。。。\nagent: 浪费我感情了。。。\nalan:你得到的表扬很多啊\nalan:应该已经习惯了\nalan:原来那么在意?一点都不知道隐藏一下。\nagent: 我本是天真烂漫之人。。。隐藏得想起来才会呀\nalan:瀑布寒..............','2008-12-09 10:11:30',99),(145,'laser','laser@henry','www.eeeeworks.org','春儿的这篇东西是所有的东西中最舒服的,尤其是在这样一个冬日暖阳的下午。 :)','2008-12-13 07:57:30',100),(146,'agentzh','agentzh@gmail.com','','laser: 呵呵,好吧。。。以后多写点这种风格的。。。','2008-12-13 08:02:19',100),(147,'Ying','chang_ying61@yahoo.com.cn','','在所谓“悠闲”的时候都在思考数学、AI、工程学……你看那些问题觉得很有趣,我看想这些问题的你也很有趣~~~','2008-12-14 12:59:16',100),(148,'nomas','nomas.chow@gmail.com','www.nomas.cn','好吧。无独有偶!\n\n不过我早写了几年!\n\n但是,意境是这么的不同!\n\n','2008-12-14 13:58:06',100),(149,'smallfish','smallfish@live.cn','http://hi.baidu.com/smallfish7788','冷空气马上要来了哦,冬天晒晒太阳确实是种享受','2008-12-16 09:53:38',100),(150,'Ying','chang_ying61@yahoo.com.cn','','小朋友,可以理解为什么你的作文成绩一直很好了,我们语文老师也喜欢你这样的调调 :D','2008-12-23 03:45:31',1),(151,'ying','chang_ying61@yahoo.com.cn','','很可爱的小朋友~~\n祝你二十年后还有这股劲头儿 :)','2008-12-23 03:53:04',6),(152,'KeepItCool','adrfonseca@gmail.com','','Any developments on the Gecko crawler ?','2008-12-28 15:08:20',97),(153,'agentzh','agentzh@yahoo.cn','','KeepItCool: my Gecko crawlers are already being used in production. I\'ll post a report in English here later. Stay tuned!','2008-12-29 03:03:48',97),(154,'sleetdrop','sleetdrop@gmail.com','http://blog.vetcafe.net','你blog的 rss 出问题了,没有办法订阅,检查一下。','2009-02-12 09:55:03',101),(155,'agentzh','agentzh@yahoo.cn','','Fixed. Thanks!','2009-02-13 04:43:35',101),(156,'weakish','weakish@gmail.com','http://weakish.pigro.net','網站的runtime太fat。google app engine和Amazon EC2說,干脆,把runtime也外包給我們吧。OpenResty說,把runtime外包給用戶的客戶端吧。有意思。\n\n把網站編譯成html+js有意思的。普通用戶要用C的程序,直接用binary就可以了,不需要裝gcc之類的。現在,站長要做動態的網站,復雜的邏輯,也不需要fcgi/cgi+database這類東西了,站長真是越來越懶了。\n\n客戶端方面,現在正常用戶的瀏覽器都支持javascript了。某些不願意安裝X windows,在純console下工作的變態用戶,用wget把網頁下載下來,轉成文本文件用Emacs打開,發現幾乎是啥也沒有。然後也許他就歎口氣放棄了,也許開始看看HTML,然後也許歎口氣開始裝X windows,或者用lisp寫Emacs插件訪問openResty的api來抓取、提交數據。手機用戶也不是問題,現在的手機越來越強。使用老爺手機的,既然網站可以提供RSS,提供一個wml也不是難事吧。(當然他們還是很可憐的,只能讀了,不能提交內容了,沒有傳統的html form了。)\n\n更有意思的是分布式。分發也有意思的。可以做分布式的網站。傳統網站都是通過http發布的,但是基於OpenResty的網站,隨便怎麼發布都可以,http/ftp,甚至email,閃存盤拷貝都可以。不僅是分發是分布式的,開發也是分布式的。站長和用戶的界限模糊了。用戶不需要架server,配置數據庫,甚至不需要站長的同意,就可以直接改站點。甚至可以把整個站放到git/hg/darcs之類的DSCM。普通用戶直接訪問站長的http,可能會在本地做一些小的修改以適合自己的需要,如果覺得這些修改對大多數人有用,可以提交一個patch給站長。比較active的用戶可以fork一個自己的站。然後包括站長在內的所有用戶之間可以互相pull,push,merge,cherry-picking changesets。\n\n又窮又懶的小站長用了免費的OpenResty服務,根本不需要出錢買空間了。整個網站打個包,放到隨便哪個免費host文件的站,讓別人去下載就是了。界面也不用多推敲,反正可能有熱心的用戶幫著做。\n\n懶但是不窮的中站長,用上付費的OpenResty服務,然後很多scale的問題就都不用考慮了。大多數用戶讓訪問主站點,小部分活躍用戶讓他們訪問alpha.example.com,鼓勵他們反饋意見,甚至直接提交修改的版本,給上相應的獎勵。\n\npost modern web 2.0,用戶提交的不僅僅是內容。web 2.5?\n\n不懶的站長從cpan上把OpenResty下載下來,然後就開始研究怎麼定制以更符合自己的需求,然後部署在自建的集群上。','2009-02-13 15:52:16',80),(157,'Vagn Johansen','gonz808@hotmail.com','','It is not possible to subscribe to your RSS feed. I get a plain page with:\n\n{\"success\":0,\"error\":\"Login required.\"}','2009-02-14 11:07:03',102),(158,'agentzh','agentzh@yahoo.cn','','I\'ve removed the querystring part from the RSS url, which now reads\n\n http://api.eeeeworks.org/=/feed/Post/_user/agentzh.Public\n\nHopefully it fixed the \"Login required\" issue in your RSS subscriber.\n\nThanks!\n','2009-02-15 12:40:41',102),(159,'agentzh','agentzh@yahoo.cn','','weakish: 啊啊啊。。。遇见知音了!多谢你对 OpenResty 思想的诠释! :D','2009-02-15 12:46:54',80),(160,'yu','xieyu2005@gmail.com','','只能用FF3.1吗?','2009-02-23 08:00:09',101),(161,'一','huiren1021@163.com','','很好的感想啊 ','2009-02-23 09:09:03',9),(162,'agentzh','agentzh@yahoo.cn','','yu: Firefox 3.0 和 2.0 当然也可以啦。。。呵呵,只不过性能要差很多 :)','2009-02-23 12:33:43',101),(163,'Datou','2simple@gmail.com','http://2simple.cn/','如何保存新内容?','2009-02-24 01:27:53',94),(164,'Datou','2simple@gmail.com','http://2simple.cn/','哦,通过第三方服务器api.eeeeworks.org\n\n有意思','2009-02-24 01:29:37',94),(165,'lily','linizou@126.com','http://blog.linizou.com','学问难做,因为很难平静','2009-03-04 05:46:01',96),(166,'smallfish','perluo777@gmail.com','http://hi.baidu.com/smallfish7788','正在看Apache模块开发指南,看完再仔细阅读下你的源码。\n\n代码注释不多 :)','2009-03-06 01:58:42',103),(167,'agentzh','agentzh@gmail.com','','smallfish:\n> 正在看Apache模块开发指南,看完再仔细阅读下你的源码。\n\n好极!\n\n> 代码注释不多 :) \n\n注释确实少了一些,patches welcome! ;)','2009-03-06 02:45:52',103),(168,'smallfish','perluo777@gmail.com','http://hi.baidu.com/smallfish7788','http://bbs3.chinaunix.net/thread-1255594-1-1.html\nApache模块helloworld习作,有待继续研究,哈 :-)\n','2009-03-06 02:51:07',103),(170,'cnangel','cnangel@126.com','','顶一下,最近好忙~~ ','2009-04-10 06:45:54',104),(171,'kindy','kindy61@gmail.com','','这篇新文章 rss 里没看到,\nhttp://api.eeeeworks.org/=/feed/Post/count/100?user=agentzh.Public\n\n返回了这个:\n\n{\"success\":0,\"error\":\"Login required.\"}\n\n咋搞。','2009-04-10 07:50:40',104),(172,'agentzh','agentzh@gmail.com','','kindy:\n\nOpenResty\'s Feed API has changed for a while now. Please re-subscribe to this blog throught the following RSS link:\n\nhttp://api.eeeeworks.org/=/feed/Post/_user/agentzh.Public\n\nAnd the subscription link on this site has already been updated. Thanks :)','2009-04-10 08:02:16',104),(173,'cnangel','cnangel@gmail.com','','your feel look like well. haha... ','2009-04-28 06:17:03',106),(174,'cnangel','cnangel@gmail.com','','i eat the crab firstly. heihei...','2009-04-28 06:17:54',105),(175,'gosber','freeda.ma@gmail.com','','你的rss订阅需要login','2009-04-29 02:29:57',106),(176,'agentzh','agentzh@gmail.com','','gosber: 多谢提醒,已修复 :)','2009-04-30 10:59:23',106),(177,'Mountain','mingli.yuan@gmail.com','http://www.mingli-yuan.info/','难得有这样的心境,好好珍惜自己年轻时的岁月吧。','2009-05-02 03:45:08',100),(178,'Winter','winter_lb@yahoo.com.cn','','仔细拜读了!\n牛人就在我身边啊!','2009-09-01 14:50:57',101),(179,'agentzh','agentzh@gmail.com','','Winter: 呵呵,过奖了,我们后来已经全面升迁到了 WebKit + VDOM 集群了,性能相比这个 Firefox cluster 有了近一个数量级的提升 :D','2009-09-02 09:33:53',101); /*!40000 ALTER TABLE `comments` ENABLE KEYS */; UNLOCK TABLES; -- -- Dumping data for table `posts` -- LOCK TABLES `posts` WRITE; /*!40000 ALTER TABLE `posts` DISABLE KEYS */; INSERT INTO `posts` VALUES (1,'完美之夜,完美之旅','
傍晚,在教工用完晚餐,我独自一人于江大校园中漫步。那真是一个美妙的黄昏,凉爽得让我觉得不可思议。站在高处,迎着习习凉风,望着远处的坡地与江水,思忖着与 Cherry 的骑车之约。如是主意已定,便立马上了 19 路,赶回城去。

20:00 终于在市政府门前迎来了 Cherry。她身着黑色的T-shirt,在夜晚显得愈加端庄与美丽。于是我们结伴而行。晚上的镇江有些令人捉摸不透,我们在转过几个弯后却惊异地发现又几乎回到了原地。当时,我的确颇感狼狈,幸好她并没有一点儿怪罪我的意思。如是顺着长江路一直西行,这才步入正轨。

与她同行,不必担心冷场与寂寞。她仍像多年前那般健谈。她嘴中总有说不完的有趣的事情——我想到了“开心果”,呵呵。我们于是一路尽情地笑着,有时甚至引得路人侧目。我们聊孙昕,我们聊徐胖胖,我们聊高中老师……一切往事都融入到了清凉的夏夜中,化作丝丝笑语,令人回味,教人陶醉……

路上行人不多,奇怪得很。不过,我们偶尔也会遇见赶“夜会”的人。他们多聚在桥头,亭边,或歌舞,或攀谈,或嬉笑:如是纳凉却也快活自在。在我眼中,他们的出现并没有搅乱这夜的清朗,反而愈凸现出这夜的宁静。凡到此处,我们都不停留,径直从他们身旁轻轻擦过……

不觉我们已来到镇扬汽渡前。高大的收费站阻碍了我们眺望润扬大桥的视线。然而毕竟,我们是来看桥的。于是继续前行。在两旁高大的路灯的照耀下,我们骑上了大桥的引桥。这儿看不见车辆,看不见路人,于是,便成了我们自由驰骋的乐园。在引桥的高处,我们停下,或俯视桥下开阔的高速公路在昏黄的路灯下的倩影,或眺望着远处由一串灯火勾勒出的长江大桥的雄姿,抑或举首仰望那明月稀星,朗朗夜空……一切仿佛都在这一刻凝固。

夜凉如水。这真是夏夜么?呵,完美之夜,完美之旅。
\"\"\"\"
','agentzh','2006-07-07 04:29:00',3),(2,'tuits是什么?','

我在网上经常看到程序员们(当然还有许多非程序员)在他们的电子邮件、IRC 聊天信息以及文档中广泛地使用 tuits 这个词,可是一般的字典里无论如何也查不到,即便是网络字典中也难觅其踪迹。tuits 的典型的用法如下:\n

    A> Will you work on that project?\n    B> Well, as soon as i have the tuits.
\n

再比如,\n

    A> Oh, i\'m exhausted. i don\'t think i have the tuits to finish the job today!\n    B> alas...
\n

But what do tuits mean? What are tuits?\n

其实从这些应用实例我们多少可以猜出,tuits 有“时间“、”灵感“、或者”动机”之类的意思。来自 libwww-perl 邮件组的美国程序员们可以证实我们的猜测:\n

邮件1\n

邮件2\n

有趣的是,后一个链接指向 Perl 语言之父 Larry Wall 对 tuits 的诠释。\n

从这些邮件不难看到,tuits 一词起源于短语 round tuit, 而 round tuit 又起源于下面这句话:\n

   I\'ll do that when I get around to it.
\n

这里搭配用法 get around to 意为“抽出时间做某事或者考虑某事”。显然,to it 一融合便成了 tuit,呵呵。是不是太过分了一点儿?\n

en.wikipedia.org 网站上对 round tuit 的定义进一步证实了上面的说法:\n

A round tuit is an imaginary object whose name is derived from the phrase ``when I get around to it\'\'.\n

我们看到,英语中的不少词汇也是很值得细细品味的。呵呵

\"\"\"\"
','agentzh','2006-07-06 18:27:00',1),(3,'抄写 Perl 6 的 Synopses','

今天下午,我继续在母亲办公室中抄写 Perl 6 的核心文档。好不容易才抄完了 S02 (Synopsis 2),然后又预览了 S03 的前几页。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

抄书确实有抄书的妙处。眼到,手到,心到。高一的时候,正是凭借抄书,我才得以在很短的时间内掌握了 VB, C 和 C++. 抄书与看书相比,缺点是苦了我的手指,优点是重要细节都不会疏漏。抄书可以强制性地放缓我的阅读速度,从而为每一句话都赢得了更多的思考时间,这的确是一件很好的事情。别看抄书似乎进度很慢,但从效果上看,却是大大地节约了时间。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

之所以如此较真地学习 Perl 6,是因为我太想尽快掌握下一代的 Perl 语言了。多年来,接触了数不清的编程语言,可唯独 Perl 5 成为我“真正的语言”。如今,Perl 6 对 Perl 进行了重新的设计,抛弃了语言层面上的向后兼容性,从而给我们 Perl 社会带来了真正意义的“革命”。我很高兴地看到,许多 Perl 5 中令人不快的阴暗角落在 Perl 6 中都成为了宽敞明亮的殿堂。Perl 5 中令人陶醉的语言特性在 Perl 6 中都进化到了令人叹为观止的地步。如果说,Perl 5 带给我们的是魔法世界的话,Perl 6 带给我们的则是真实的神话。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

抄写 S02 的过程对我来说是不断拍案的过程,相信 S03, S04, ... 惊喜还会不断延续。虽然大部分 Perl 6 的新特性我在过去的两年中早有所闻,但是经过抄写 Synopses 这样的如此近距离的接触,我对 Perl 6 的巨大威力有了更加深切的体会。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

随着 v6-alpha,这个基于纯 Perl 5 的 Perl 6 编译器正在通过 Pugs 测试集中越来越多的测试,我学习 Perl 6 的愿望也越来越强烈起来。说实话,作为 v6-alpha 的用户本身就是一个很激动人心的事情了,但是我希望自己能进一步成为 v6-alpha 的贡献者之一,从而能够帮助台湾的 clkao (高嘉良)和巴西的 fglock 让 v6-alpha 更快地成熟起来。\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n

现在我已经从 audreyt(唐凤)那里获得了 Pugs 项目的 commit bit,成为了 Pugs 团队的一员。虽然我可以直接上传改动了,但我仍然缺少相关的背景知识。首先,我得熟悉 Perl 6,从而知道我们到底要实现什么;其次,我得消化 fglock 的 Pugs::Compiler::RulePugs::Compiler::Perl6 以及 clkao 的 Data::BindSub::Multi, 当然还有 Stevan 的 Moose 和 Ingy 的 Module::Compile,从而知晓他们是如何实现的. 最后,我才可能真正参与到 v6-alpha 的开发工作中去.

\"\"\"\"
','agentzh','2006-07-18 13:59:00',2),(4,'Notes for this fortnight (2006-09-21 ~ 2006-09-30)','

Sep 21 (to Sun Xin~)

our charming XML instructor today asked me to give one or two talks in her class because she thought i was an expert in this domain. i\'m very excited and have decided to make some good-looking slides in both english and chinese. i\'ll work on the new slides for the coming talks in the next few days. i\'ll send them to you for review once they are ready.

i\'ll also send you a bunch of _old_slides_ for the talk given in the last term tomorrow. they\'re in pure english and most of my classmates liked it. i hope you can proofread the old slides since i\'m going to publish them on the web.

Our XML instructor is so beautiful that i dare say a lot of boys in the classroom like her very much. she holds great charm for me. i love to talk to her after the class. talking to her in person is really enjoyable. she is an extremely lovely girl. yay for her beauty and good mood!

Sep 22 (to Sun Xin~)

mails sent. remember to use Firefox to access the .xul URL (i.e. the slides) and don\'t click too fast while reading the slides since loading images can be slow.

btw, i\'ll use cherry\'s qzone blogs as a study case in my new slides for the XML talk. the slide-making process can be fun! stay tuned! :)

Sep 22 (to Jack Shen~)

hey, jack. let me talk about microcosmic stuff, such as interface design for individual classes or small class library and you talk about the handwavy macroscopical things like large OO systems. i\'ll try my best to put enough basic weapons under the audience\'s belt before your lectures. what\'s your opinion?

Sep 23 (to Sun Xin~)

my instructors have asked me to give for total 12 talks this semester. that\'s really wonderful since i can take a more leisure pace during my talks. but i definitely need many more slides and pictures. i\'ll be talking about XML, Regular expressions (regexes) and object-oriented modeling and design. what cool stuff!

Sep 27 (to Sun Xin~)

i\'ve produced 82 slides these two days, and i am about to crash... for my first talk, there are still 20 slides to go... it\'s really exciting!!! man!!!

man, i\'ve sent a weird english poetry to you for translating. i need the chinese transcriptfor my slides. please get back to me ASAP. it\'s quite urgent since the talk is scheduled on*this* Friday evening. thank you in advance. :)

Sep 27 (to Cherry Chu~)

our XML teacher has asked me to give one or two talks to my classmates in her class. and i am going to use *your* Qzone blogs as a study case in my slides. :)

will you mind my introduction to your Qzone home? btw, an even shorter URL is working now: http://perlcabal.org/agent/cherry.html. feel free to give it a shot.

...glad to hear that. i have 16 lectures to give out this semester. i\'ve been busy making slides for my talks. it is a hard job but is also fun. :)

Sep 29 (to Sun Xin~)

the talk was a big success. the audience laughed a lot and i was often stopped by the girl students\' ``wow\'\'. my instructor said after the talk that he was exceedingly impressed. he told me that it had given him great inspiration and determination. he said he had even been pondering giving up his C.S. career, but my talk completely changed his mind.

...nah. cherry didn\'t come because she is in a different department and i had not invited her to my talk.

...sorry, i didn\'t show your transcript explicitly in my slides. Audrey offered a translation in ancient chinese right before the talk and i used hers. but your work had helped me a lot. without your translation, i can\'t grok that poem to such an extend. thank you!

it\'s worth mentioning that Larry Wall also provided me with an excellent translation in modern english. you know, he is a great linguist. :)

...LOL. lucky indeed. getting so much help and support is like a dream!

Sep 30 (to Cherry Chu~)

Heh, it will rain tomorrow anyway. hopefully the weather will get better when you come back from shanghai. :)

...nope, not that one. i was talking about the art of naming. the talk mentioning yourQzone space will be given on Oct 14, which is about XML in the real world.

Sun Xin asked me last night if cherry had attended my talk. and i explained to him that you are in a different department and sadly i had not sent you an invitation.

The talk was on this Friday evening. and i\'ll give talks at that time for every week from now on. we are at Z101. welcome joining us! 9th and 10th classes. :)

...nah, chinese speech mostly. every slide contains two versions of the content, the chinese version and the english version. and yeah, there\'ll be many students in my class. don\'t worry. :)

it will simply rock if you can come. for another thing, i really hope you can also attend my XML talk because i\'m going to show my classmates your blogs there. he he.

the XML talk has been scheduled at 10504, 7th or 8th class. the concrete date is still undecided. i\'ll tell you once i had talked to our XML instructor. OK?

...(agent does his happy dance.)

the XML talk should be on Thursday afternoon, btw.

cherry, i have the idea of writing journals based on my cellphone messages. it\'s a great source of materials, you know. of course, i won\'t public any messages that i\'ve received from others. for example, your replies will be excluded while my messages to you will probably be shown. what\'s your opinion? will you mind?

\"\"\"\"
','agentzh','2006-10-17 13:29:00',0),(5,'Notes for this fortnight (2006-10-01 ~ 2006-10-16)','

Oct 1 (to Sun Xin~)

Please check out your mailbox. i sent one journal and 107 slides to you for proofreading yesterday. remember that i\'ve said i would try my best to keep you relatively busy? :)

Oct 4 (to Sal Zhong~)

I\'ve rewritten your Win32::xul2ppt_mec module using Win32::OLE and stevan\'s excellent Moose module. Now it\'s named XUL::Image::PPT and the xul2ppt utility has been divided into two separate tools, xul2img.pl and img2ppt.pl. Please check out http://svn.berlios.de/svnroot/repos/unisimu/Perl/XUL-Image-PPT/ for the source code. :)

Regarding the new xul2img utility, the --count and --title options are required. use --help to see the usage. because the XUL => image part is still based on Win32::GuiTest, the user interface is somewhat fragile and cannot be as nice as that of img2ppt. it\'s still the user\'s responsibility to open .xul with firefox and not to enter the full view mode (via F11) before running the xul2img tool.

Delay settings like 0.5 sec should also work now since i\'ve switched to Time::HiRes\'s sleep function. btw, Moose is so cool that writing perl 5 OO code has been exceedingly enjoyable. you know, perl 5\'s OO was ever a weak or even boring part in the past. Moose has brought me the feeling of using Perl 6 *today*. So don\'t hesitate and give it a shot! Enjoy~

(agentzh mooses.)

Oct 5 (to Sun Xin~)

Currently i am making slides for my XML talk. the topic is ``XML in the real world\'\'. will send the slides to you for review once they\'re ready. :)

Oct 6 (to Cherry Chu~)

I will send you a message when i get up tomorrow morning. please keep your phone on, OK? if you get up earlier than i, would you please inform me via a message? thank you. :)

Oct 6 (to Jack Shen~)

The slides for my XML talk are ready now. please check out your mailbox for details. the slides contain a lot of pretty pictures. i\'ve covered hot topics like RSS and AJAX using Google Reader, the Qzone site, and my GetQzone utility as study cases. these topics are extremely exciting! comments on my slides will be appreciated. :) i hope miss zheng will be kind enough to give me more time to explain everything in my slides...hehe.

Oct 7 (to Cherry Chu~)

cherry: moose. :)

cherry: elk! :D

I\'m now heading out. :) 7:15 AM. don\'t be late, cherry.

...yay! cherry++ i\'m already waiting for you. :)

...i am home now, cherry! yay! ...I was walking pretty fast. hehe. have a good rest. hopefully you will regain your strength soon. :)

Take care and sleep early, cherry. gotta run to shower and sleep myself. G\'night &

Oct 8 (to Sun Xin~)

Cherry and i rode to the yangzhou city yesterday. we favored small roads in the fields over big ones. as a result, we were often followed by barking dogs and blocked by rivers and fields in our way. it was frustrating but also fun. she was amazingly vigorous and charming yesterday...we talked very happily and laughed a lot. you know, it was quite amusing to see she also talked and laughed very loudly, just like me! yay! hooray for cherry\'s beauty and the enormous parallels between us! hehe.

we\'ve decided to ride to other cities in the next few times. but it\'s still undecided which city to go first. what\'s your opinion, man? ;-)

Oct 8 (to Cherry Chu~)

how are you today? i am still a bit tired. sigh.

...wow, nice to hear that. btw, i\'m happy to see my friend laye has replied to your journal. he\'s a talented programmer and now studying in the Fudan university. :) And your ``journal of 70 kilometers\'\' post reads very well! :)

...nod nod. he was in ujs when he was an undergraduate student. sadly we have never met in person. :(

Oct 9 (to Sal Zhong and Jack Shen~)

Yay! now i can do Java Swing programming in pure perl 5! furthermore, my perl interpreter can now learn new Java libraries all by itself. so i can manipulate *any* Java classes and objects as if they were implemented directly in perl 5. thanks to Inline::Java and Java::Swing. now i\'m trying to get them work with pugs (i.e. perl 6). unfortunately, pugs doesn\'t do auto-importing for perl 5 modules. sigh. maybe i need to write some perl 5 wrappers and glue code there. oh, well...

Oct 9 (to Sal Zhong~)

huh! google++

i will definitely look into its shiny source code search engine the other day. thanks for the info. :)

Oct 9 (to Sun Xin~)

man, i\'ll (selectively) translate these notes myself because i don\'t want to occupy too much of your spare time. anyway, i can do the translation work more easily and more accurately. would you please proofread both my english and chinese transcripts for me? i\'ll be very grateful to your review! ;)

Oct 10 (to Jack Shen~)

I\'ve nailed down the basic syntax of the SXML language. it looks pretty neat. i\'ll implement converters for XML <=> SXML and HTML <=> SXML. i believe it\'s important enough for both XML\'s human reading and human writing.

Oct 10 (to Cherry Chu~)

Moose. will you come to my class this friday evening? :)

Oct 16 (to Sal Zhong~)

jerry gay (the guy also known as particle) is rewriting my smartlinks.pl using Moose . it\'s really wonderful! he will commit the code to the parrot repos. He said he would introduce smartlinks to the parrot test suite and link the tests to both the Perl 6 Spec and the parrot PDDs. not sure if he still has the crazy plan to port smartlinks.pl to PIR. anyway, as christopher said, the idea of smartlinking has inspired several add-on hacks. hooray!

btw, pugs 6.2.13 is going to release tomorrow. larry is using pugs for his $work! sweet...

\"\"\"\"
','agentzh','2006-10-17 13:29:00',0),(6,'宁舍身命,终不违犯','
“要么不学,要学就把它学好。”

这是从我年幼时代就定下的原则。我好不容易在初三时代重新定位了自己的学习方式和目的,因此在任何时候我都不愿向应试教育屈服,即便是损失学位,损失学费,损失时间。

我几乎无法忍受学校里的很多做法。凭什么要求我们学习数量如此惊人的本科课程?凭什么找一些连教师们都一知半解的高深的理论来压我们?凭什么那么多门课都要考那些需要死记硬背,迂腐无用的题目?

我的家人都劝我变通一些,圆滑一些,但打死我我也不干。我不愿浪费自己哪怕一分钟的时间。

具有讽刺意味的是,如今我正在给我们专业大四的本科生以及研究生上课,连老师们都说收获很大。可是我自己这边却有一些课程需要重修,需要补考。我的成绩单上也有许多 90 分以上的科目,那是因为那些科目我有时间好好琢磨了。其实学校开的所有科目都有属于自己的美妙天地,但是我根本无暇探索。因此,我显然需要更多的时间来完成自己的学业。说我比别人笨也好,比别人懒也罢,反正我就是来不及。4 年时间学校要求我们涉猎如此之广,如此之深,可为什么许多计算机专业的研究生们出来仍是表现平平?为什么我身边的同学们在找工作的时候仍然感叹自己四年未有多少收获?这些都是值得那些制定教学大纲、安排本科课程的人仔细反思的。

从我个人来说,大学四年真的没什么遗憾,我积累了许多有用的计算机方面的知识和技术,开发了众多的有趣项目,阅读了许多学科的英文版教材,又积累了不少幻灯片制做、演讲、以及计算机专业教学方面的实践经验。所以我完全没必要为了 4 年毕业而破坏原则,完全没必要为了抢时间而玩命干。通过计算机专业的学习,其实我已经学到了我想学的东西,已经实现了最初进大学时制定的宏伟目标和学习计划。其实,我已经很满意了。呵呵。说实话,毕业证书和学位对我而说真的没有太大的意义,因为我早超越过去了。

今天之所以写了这么多抱怨的话,是因为刚刚和一个专业课老师商量能否用科研项目代替那个值得诅咒的考试,居然被他拒绝了!好啊,没关系,反正我是没时间去学的。教我去背考题,连门儿都没有。到时间交白卷,直接让我重修得了。那样多痛快啊~~~呵呵。

坚持这个原则,的确让我感到很有自信,让我不怕任何困难。我非常希望我也能在生活上建立起相应的个人原则,做一个正派的人,做一个高尚的人,做一个有智慧的人。:)

\"\"\"\"
','agentzh','2006-10-23 08:59:00',4),(7,'Notes for this fortnight (2006-10-18 ~ 2006-10-30)','

Oct 18 (to Jack Shen~)

I wrote a UML class diagram generator based on GraphViz. it can parse arbitrary perl OO modules and obtain the inheritance relationships and method/attribute list automatically. it\'s called UML::Class::Simple. And it\'s much easier to use than StarUML . you know, dragging mouse to draw diagrams is really painful. yay for automatic image generation!

(Here is one of the sample outputs: http://svn.berlios.de/svnroot/repos/unisimu/fast.png.)

Oct 18 (to Sal Zhong~)

i\'m planning to upload UML::Class::Simple to cpan once it\'s mature enough. will you test it for me? bug reports and patches are most welcome. :)

it\'s still undecided how to differentiate perl classes\' properties from other ordinary methods. i\'m also pondering the idea of adding relationships other than inheritance. i\'ll be delighted if you have some ideas on these matters.

Note that i\'m ignoring the Autodia module on CPAN since i\'m not in favor of XML and a quite different approach has been taken in my project. anyway, i have to admit it\'s wise to talk to Autodia \'s author and merge these efforts. at last, i must thank Alias for creating PPI and suggesting the use of Class::Inspector. they\'re invaluable when one wants to extract meta info from the perl world.

Oct 19 (to Jack Shen~)

I\'ve merely finished the slides for recap. they already reach the amount of 44 and the number is still counting. alas, still wondering what to say in the next talk on the design of methods and subroutines. :(

Oct 19 (to Cherry Chu~)

Thanks. the talk went pretty well. it\'s interesting to see that i had the feeling just before the talk that you would not come. so i was not very surprised by your absence. no problem, there\'s always ``the next time\'\'. :)

i\'ve been busy making slides for tomorrow\'s talk. they\'re still not finished yet. sigh. have to make more slides during the daytime tomorrow. producing so many slides is quickly getting tedious. hehe, you know that feeling, right? ;-)

Oct 20 (to Cherry Chu~)

这几天每天都要上讲台,而且一上就是 2 节,感觉好累哦。 不过上课时也时常有灵感出现,把平时很多只能意会的东西概念化、理论化, 从而也就可以很好地传达给我们学院的同学们了。

另外就是做了许多幻灯片,它们像是连环画,又像是小小说,都很精致, 都很漂亮。它们是我从高一开始积累的编程思想的一些汇总与整理,真是有趣的很哦~ 我的朋友们上过我的课后都说收获很大,呵呵, 我觉得再没有什么比这个更让人激动的了。耶!

……谢谢。明天下午还要给我们学院的研究生做一次讲座。振奋哦~~~哈哈!:D

Oct 21 (to He Shan~)

我昨晚的课上得还行么?是不是太悠闲,节奏太缓慢了?

 > 呵呵,虽然这会才看到你的消息,但我的思维却始终没有离开你。我想你的课让
> 我对自己后面的路该如何走,有了全新的认识,就像赵鹏说的有种豁然开朗的感
> 觉。

如此之高的评价我真是担当不起呢。看来我算是遇到知音了。 我最期待有人能对我说:“Oh, great! that\'s really important!”

哈!我想人生最幸福的事莫过于此!

 > 悠闲嘛,开始是觉得有一点慢的感觉,没那么带劲儿,下课了,我还和鹏说,
> 你不知道他充满激情的讲话是多么的有煽动性...后来你就进入状态了,特棒。

Oct 22 (to He Shan~)

 > hi! I\'ve found a book. IT is so nice that i have been
> reading about it all the afternoon. it is great, just
> like an extended version of \"The Practice of
> Programming\". it\'s named \"Code Complete\".

I\'ve got the feeling that you are currently on the *right* way. you\'ll definitely become a good hacker if you keep going. hmm, hopefully you\'ll join us perl camels soon. ;)

 > 真的吗?呵呵,好,我会一直走下去的。现在我真的喜欢上编程了,我对优秀程序员
 > 所具有的品行狂热的向往。谢谢你的鼓励与帮助。耶!

Oct 22 (to Jack Shen~)

 > 用 com 如何向 ppt 插图片?xul2ppt 的 python 版本急需。

LOL. apparently you are not a VB guy. inserting images into ppt slides is straightforward once you know how to record down VBA macros in the PowerPoint environment and browsing the generated code in its VB IDE. Another way to get an answer is searching the web. iirc, the method should be AddPicture or something like that. not sure though, computers are out of my reach right now. :(

 > 知道了~ 我发现 python 在科学计算方面很厉害,有很好的库,
> 我准备用 python 给我爸编程。python 有自己的 matlab 库,
> 但不需装 matlab. 但当然没有 matlab 强大,这点是肯定的,
> 哈哈。

Python is even more powerful than MATLAB, Maple, and Haskell? i doubt that. :)

...I was exclusively hacking on the new tokenizer for Makefile::Parser and completely forgot that i had C# classes tonight. anyway, the next major release of M::P takes precedence over any other things. :)

Oct 23 (to Sal Zhong~)

I\'ve just started to rewrite M::P\'s codebase (which will hopefully be released as M::P 1.00 soon). Yes, it\'s long overdue. I\'ve had a pretty good plan for a scalable and extensible gmake implementation based on M::P for long.

The new M::P API will offer parsing results at two different levels:

  • Makefile DOM tree

    It\'s a syntax-oriented data structure which preserves every single bit of info in the original makefile (including whitespaces and comments). So one can modify some part of the DOM tree, and write the updated makefile back to disk. I think it\'s useful to some GUI apps which want to edit makefiles via menus and is also beneficial to the gmake => PBS translator.

  • Makefile AST

    The AST desugars the handwaving parts of the DOM tree down to a semantic-oriented data structure for make-like tools to ``run\'\' it or for some visualizer (e.g. my Makefile::Graphviz) to depict the underlying dependency relations. For the PBS emitter, I think we should work out a special AST for it since the desugaring must be lossless, much like a program correctness proving system.

I\'m currently working on the M::P tokenizer and will finish the DOM tree constructor these days. The process should be going pretty fast since it is mostly test-driven.

The first goal is to implement the new M::P APIs and get my pgmake utility pass most of the gmake tests so that I can kick M::P 1.00 out of the door.

I\'m stealing a lot of source code and pod from Alias\'s PPI module. I\'ve noticed that the basic structure of PDOM trees can also fit my needs very well. it\'s called MDOM in my M::P though. ;-)

Oct 24 (to Sun Xin~)

Take care. translating may drive you mad some day. just have appropriate amount of fun, dude!

Oct 26 (to Jack Shen and Sal Zhong~)

my gnu Makefile DOM builder now supports most kinds of rules, 2 flavors of variable assignments, macro interpolations, and various command and comment syntax. Now it\'s trivial to add new node types and extend the DOM parser.

i\'ll add support for double-colon rules, the define/vpath/include/ifeq/ifneq/ifdef/ifndef/... directives, and other missing structures tomorrow. After these additions, the DOM parser will be quite complete and will serve as the solid ground that we keep standing on. constructing the Makefile AST will be much easier if we keep a DOM tree handy.

yay for test-driven development! without TDD or Alias\' PPI , i wouldn\'t have progressed so rapidly. ;-)

Oct 29 (to Sal Zhong~)

When and where shall we take the Java exam?

...Oops, it seems impossible to release UML::Class::Simple tonight. still have several missing features to implement and the pod needs loves too. hmm, christopher may be unhappy since i earlier made the promise to him that i would make the release by *this* weekend. sigh. hopefully i\'ll get some cycles tomorrow.

...nod nod. but i also gotta review the data mining textbooks for the coming exam. furthermore, i\'m planning to hack on two expert systems in the next week. i\'ll be programming in Prolog, CLIPS , and Perl simultaneously, which must be a lot of fun! yay! :D

Oct 30 (to Sal Zhong~)

I\'ve just talked to Alias, the author of PPI , on #perl. he said that i could borrow as much source code from PPI as i would for my Makefile::DOM module. PPI::Element, PPI::Node, PPI::Token, and PPI::Dumper can be reused by my MDOM directly without many changes. i also briefly introduced the two-level ASTs to him and expressed my appreciation of PPI . It has given me plenty of inspiration on how to push my Makefile::Parser further.

\"\"\"\"
','agentzh','2006-10-30 15:29:00',0),(8,'怎样生活','
每天都在奔跑————不好,这不是我想要的生活。

每天都在学习————不好,这也不是我想要的生活。

每天都在工作————不好,这还不是我想要的生活。

我自己究竟想要什么样的生活呢?我不知道。

嗯,或许是那种比较清闲的生活。繁忙让我厌烦,压力让我不悦。

让别人拉着我向前奔跑?天哪,那有什么趣味?

让自己逼着我向前奔跑?嗨,奔跑又是为了什么?

按照“习俗”追求的许多东西,想来根本没有意义。归根究底,仍是放牛娃的逻辑:
学习,成功,娶妻,生子,学习,成功,娶妻,生子……

无聊之极。

极少去思考自己的思考。平日里所谓的思考,想来更多的是一种习惯,一种迷惑。

恶念在心中生起来却浑然不知,甚至乐此不彼。可悲,可叹,可恶!

终日只知愤世嫉俗,殊不知最俗最坏的竟是自己。

妍媸自彼,与我何干!

其实只愿在大部分的时间里,能够真真正正地静下心来,读懂我的灵魂,读懂我的心……

这个世界是虚幻的,我的心也是虚幻的。无奈。

\"\"\"\"
','agentzh','2006-11-10 14:32:00',0),(9,'以苦为乐','
突然发现自己的生活是如此虚幻。疾病和死亡会在任何时候轻松地毁灭原本引以为荣的一切。健康时会全然忘却病时的巨大痛苦,而在病中时会如此羡慕平日里觉得平淡无味的一点一滴。

死亡最终会降临到我的身上,你的身上,他的身上。是啊,年轻人怎么会真正认真地思考老苦和死苦呢?在青年人的眼中,生活像一条彩色的绸带,无限地延伸至未来。逻辑上的老去和死亡,究竟是“逻辑上”的,我们的大脑认同,而我们的心其实不然。

我不敢去追问。不敢去追问学习的意义,追求的意义,生命的意义,以及存在的意义。

我习惯于化苦为乐。我擅长这桩事情。面对很枯燥的学科,我也会想尽各种方法去挖掘它的美,它的本质,让自己能在那里面找到一乐趣,做出一些事情。如此折腾,无非是想为自己学习各门课程寻找一个理由。其实,仅是寻找一个借口。

上大四的今天我还在摆弄高三的几何题,仅仅是因为我想继续高三时搞的一个自动化证明项目。表面看来很酷,深究起来觉得可悲。我还在自己延续高考给我的伤害。我还在自己延续那个可笑的“借口”。

从很小的时候起,我就沉迷在这种游戏之中,而且乐此不疲。不能说我是假装对它们感兴趣。我真的发现了它们的美,我真的喜欢上了包括数学在内的那些原本很讨厌的学科。可又能怎样?我还是不知道它的意义。

确实,在这一连串无休止的游戏中,我积累了许多领域的知识和技术,其中的许多是让我身边的不少同学羡慕的。可那又能怎样?又有什么意义呢?
\n
是啊,我或许有了这些东西,可以更容易地找到工作,更容易地找到比较好的工作。可那只是为了活下去,并没有解释为什么要活下去。

我想过我也许会而且也应该为人类的进步做贡献,让现在的人们,以及我们的后代生活得更好。可是,我看到的现实是,随着物质文明的日益丰富,人的欲望也日益膨胀,人的压力也日益增加,人的道德也日趋滑落,人的生活也越来越不幸福。

毕竟,幸福是一种感觉,而不是一种物质。

看来,我不应该再去“添砖加瓦”了。我们所吹捧的那些科学、那些技术,无法向我解释人生的意义,无法向我解释它们自己的“真正意义”,无法向我解释这个世界这个宇宙的意义。

我在孩童时就渴望知晓星空后面的秘密。这个世界的本质只有一个,生老病死的源头只有一个。我是如此渴望在今生得到它。将自己的时间浪费在那些自己编造的“借口”上,浪费在与这个应试制度作抗争上,实在是无趣的很,实在是可惜的很。

今天的人们似乎更多地是向“外”去求索。于是这才有了天文学、物理学、化学、生物学这些东西。我们喜欢说我们每天都在进步,每天都在接近那个“绝对真理”。可如果我们的方向从一开始就错了怎么办?如果我们历尽千辛万苦,发现自己苦苦追寻的“真理”其实是一场空,怎么办?如果我们在这个过程中,自己把自己毁灭了怎么办?

我们的科学真的在接近真理,而不是在远离真理么?

接近真理的时候,我们的烦恼应该越来越少,我们的品德应该越来越高尚,我们的生活应该越来越幸福。

真正的智慧,只有那些有德行的人才有资格——或者说才有可能获得。真正的智慧应该让我们远离生活中的一切苦恼。

我要看着自己,嗯,紧紧地盯着。看着自己的过失,看着自己的迷惘,看着自己的贪欲。

我要坐着思考,嗯,静静地沉思,思考自己的存在,思考自己的痛苦,思考自己的出路。
\"\"\"\"
','agentzh','2006-11-14 14:21:00',1),(10,'抱怨','

电子政务老师过分……居然在当中打断我……我才讲到第 20 张。一共准备了 58 张呢……

王龙志那小子也跑了……我可是认真地听完了他的演讲了哦。

很高兴的是,开始讲的时候还有几个同学在下面窃窃私语,而当我讲到美国 FirstGov 网站以后, 所有同学都抬起头认真地听我说了。耶~~~感觉好棒哦~~~要的就是这种效果。

我要好好让咱们的老师看看电子政务课应该怎么个上法。全国新闻联播式的一页一页地朗读课件 只是没有教学经验的初学者的方式!上课一定要充满爱心,充满激情,充满乐趣, 这样才能感染听众,这样才能不误人子弟……

有兴趣的朋友请参见我这堂课的幻灯:

http://svn.berlios.de/svnroot/repos/unisimu/Slides/egov/egov.ppt

或者

http://svn.berlios.de/svnroot/repos/unisimu/Slides/egov/egov.pdf

正如我当时在演讲前所说的,幻灯里几乎每一句话都是我自己的。 如有引用,必有双引号标出。 在此之前,我已经听了太多太多大段大段抄袭的演讲。简直都厌烦死了~~~也只有张娣、王龙志, 还有 3 班另一个我叫不出名字的男生讲的还有些东西。还不至于让我感到时间被浪费了。至于 其他人的……简直就是时间“谋杀”……但出于尊重,我一直认真地听完最后一个人的报告。这也算是 给我们老师一个榜样,让她知道什么叫做最基本的尊重。

好在事先我已经给我徒儿、祥子,还有珣新完整地讲解过这套幻灯了。其实我如此认真地准备就 是想在今晚真正向同学演示一些电子政务方面的实实在在、有血有肉的东西。看来我是没有机会 在公共场合完整地讲完这套幻灯了。

事实上,我对我的每一次上台机会都是非常珍惜的。讲台是一个很光辉、很神圣的地方。可悲的是, 许多大学里的职业教师看不到这一点。从我们的许多老师身上我能清晰地感受到一种普遍的沮丧情绪。 似乎他们认为在大学里教书是一种“低就”,是一种“委屈”。

而我从讲课和教学当中却发现了极大的乐趣,这种乐趣不是一般的编程和私人的交流所能比拟的。 那是一种与许多朋友进行思想沟通的美妙场合!

是啊,“与其诅咒黑暗,不如点亮一枝蜡烛。”我希望以我的实际行动作出一些贡献(对自己的, 还有对我的朋友们的)。这样才能让我觉得安心。

与应试教育抗争了这么多年,我真的累了。尽管在这个过程当中也积累了一些东西值得和我的同学们 一起分享。

明天专家系统课程还有一个极有有趣的讲座,有兴趣的同学欢迎光临啊~~~ 周五下午 7、8 节,2212。明天的讲座的幻灯片我昨天就已经准备好了。大约有 94 张。我将通过一 些有趣的例子深入浅出地介绍了我自己设计和实现的一种专家系统编程语言,名为 XClips。我已经和 小万简单地演示过了。他给我的反馈很不错,夸我的 XClips 系统做得“很专业”。好有成就感哦,呵呵。

``Introduction to XClips\'\' 幻灯片的位置如下:

http://svn.berlios.de/svnroot/repos/unisimu/Slides/xclips/xclips.ppt

或者

http://svn.berlios.de/svnroot/repos/unisimu/Slides/xclips/xclips.pdf

欢迎大家批评指正!

虽然这学期我已经给大家和刘一松老师的研究生上了近 10 次大课了(而且还要上一二次),但其中 没有一次是我自己向老师申请的。每一次都是老师邀请我上我才上的。我这个人平日行事虽然好张扬, 但也没到没课找课上的地步。毕竟,每上一堂课,都要做大量的准备工作。而且在讲堂上讲上个 90 分钟 甚至更长是极为耗费体力的。

正如我的朋友蔡玉飞先前警告过我的,我自己这边的重修课还焦头烂额……其实我应该算是这个班上成绩 最差的了。嘿,没关系,不急,咱不急。呵呵。

身边的朋友们不是在找工作,就是在准备考研。就我一个人还不知道以后怎么办。是啊,以后怎么办呢? 没想过。先把眼前的每一件事做完美吧。以后的事情,等以后再说。你说呢?

其实想想生活还是如此美好的,呵呵。有这么多朋友,有这么多有趣的知识和技术…… 珍惜眼前所拥有的一切,不要等失去了再后悔。以一颗感恩的心,面对每一天的生活。

别忘了我可是两“一”老人啊:“一事无成,一文不值。”自己这么认为就足够了。 所谓“举世誉之而不加劝,举世非之而不加沮” ,“定乎内外之分,辨乎荣辱之境” 。 这都是我的座右铭。

呵呵,哲学是好东西啊。许多哲学思想是可以帮助我们开智慧的。这比生命更重要。

没有智慧,那人和禽兽、机器就没什么差别了。所以有些人虽然活着,他的心却已经死了。

在这儿发泄了一通,对不起诸位啊……抱怨可不好哦。关注我博客的同志们会发现,我最近一直 在抱怨。更年期到了?我想主要是因为心情有些郁闷。“内郁于中,自然要发之于外。” 不过有时我觉得我和年纪相仿的同学有代沟,而和小学里的那些孩子们在一块却感觉不到。 其实我还小呢,呵呵。总是这么天真幼稚的。有一句说一句,从不知在别人面前说客气的话,说好听的话 我父母也批评过我好多次了。我就是不愿改。因为我觉得那些很虚伪。真的不喜欢兜圈子。 确实,我一点儿都没长大,而且讨厌长大。很没出息吧?呵呵。话又说回来,要不怎么叫做 “两一老人”呢,呵呵。

其实我妈也是如此啊,呵呵,她到现在都承认自己没长大。真是“有其母必有其子”。

想想我现在过得很幸福,真的。没什么烦恼,没什么寂寞的,也没什么操心的。 只是偶尔会贪心,会不知足,会抱怨一通……

今儿个累了,要休息了…… 明天见……

Zzz

\"\"\"\"
','agentzh','2006-11-16 15:21:00',2),(11,'XClips 与 VRG','

前些日子我本打算为本周的专家系统课程制做两组幻灯片。一组是《Introduction to XClips》,介绍我基于 CLIPS 设计的专家系统编程语言;一组是《Introduction to VRG》,介绍我用 XClips 语言编写的 立体几何自动化证明系统 VRG。但由于时间的关系,只完成了第一组。第二组我真的累了,暂时不想做了(尽管有更多更激动人心的东西值得介绍)。

《Introduction to XClips》这一组幻灯片,共 94 张。制做这套幻灯的过程是非常令人愉快的,尽管有些辛苦。呵呵。这是我第一次为自己设计和实现的专家系统语言编写幻灯,激动啊~~

如果您在江大校外,可以从这里下载 PPT 格式的幻灯:

http://svn.berlios.de/svnroot/repos/unisimu/Slides/xclips/xclips.ppt

将上面的 .ppt 改为 .pdf 可以取得 PDF 格式的版本。

如果您在江大校内,则可以从江大医学院的服务器上获取:

http://yxy.ujs.edu.cn/images/xclips.ppt

或者

http://yxy.ujs.edu.cn/images/xclips.pdf

经过 10 天的努力,VRG 和 XClips 这两个项目从无到有,从小到大。

高中数学书上几乎所有的立体几何部分的公理、定理现在都能正确地为我的专家系统所证明啦。对应的测试文件如下:

http://svn.berlios.de/svnroot/repos/unisimu/VRG/t/sanity.t

另外,我使用高三时搜集的许多高考复习题轰炸它,也全部为它轻松搞定。对应的测试文件如下:

http://svn.berlios.de/svnroot/repos/unisimu/VRG/t/senior.t

你看到的这两个 .t 文件其实都是 100% 的 perl 脚本文件。由于使用了 Ingy 的 Test::Base 模块, 测试都是自说明的,非常清晰,非常漂亮。呵呵。

通过 VRG 项目我证实了向量化方法和定性推理的确是极为有力的几何证明工具。

该项目的源代码总是可以从下面的位置自由获取:

http://svn.berlios.de/svnroot/repos/unisimu/VRG

与此同时,我还在专家系统的自动化单元测试技术、自动化覆盖测试、DBC (Design by Contract) 风格的自检验、基于模块的规则隔离与事实共享、推理过程的可视化等方面做了不少有趣的工作。我正试图将这些东西以最自然的形式融入到我的幻灯片中。呵呵。

由于使用像 CLIPS 这样的基于正向链 (forward chaining) 的推理引擎,我可以从 Prolog 的无限循环的困挠中解放出来,从而将主要力量放在知识库本身的表达以及推理过程的自动化解释的核心问题上,而不是时时刻刻去关心像消除左递归,避免规则回路这样的枯燥而琐碎的事情。耶~~~

\"\"\"\"
','agentzh','2006-11-17 14:21:00',2),(12,'真相','

我们说的学习,其实并不是学习,只是叫做学习。

我们说的课业负担重,其实并不是课业负担重,只是叫做课业负担重。

我们说的烦恼多,其实并不是烦恼多,只是叫做烦恼多。

我们说的世间罪恶,其实并不是世间罪恶,只是叫做世间罪恶。

我们说的聪明智慧,其实并不是聪明智慧,只是叫做聪明智慧。

我们说的成就高,其实并不是成就高,只是叫做成就高。

我们说的美丽,其实不是美丽,只是叫做美丽。

为什么呢?我们看到的都只是事物的表相而已,不是真相。美好与丑陋,烦恼与自在,幸福与痛苦,都只在我们的一念之间。

是啊,就是一念之间,就是如此容易。

即便我们拥有再多的财富,取得再大的成就,学习再多的知识,也可能不及一个普通的乡村农夫来得快活自在,来得幸福安乐。 因为幸福只是一种感受,只是一种心理体验。掌控了自己意念,其实也就掌控了自己的幸福。什么成就啦,财富啦,地位啦,学问啦,都不过是过眼云烟,换不来真正的快乐。

公平是什么?我们拥有纯洁的心地,清净的生活,善良的灵魂,这便是上天对我们最大的恩赐,对我们来说,也就是最大的公平。

现代人生活得太苦了。虽然,如今的物质文明超越了过去一切世代的总和,但人们其实还不及过去的人们生活得幸福。巨大的精神压力,飞快的生活节奏,膨胀的贪著欲望, 缠缚身心的烦恼……这些都将唾手可得的幸福赶跑了。

身体上的苦真算不上什么,精神上的苦楚,才是最大的悲哀。自然界中的其他物种,其实大部分时间都饱受饥饿之苦,但我们又不得不羡慕它们的快活自在。

宇宙中最捉摸不透的便是我们的心了。它总会生出如此之多的念头,如此之多的妄想,如此之多的烦恼。但是我们却无法得到自己过去的心,自己现在的心,和自己未来的心。

这听起来似乎有些不可思议。但事实上确是极为明显的。当我们觉察到自己心中的一个念头的瞬间,其实这个念头已经在心中灭去了。“贼后兴兵”,了无所得。因此,我们一定要处处留心,时时在意,以避免我们的心随着烦恼而行。

随顺烦恼,便是自寻烦恼。烦恼本来是没有的,烦恼是我们自己的心造出来的。

记得高中的时候,我向一个同学抱怨说,“我怎么会这么痛苦呢?”对方的回答让我惊愕: “其实人大多数的痛苦都是自己造成的。”我如今才明白了她的意思。

仔细地观察,痛苦确确实实都是自己“伪造”出来的。没有人,没有事,能真正让我们痛苦,只有我们自己才会让自己痛苦。因为痛苦本来就是自己的,痛苦本来就是一种内心感受,痛苦本来就是没有的。

而我呢?一直以来,总是在诅咒教材,诅咒学校,诅咒教育制度,诅咒身边的环境,诅咒除了自己以外一切可以诅咒的东西。结果呢?随顺了烦恼,增长了烦恼。于是成了自己和自己过不去,岂不贻笑大方?而所谓的“自己”,其实也是没有的。

\"\"\"\"
','agentzh','2006-12-17 06:23:00',2),(13,'幸福','
近来时常为一种幸福的感觉所包围。这种幸福不同于 hacking 和编程技术上的进步所带来的快乐,亦不同于独自一人浪迹天洼的那种幸福,亦有别于静心冥想时的快乐。这种幸福让我回想起小学时代的一些事情,让我回想起高中时代的一些事情。无论如何,妙不可言。

确实,本来就没有痛苦的,只有幸福~~~我没有必要恐惧,没有必要担心。一切都是命运安排好的。
\"\"\"\"
','agentzh','2006-12-22 12:23:00',0),(14,'Overview - VRG 专家系统概览','

NAME

Overview - VRG 专家系统概览


AUTHOR

章亦春 <agentzh at gmail dot com>

计算机科学与通信工程学院 江苏大学


VERSION

   Maintainer: Agent Zhang <agentzh at gmail dot com>
Date: 24 Dec 2006
Last Modified: 24 Dec 2006
Version: 0.01


VRG 是什么?

VRG 是一个立体几何定性问题证明系统。比如下面这样的问题都可以使用VRG 进行证明:

  1. 若直线 l // 平面 alpha, 则 l 平行于 alpha 内的所有直线吗?

  2. 设 alpha、beta 表示平面,a、b 表示直线,则 a // alpha 的一个充分条件是不是 alpha 垂直于 beta, 且 a 垂直于 beta ?

  3. 判断平行于同一个平面的两个平面是否平行

  4. 一个平面内的两相交直线与另一个平面内的两条相交直线分别平行,则这两个平面平行吗?

  5. 若平面 alpha 垂直于 平面 beta, 直线 n 在 alpha 上,直线 m 在 beta 上,m 垂直于 n, 则同时有 n 垂直于 beta 和 m 垂直于 alpha 成立吗?

  6. PA、PO 分别是平面 alpha 的垂线、斜线,AO 是 PO 在平面 alpha 内的射影,且 a 在 alpha 上,a 垂直于 AO,则 a 垂直于 PQ.

上述问题都引用自 VRG 的自动化测试台的用例。VRG 可以对任一个用户问题作出 2 种基本判断:Yes (即可以证明)和 No(即无法确定),并且给出提示信息和证明过程。


用户如何向 VRG 描述自己的问题?

用户通过一种类似几何语言的“用户语言”向 VRG 描述自己的问题。

例如上面的第 1 题可以用 VRG 用户语言表达如下:

    line l, m;
plane alpha;
l // alpha, m on alpha => l // m;

第 2 题可以表达如下:

    plane alpha, beta;
line a, b;
    alpha T beta, a T beta => a // alpha

第 3 题可以表达如下:

    plane alpha, beta, theta;
alpha // theta, beta // theta => alpha // beta

第 4 题可以表达如下:

    line l1, l2, l3, l4;
plane alpha, beta;
point P, Q;
    l1 on alpha, l2 on alpha, meet(l1, l2, Q),
l3 on beta, l4 on beta, meet(l3, l4, Q),
l1 // l3, l2 // l4 => alpha // beta

第 5 题可以表达如下:

    plane alpha, beta;
line m, n;
    alpha T beta, n on alpha, m on beta, m T n => n T beta, m T alpha;

第 6 题即三垂线定理,其 VRG 描述如下:

    plane alpha;
line a;
line b; -- line PA
line d; -- line AO
line c; -- line PO
b T alpha, project(c, alpha, d), a on alpha, a T d
=>
a T c;


用户该如何运行 VRG 系统?

用户首先使用 VRG 用户语言描述自己的立体几何问题,并将之保存到一个磁盘文件,并使用 .vrg 作为文件扩展名。然后使用下面的命令行进行求解:

    $ perl script/vrg-run.pl foo.vrg

典型地,若将上面的第 1 题用 VRG 语言描述后保存至 problem-1.vrg文件,则运行 vrg-run 程序的情景如下:

    $ perl script/vrg-run.pl problem-1.vrg
Yes.
    generating vectorize.png...
generating vector-eval.png...
generating anti-vectorize.png...
generating problem-1.png...
generating problem-1.vrg1.png...
generating problem-1.vrg2.png...

输出的第一行为``Yes.\'\',表示成功求证。后面的输出表示 vrg-run 程序又生成了许多图片文件。其中最重要的是 problem-1.png,它以有向图的形式绘出了整个程序证明的推理过程,即系统是如何从已知事实出发一步一步推出求证目标的。而 vectorize.png 描绘的是整个证明流程中的第一大步,即“向量化”阶段的推理过程;vector-eval.png 描绘的则是第二阶段,向量空间内的推理过程;anti-vectorize.png描述的则是第三阶段,亦最后一大步,即“逆向量化”部分的推理过程。

最后生成的 2 张图片比较特别。problem-1.vrg1.png 描述的是已知条件所对应的向量关系图(即 Vector Relational Graph),而 problem-1.vrg2.png 描绘的则是推理结束后结论加已知条件所对应的向量关系图。向量关系图本身使用下面的表示约定:所有节点表示向量,黑色实线表示“垂直关系”,黑色虚线表示“既不平行,也不垂直”,红色实线表示“平行关系”,红色虚线表示“不平行关系”,而其他关系会用文字显式标出。通过“向量关系图”,用户可以看到证明过程的数学本质。


VRG 是如何绘制这些 PNG 格式的有向图的?

VRG 在内部使用 AT&T 的自由软件库 Graphviz 来生成所有的有向图。


VRG 在证明结果的描述上还有哪些特别之处?

对于多证明目标的题目,VRG 在判断不成立时,会显式地指出具体是哪些目标是未决的。而对于题目自身的条件是彼此冲突的,比如两个几何元素既平行又垂直了,VRG 也会显式地指出冲突所涉及的细节(比如哪两个元素冲突了,是哪两个关系冲突了)。


VRG 经过了怎么的测试?

我已使用高中数学教材中所有的公理、定义、定理和推论对 VRG 进行了测试(在 VRG的测试集中即对应 sanity.t 文件),此外,我还使用高三时候积累的所有相关的高考复习题对 VRG 进行了测试(在测试集中即对应 senior.t 文件)。


哪些立体几何问题是 VRG 无法求解的?

对于涉及定量关系的几何问题是无法用 VRG 进行求解的,比如角度计算问题、线段长度之类。VRG 是定性求解系统,它只能处理“垂直”、“平行”、“线在面上”这样的定性关系。


VRG 的知识库是使用什么语言描述的?

VRG 的知识库全部是使用我自主设计和实现的通用目的专家系统编程语言 XClips 进行描述的,在 VRG 源代码目录中,对应 knowledge/*.xclp 这些文件。

由于使用了可扩展的 XClips 语言,VRG 的知识库非常简洁,非常清晰。


VRG 在底层采用了什么样的推理引擎?

VRG 在底层使用了美国航空航天局约翰逊太空中心开发的正向链推理机 CLIPS. 事实上,VRG 系统与 CLIPS 的交互全部是通过 XClips 系统来完成的。XClips 正是建筑在CLIPS 之上的。

值得一提的是,CLIPS 是发布在公共域(public domain)中的,因此可以将之用于任何目的。


VRG 可以运行在哪些操作系统上?

VRG 的构件和依赖项都是高度可移植的,包括 CLIPS, perl, Graphviz, 因此可以不加修改地运行在包括 Windows, Linux, FreeBSD, Solaris 在内的多种操作系统上。目前,我只在 Windows XP 和 Windows 2000 上进行过测试。


如何获取 VRG ?

您总是可以从下面的 SVN 仓库获得 VRG 最新版本的源代码:

http://svn.berlios.de/svnroot/repos/unisimu/VRG


如何加入 VRG 的开发工作?

如果您想帮助完善 VRG 系统,请发送电子邮件告知作者。谢谢!


COPYRIGHT

Copyright 2006 by Agent Zhang (章亦春). All rights reserved.


SEE ALSO

the KB manpage

\"\"\"\"
','agentzh','2007-02-06 12:59:00',0),(15,'KB - VRG 知识库简介','

NAME

KB - VRG 知识库简介


AUTHOR

Agent Zhang (章亦春) <agentzh at gmail dot com>


VERSION

   Maintainer: Agent Zhang <agentzh at gmail dot com>
Date: 26 Dec 2006
Last Modified: 26 Dec 2006
Version: 0.01


DESCRIPTION

这篇文档将简要地介绍一下 VRG 立体几何定性证明系统的知识库。如果您对 VRG 项目还不熟悉,请先阅读该项目的 Overview 文档。:)


记法约定

VRG 知识库使用 XClips 语言进行描述。为方便起见,在本文档中的规则和事实示例亦使用 XClips 记法。VRG 定义了如下的特有运算符:

  • 前缀 (prefix) \\ 表示谓词名 line,例如 \\a 等同于 line(a).

  • 前缀 # 表示谓词名 plane,例如 #alpha 等同于 plane(alpha).

  • 中缀 (infix) T 等同于谓词名 orthogonal,表示正交或者垂直关系。

  • 中缀 // 等同于谓词名 parallel,表示平行关系。

  • 中缀 X 等同于谓词名 cross, 表示既不平行也不垂直的关系(在 VRG 内部术语中,称此种关系为 “斜交关系”)。

  • 中前缀 (infix-prefix) ~ 表示谓词名前缀 not_, 例如 a [~//] b 等价于space_not_parallel(a, b).

  • 中包围缀 (infix-circumfix) [ ] 表示立体几何空间中的关系,比如 a [//] b 就等同于谓词space_parallel(a, b),而 a [T] b 就等同于谓词 space_orthogonal(a, b).

  • 中包围缀 < > 表示向量空间中的关系,例如 a <//> b 等价于谓词vector_parallel(a, b), 而 a <~T> b 则等价于谓词 vector_not_orthogonal(a, b).

特别地,以问号 (?) 起始的标识符为 XClips 变量,如 ?alpha, ?m 之类;否则为常量,如betal.

变量一般用于规则,而常量一般出现在事实中。

这些其实都是 XClips 语言的语法。有关 XClips 语言的更多信息,请参见我的``Introduction to XClips\'\'讲座的幻灯片:

http://perlcabal.org/~agentzh/slides/xclips/xclips.pdf


知识库的建模对象

VRG 知识库大体上可以分为三个部分,一是在立体几何空间中的推理,二是向量空间中的推理,三是在这两个空间之间的关系映射。

立体几何空间

在立体几何空间中,基本的研究对象是空间直线和平面这两种立体几何元素以及它们之间的关系。这些关系包括

二元关系

线线关系

对于线线关,VRG 仅处理线线关系中的平行关系,垂直关系,斜交关系,以及它们的衍生关系,例如不平行,不垂直,不斜交等等。

线面关系

VRG 仅处理线面关系中的线面平行,线面垂直,线面斜交,线在面上,以及它们的衍生关系,例如线面不垂直,线不在面上等等。

比如:

    /* line a is parallel to line b */
    \\a, \\b, a [//] b.
    /* line c is perpendicular to line d */
    \\c, \\d, a [T] b.
    /* line e is not parallel to line f */
    \\e, \\f, e [~//] f.
面面关系

VRG 仅处理面面关系中的面面平行,面面垂直,面面斜交,以及它们的衍生关系,例如面面不平行等等。

比如:

    /* line l is parallel to plane alpha */
    \\l, #alpha, l [//] alpha.
    /* line a is perpendicular to plane beta */
    \\a, #beta, a [T] beta.

三元关系

线线相交于一点

比如下面这条事实

    \\a, \\b, meet(a, b, A).

便指示了直线 a 和直线 b 相交于点 A.

线在面上的投影

该关系是指,一条直线在一个平面上的投影是另一条直线(或点)

下面这条 XClips 事实

    \\a, #A, \\b, project(a, A, b).

就指明了直线 a 在平面 A 上的投影是 b.

线面相交于一点

比如下面这条事实

    \\a, #alpha, meet(a, alpha, P).

指示直线 a 与平面 alpha 相交点 P.

VRG 在立几空间中的推理任务主要是将复杂的关系分解为基本关系,或者将基本关系合成为复杂关系。

向量空间

向量是立体几何元素的抽象表示。从数学语义上讲,立几空间中的平面在向量空间中对应其“法向量”,而立几空间中的直线在向量空间中对应其“方向向量”。

向量空间中的关系演绎是整个证明系统的核心。VRG 正是通过从已有的向量关系推出新的向量关系,来间接地从已有的几何关系推出新的几何关系的。

在向量空间中仅讨论下列关系:

平行关系

例如

    a <//> b

表示向量 a 与向量 b 平行。

垂直关系

例如

    a <T> b

表示向量 a 与向量 b 垂直。

斜交关系

例如

    a <X> b

表示向量 a 与向量 b 斜交。


基本假设条件

目前,知识库使用了下列假设条件:

  • 若一平面与另一平面的名称不同,则认为两平面不重合。(知识库自身创建的“辅助平面”除外。)

  • 若一直线与另一直线的名称不同,则认为两直线不重合。(知识库自身创建的“辅助直线”除外。)

取消这两条基本假设虽然从逻辑上更加完整,但从实用性的角度上讲,将不可避免地使知识库中到处充斥着“a 与 b 不重合”这样的断言,同时也会增加了用户输入已知条件的负担,增加了因人为的已知条件不充足而无法求证的可能性。


知识库的推理流程

知识库从物理上分为 4 个 CLIPS 模块(module),亦对应推理流程的 4 大阶段:

Vectorize 模块

Vectorize 模块是由 preprocess.xclpvectorize.xclp 这两个文件实现的。该模块负责完成从几何空间内的线线关系、线面关系、面面关系及其他复杂关系到向量空间内的向量关系的转换。

Eval 模块

Eval 模块是由 vector-eval.xclp 文件实现。该模块负责在向量空间内执行推理,从已知的向量关系不断推出新的向量关系。

AntiVectorize 模块

此模块由 anti-vectorize.xclp 文件实现。它负责执行 Vectorize 模块的“逆操作”,即将新的向量关系还原为几何空间中的线线关系、线面关系和面面关系。

GoalMatch 模块

GoalMatch 模块完成用户给定的证明目标在所有已知事实中的匹配及相关的解释工作。

当推理机的焦点处于某个模块时,只有属于该模块的规则和事实才能被参与推理。

有关立几空间的事实由 Vectorize 模块,AntiVectorize,和 GoalMatch 模块共享;有关向量空间的事实由 Vectorize 模块,Eval 模块,和 AntiVectorize 模块共享。

推理机运行的具体流程如下

  • 用户输入的已知条件所对应的“初始事实”被导入到 Vectorize 模块。

  • 推理机焦点 (focus) 从默认模块 MAIN 切换至 Vectorize 模块,执行立几空间内的关系演算和“向量化”操作。

  • 上一步运行完毕后,再将焦点移至 Eval 模块,执行向量空间内的关系演算,推出更多的向量关系。

  • 将焦点移至 AntiVectorize 模块,对所有新的向量关系执行反向量化,还原出立几空间中的语义。

  • 焦点被切换至 GoalMatch 模块,使用用户给定的证明目标对所有已知事实进行匹配,并生成解释和评价。


知识库的内部结构

知识库由下列 XClips 源文件构成:

vrg-sugar.xclp

该文件定义了知识库中所使用的特殊的运算符,例如前缀 \\ 和中缀 //.该文件为知识库中所有其他 .xclp 文件所包含。详情请参与 记法约定.

例如前缀 \\ 的定义如下:

    prefix:<\\>   line

而中缀 // 的定义如下:

    infix:<//>   parallel

preprocess.xclp

该文件定义了 VRG 的“预处理规则”。这些规则的主要工作是在立几空间内部进行关系演算,其目的在于将 project(投影)和 meet(相交)这样的复杂关系转换为平行、垂直之类的简单关系,同时为某些基本关系生成“同构异形体”,以简化后续的匹配工作。

具体说来,此文件包含下列几条规则:

  • 当两个平面 alphabeta 相交于直线 l 时,则 alphabeta不平行,并且 l 同时在 alphabeta 上.

        #?alpha, #?beta, meet(?alpha, ?beta, ?l)
    => ?alpha [~//] ?beta, ?l [on] ?alpha, ?l [on] ?beta.

    这儿的前缀问号(?)表示为变量,而非常量。

  • 当两条直线 lm 相交于一点时,则存在一个平面 alpha 使得 lm都在 alpha 上,且 l 不平行于 m.

        \\?l, \\?m, meet(?l, ?m, ?)
    =>
    ?alpha := gensym(), #?alpha, temp(?alpha),
    ?l [on] ?alpha, ?m [on] ?alpha,
    ?l [~//] ?m.

    这里的单个问号变量 (?) 表示“通配符”(wildcard).

  • 若直线 l 和平面 alpha 相交于一点,则 l 既不平行于 alpha,也不在 alpha之上:

        \\?l, #?alpha, meet(?l, ?alpha, ?) => ?l [~//] ?alpha, ?l [~on] ?alpha.
  • 若直线 l 在平面 alpha 上的投影为直线 m,则存在一个平面 theta 使得 (1) lalpha 斜交,(2) ltheta 上, (3) thetaalpha 相交于 m, 并且(4) thetaalpha 垂直:

        \\?l, #?alpha, \\?m, project(?l, ?alpha, ?m)
    =>
    ?theta := gensym(), #?theta, temp(?theta),
    ?l [X] ?alpha, ?l [on] ?theta,
    meet(?theta, ?alpha, ?m),
    ?theta [T] ?alpha.
  • 若平面 alpha 与直线 l 之间存在某个特定的关系 R, 则 lalpha 亦满足(交换律):

        #?alpha, \\?l, ?alpha [?R] ?l => ?l [?R] ?alpha.

vectorize.xclp

本文件包含了执行“向量化”步骤的所有规则。

线线关系的向量化

若直线 l 与直线 m 之间存在关系 R, 则向量 l 与向量 m 之间亦存在关系 R.

    \\?l, \\?m, ?l [?R] ?m => ?l <?R> ?m.

线面关系的向量化

  • 若直线 l 与平面 alpha 垂直,则向量 l 与向量 alpha 平行:

        \\?l, #?alpha, ?l [T] ?alpha  => ?l <//> ?alpha.
  • 若直线 l 与平面 alpha 平行,则向量 l 与向量 alpha 垂直:

        \\?l, #?alpha, ?l [//] ?alpha => ?l <T> ?alpha.
  • 若直线 l 与平面 alpha 斜交,则向量 l 与向量 alpha 亦斜交:

        \\?l, #?alpha, ?l [X] ?alpha  => ?l <X> ?alpha.
  • 若直线 l 在平面 alpha 上,则向量 l 与向量 alpha 垂直:

        \\?l, #?alpha, ?l [on] ?alpha => ?l <T> ?alpha.
  • 上述关系的否定亦然:

        \\?l, #?alpha, ?l [~T] ?alpha  => ?l <~//> ?alpha.
    \\?l, #?alpha, ?l [~//] ?alpha => ?l <~T> ?alpha.
    \\?l, #?alpha, ?l [~X] ?alpha => ?l <~X> ?alpha.

面面关系的向量化

若平面 alpha 与平面 beta 满足关系 R, 则在向量空间中,alphabeta 亦满足关系 R.

    #?alpha, #?beta, ?alpha [?R] ?beta => ?alpha <?R> ?beta.

vector-eval.xclp

此文件中的规则都是向量空间内的“求解规则”,用于从已知的向量关系推出全新的向量关系。这些规则是整个 VRG 系统知识的核心

  • 已知 a, b, c 都是向量,若 a // b, bc 满足关系 R,且 c 不同于 a,则 ac 亦满足关系 R.

        ?a <//> ?b, ?b <?R> ?c, ?a \\= ?c
    => ?a <?R> ?c.

    这一条规则的意义是,向量间的关系可以通过“平行”关系进行传递。在立体几何空间中,许多定理、定义和推论都对应于这一条规则。

    比如高中数学课本``立体几何\'\'一章有下列公理和定理是本条向量规则在立几语义中特殊的表现形式:

    我们看到,一条向量化规则对应到如此之多的立几定理和公理。从这个意义上讲,向量化方法有效地揭示出立体关系的本质。

  • 已知 ab 都是向量,若 a 垂直于向量 b, 或者 ab 斜交,则 a 不平行于 b.

        ?a <T> ?b; ?a <X> ?b => ?a <~//> ?b.

    本规则其实揭示的其实就是“不平行”的定义。之所以专门编写一条规则来产生“不平行”关系,是因为“不平行”在下面这条规则中扮演着关键性的角色。

  • 已知 a, b, c, d 四个向量满足下列关系:a 垂直于 b, b 垂直于 c,c 垂直于 d, d 垂直于 a, a 不平行于 c, 且 b 不同于 d,则有 b // d.

        ?a <T> ?b, ?b <T> ?c, ?c <T> ?d, ?d <T> ?a, ?a <~//> ?c, ?b \\= ?d
    => ?b <//> ?d.

    在高中数学课本中有如下定理是该向量规则的“特殊表现形式”:

  • 若向量 a 与向量 b 满足关系 R,则 ba 亦满足关系 R.

        ?a <?R> ?b => ?b <?R> ?a.

    这条规则揭示的是向量关系满足交换律。

anti-vectorize.xclp

本文件中的几条规则执行“逆向量化”操作,正好是 vectorize.xclp 中规则的“反函数”,比如逆向量化规则

    \\?l, #?alpha, ?l <T> ?alpha => ?l [~T] ?alpha, ?l [~X] ?alpha.

的含义是:如果在向量空间中,向量 l 垂直于向量 alpha,且在立体几何空间中,l是直线,alpha 是平面,则有在立几空间中,直线 l 不垂直于平面 alpha,且直线 l 不斜交于平面 alpha.

goal-match.xclp

本文件中的规则使用用户给定的证明目标对已得到的事实进行匹配。

  • 若用户求证 ab 在立几空间存在关系 R, 且事实库中确实存在该事实,则生成 solved 事实指示目标已解决。

        ?a *[?R] ?b, ?a [?R] ?b
    => solved(space-relation, ?R, ?a, ?b).
  • 若用户求证 ab 在立几空间存在关系 R,且事实库中不存在该事实,则生成 pending 事实以指示该目标“未决”。

        ?a *[?R] ?b, ~exists(?a [?R] ?b)
    => pending(space-relation, ?R, ?a, ?b).
  • 若用户给定的有关 ab 的一求证目标未决,且事实库中存在 ab之间确定的某种关系,则生成 hint 事实,以提示用户。

        pending(space-relation, ?, ?a, ?b), ?a [?R] ?b
    => hint(space-relation, ?R, ?a, ?b).


知识库的完整性自检与 DBC

除了上述规则之外,知识库中还收录了许多自检测规则,用于检测事实库内部的完整性。这些设施可以有效地检测出用户给定事实之间的冲突、知识库规则之间的冲突,以及其他形式的 VRG bug.

事实上,在 VRG 的早期,这些自检测规则确实捕捉到不少连题库测试台都未捕捉到的 bugs。

一条典型的自检规则如下:

    \\?l, #?alpha, ?l [on] ?alpha, ?l [~on] ?alpha
=> contradiction(\"[on]\", \"[~on]\", ?l, ?alpha).

其含义是:一条直线要么在一个平面上,要不不在那个平面上。如果同时存在这两个事实,则生成 contradction 事实指示矛盾冲突的存在。

将完整性测试逻辑与系统自身的实现放在一起,在软件工程中称为 Design by contract (DBC).VRG 的实践表明,在基于规则的系统中实现 DBC 要比传统的命令式语言要方便和自然得多。


知识库的 Subversion 仓库

您总是可以从下面的 Subversion (SVN) 仓库取得最新版本的 VRG 知识库:

https://svn.berlios.de/svnroot/repos/unisimu/VRG/knowledge


TODO

  • lineplane 谓词的基础上引入 point 谓词用于显式地声明几何点。

    虽然当前知识库已通过使用隐式的点对象来处理类似“两线交于一点”的条件,但显式的点对象无疑会提高规则的可读性和知识库的可扩展性。


COPYRIGHT

Copyright 2006 by Agent Zhang (章亦春). All rights reserved.


SEE ALSO

the Overview manpage

\"\"\"\"
','agentzh','2007-02-06 12:59:00',0),(16,'Makefile 项目的历史与背景','

在大三上学期的时候,即 2005 年国庆前后,我正在为我的计算机组成的课程设计项目 Salent 准备 报告 用的素材。那时我就想到从 Salent 项目自身的 Makefile 自动生成项目的 构造流程图 。毕竟 Makefile 文件中已经包含了项目文件间的依赖关系,以及从各组依赖项生成对应目标的 Shell 命令。

在这个应用中,我需要一个 Makefile 解析器以及一个有向图的示意图生成器。至于后者,AT&T 免费的 GraphViz 库可以很好地胜任。至于前者,我进行了大量的网络搜索。我试用了 CPAN 上的 Make 模块,但它不能很好地支持 NMAKE 语法的 Makefile,于是我就针对 Salent 项目的 Makefile 所使用的特性,同时综合了 GNU make 的一些常用特性,自主开发了 Makefile::Parser 模块,并发布到 CPAN。

很快地,以 Makefile::Parser 为基础,我推出了从 Makefile 自动生成构造流程图的 Makefile::GraphViz 模块。

有趣的是,CPAN 上也有一个所谓的 GraphViz::Makefile 模块。和我的不同的是,该模块是基于前面提到的 Make 模块的。因此与我的库实际上构成了``竞争\'\'关系。

在随后的几周内,我开始根据 GNU make 手册 ,向我的 Makefile::Parser 不断地添加新特性。但我很快发现,已有的框架变得越来越难于扩展,根本无法胜任 gmake 庞大的特性集。因此当 Makefile::Parser 0.11 发布之后,我就放弃了旧的代码基础,开始另起炉灶了。

2006 年的冬天,我开始仔细阅读 GNU make 手册 ,并着手将 gmake 自身的测试集 移植到我自己的 Makefile::Parser 项目中来,以便采用测试驱动的方法来创建全新的 Makefile::Parser 实现。

虽然 gmake 官方的测试台亦是用 Perl 开发的,且亦可作用于任意的 make 可执行文件,但是它却使用的是过时的 Perl 4 语言,并大量调用了 sh, diff 等特定于 *NIX 的工具,从而变得高度不可移植。所以我才下决心使用现代的 Perl 5 自动化测试框架 Test::Base 对 gmake 已有的测试集进行改写,以期达到下列目标:

  • 可以不加修改地运行在 Win32, Cygwin, FreeBSD, NetBSD, OpenBSD, Linux, Solaris, Mac OS X 等多种类型操作系统上。

  • 测试用例采用声明性的记法,保证可读性、清晰性和简洁性。

  • 易于扩展,并可用于编写针对其他 make 工具(如 nmake, dmake, bsdmake)的测试集

  • 易于配置,可以指定任意的 shell 命令行作为 make 测试对象

为了确保新的 gmake 测试集的可移植性,我自己用纯 Perl 开发了一个 Bourne Shell 虚拟机 。毕竟,Windows 的 Shell 语法和行为与 Bourne Shell 是如此地不同。另外,其他系统中默认的 shell 也有可能是像 csh 这样的东西。由于该 sh 虚拟器是为 Makefile::Parser 的测试集服务的,因此只需要实现 Bourne Shell 特性的一个很小的子集,即 gmake 测试用例中实际使用到的特性集。

目前,gmake 测试集的转换工作正在进行中,您可以从下面的位置看到已完成转换的 gmake 测试脚本:

http://svn.berlios.de/svnroot/repos/makefileps/t/gnu/

从那以后,迫于江大日益繁重的课业负担,Makefile::Parser 一直进展缓慢。在过去的一年中,有许多人向我表达了各种各样有趣的需求,这驱使我不断地调整项目的设计与目标。

  • AT&T 用户 Billy Patton 向我表达了他的一个有趣的需求:他希望能通过编程方式,读取一个 Makefile 文件,然后进行一些修改,再写回磁盘。他说,他希望通过 GUI 菜单来帮助没有 Makefile 使用经验的用户来操纵 Makefile。这个需求意味着,读取 Makefile 的过程必须是``无损\'\'的,即我的库不可以扔掉包括注释、空行在内的任何东西,同时我还必须提供相应的接口将修改过的 Makefile AST 写回磁盘,即提供一种 Makefile Writer。

  • Gurets Maxim 通过 CPAN RT 向我 传达了 这样一个需求:他希望看到 Makefile::Parser 拥有 GNUMake, NMake, BSDMake 等多个子类,从而能解析各种已知格式的 Makefile. 他认为现有的 Makefile::Parser 实现将 NMAKE 和 GNU make 的特性杂糅在一起的做法并不可取。我表示赞同,因为 NMAKE 和 gmake 在行为上有许多矛盾之处。

  • 微软公司 Unix 互操作团队的 Madhuri Mandava 和 Pugs 团队的 Christopher Malon 更乐衷于看到将 NMAKE 的 Makefile 转换为 gmake 格式的 Makefile,或者相反。这种需求要普遍得多,毕竟有太多太多基于 Linux 的开源项目需要移植到 Win32,而 Makefile 的翻译往往是很重要的组成部分。比如我自己就曾经吃力地将 Judy 库 的 Makefile 翻译为 NMAKE 接受的版本--唔,那可真是枯燥之极。

  • 这个世界上除了 make 还有许多其他的项目构造和管理工具,比如 Ruby 世界里的 Rake , Java 里的 Ant,以及 CPAN 上的 PerlBuildSystem (PBS) 。PBS 的作者之一,瑞典的 Nadim Khemir 和我一直保待着通信联系。他非常希望看到,gmake 等其他 make 工具的 Makefile 文件能通过我的 Makefile::Parser 或者类似的东西,自动地转换为 PBS 自己的配置文件 (pbsfile)。

  • Adam Beauchamp 用标准的状态机设计模式对我的 Makefile::Parser 0.11 进行了改写,并通过了我所有的回归测试。可惜的是,他工作在了一个早已废弃了的实现上,但是他的想法真的很有趣。经过他改写的版本看上去更加“面向对象”了,而且原先极为臃肿的 parse 方法也变得简洁了许多。我对他的方式的唯一顾虑就是执行效率。

在 Nadim Khemir 的大力推动下,我于大四上学期的前一两个月,启动了 Makefile::DOM 项目。该项目受 Adam Kennedy (Alias) 的 PPI 模块的启发,将 Makefile 视为“文档”而非程序进行解析,解析的结果是一棵类似 DOM 的树型数据结构。该项目由于能无损地对 Makefile 进行解析,故可以很好地满足前面 Billy Patton 等人的需求。从 DOM 树写回 Makefile 也是极容易的。同时 Makefile::DOM 亦可作为其他所有需求及应用的基础,因为它实际上完成的是 Makefile 的词法分析以及一部分简单的语法分析任务。

Makefile::DOM 的进展非常迅速,目前已经支持了 Gnu Makefile 的大部分语言结构。我以为至少 0.0.1 版已经可以在近期发布到 CPAN 了。

\"\"\"\"
','agentzh','2007-02-07 08:00:00',0),(17,'Makefile 项目的组成','

该项目将由下列三部分组成:

Makefile::DOM

该模块将 Makefile 视为“文档”进行“无损”的解析,生成类似 DOM 的树形结构。DOM 树中将保留原输入文件中的所有信息,包括空格、空行、注释等。这意味着,从 DOM 树可以还原出原始的 Makefile 文件。另外 DOM 树自身的每个节点甚至整体都是可修改的,就像  PPI  和 HTML::TreeBuilder 那样。

Makefile::DOM 的接口完全模仿了  PPI  的 API 设计。事实上,我直接照搬了 PPI::Node, PPI::Element, PPI::Dumper 的源代码和 POD 文档(此举已得到  PPI  的作者 Adam Kennedy 的完全许可)。

Makefile::DOM 被设计成与具体的 Makefile 语法无关。同一套 DOM 节点类型将在不同格式的 Makefile DOM 生成器之间共享,比如, MDOM::Document::Gmake  负责对 GNU Makefile 进行解析,返回 MDOM::Document 类的实例(即 DOM 树的根);而 NMAKE Makefile 的解析器 MDOM::Document::Nmake 亦返回 MDOM::Document 类的实例。日后,还将考虑添加对 dmake 和 bsdmake 的支持。

目前 MDOM::Document::Gmake 已初具雏形,下面要做的就是添加遗漏的节点类型和进行综合测试。

测试 Makefile::DOM 最好的方法就是在其基础之上,开发出完整的 make 工具,然后通过对应 make 工具的测试集。比如,测试 MDOM::Document::Gmake 最好的方法就是利用它实现一个 pgmake 脚本,然后去跑 GNU make 官方测试集。类似地,我也需要开发出 pnmake 脚本。

Makefile::Parser

全新的 Makefile::Parser 实现不会在 API 上进行太大的改动。换言之,新版本的接口仍将基本按照  0.11版  也即  Make  模块的接口来设计。尽管如此,我仍会根据需要,对 API 进行扩展和补充。

Makefile::Parser 的任务在于,从 make 工具的视角,对 Makefile DOM 树进行深层的语法分析和语义脱糖。这意味着,得到的 AST 必然是“有损”的,而且必然包含了当前环境中的信息。这些环境信息包括系统中的环境变量设置、命令行选项、命令行传递的 Makefile 变量值、甚至磁盘文件的当前状态等。这种环境信息的依赖意味着 Makefile::Parser 并不适合进行严格意义上的 Makefile 翻译与转换工作。真正的翻译与转换要求 AST 是与上下文无关的,因此必须从 Makefile::DOM 出发重新开始。

Makefile::Parser 的用途很多,比如对 Makefile 中的依赖关系进行可视化(典型的应用就是 Makefile::GraphViz 这样的模块)。另外就是进行一些实用主义的翻译。当需要转换的 Makefile 并未使用强烈依赖于上下文的高级特性的时候,从 Makefile::Parser 产生的 AST 出发已经可以得到相当令人满意的翻译了。

Makefile::GraphViz

下一代的 Makefile::GraphViz 将基于 Makefile::DOM 和全新的 Makefile::Parser,同时保持向后兼容。

Makefile::Compiler

该模块就是进行不同格式 Makefile 之间的转换,以及将某一种格式的 Makefile 转换成其他非 make 项目管理工具的配置文件,比如 PerlBuildSystem, Rake, 和 Ant.

正如前面提到的,这里最简单的做法就是从 Makefile::Parser 生成的“有损” AST 出发,进行代码生成。但是通过这种方式得到的目标代码强烈地依赖于进行翻译时刻的系统上下文,影响目标代码的通用性和可移植性。尽管如此,对于许多足够简单的 Makefile 而言,种用这种方法生成的目标代码已经足够好了。幸运的是,现实世界中的大部分 Makefile 都是足够简单的。

更完美的翻译方式当然是从最底层的 DOM 树出发,按照类似“程序形式化证明”的方法进行复杂的 AST 变换。利用此种手段可以得到相当“地道“的目标代码,其质量接近人类手写的代码,但是 AST 变换算法可能会极端复杂。届时可以考虑使用像属性文法这样的工具(Language::AttributeGrammar)。

在实际翻译中,有一个很重要的问题就是如何处理 Makefile 中内联的 shell 命令。毕竟任何一个 Makefile 文件中都包含至少两种“语言”:Makefile 本身的记法,以及命令中的 Shell 记法。比如 GNU makefile 中的 cp, mv 在 NMAKE makefile 中就不应当出现。这意味着,Makefile::Compiler 可能还得实现一个 shell 转换器以完成不同 shell 之间的编译工作……

\"\"\"\"','agentzh','2007-02-07 11:14:00',0),(18,'Makefile 项目的开发计划','

 

Makefile::DOM

第一阶段的工作将集中在 Makefile::DOM 的开发上。

该模块以及其他模块都将遵循“早发布,常发布”的原则,并使用先进的基于  Subversion  的  SVK 版本控制系统 进行源代码的管理。

Makefile::DOM 在  CPAN  发布的版本号,采用三段数的格式,比如 0.2.12。以此版本号为基础,可将该模块的开发工作分为下列里程碑:

  • 0.0.x

    从 0.0.1 开始,实现  MDOM::Document::Gmake  模块。它将逐步地支持 GNU make 几乎全部的词法和语法结构,完成相应的 POD 格式的英文文档,以及比较全面的基于 Test::Base 模块的  单元测试台

  • 0.1.x

    从 0.1.0 开始,逐步地在 MDOM (即 Makefile::DOM) 的基础上开发出 GNU make 的纯 Perl 实现(名叫 pgmake),从而得以运行  GNU make 官方的测试集 ,同时完善  MDOM::Document::Gmake ,进而确保并验证 MDOM 自身的完整性。

    考虑到 GNU make 官方测试集并不是很完整,因此还须根据  GNU make Manual  文档对该测试集进行扩充,以便尽可能多地覆盖 gmake 实际支持的特性集。

  • 0.2.x

    从 0.2.0 开始,逐步实现 MDOM::Document::Nmake 模块,使得它能支持微软 32 位 NMAKE 几乎全部的词法和语法结构,完成相应的 POD 格式的英文文档,以及比较全面的基于 Test::Base 模块的单元测试台。

  • 0.3.x

    从 0.3.0 开始,在 MDOM 基础上开发出 NMAKE 的纯 Perl 实现(名叫 pnmake),从而得以运行 NMAKE 测试集,同时完成 MDOM::Document::Nmake,进而确保并验证 MDOM 自身的完整性。

    由于微软的 NMAKE 不像 GNU make 那样是开源项目,我无法取得 NMAKE 官方的测试集,故必须按照 MSDN 网站上的  NMAKE Reference  文档自主设计测试用例。

  • 0.4.x

    将 GNU make 和 MS NMAKE 对应的基于 IPC::Run3 的测试集转换为针对 MDOM 的高度可移植的轻量级测试集。

  • 0.5.x 及其以后版本

    不断完善文档,不断修复自己发现的和其他用户报告的 bug,不断根据用户需求完善接口和实现。

Makefile::DOM 的 SVN 仓库位于下面的位置:

http://svn.openfoundry.org/mdom/

其结构分为 trunk (主干)和若干个 branches (分支)。主干是主流的版本;CPAN 发布总是从主干产生。而各个分支主要用于试验和演化新特性,待成熟后才``融合\'\'回主干中去。融合工作可以由 SVK 自动完成(利用 SVK 的 smerge 命令)。反过来,主干中的更新,借助于 SVK,也可以轻易地融合到各个分支中去。

本模块计划拥有以下分支:

  • /branches/gmake

    用于开发 Perl 版本的 GNU make 实现,pgmake,并将包含基于 IPC::Run3Test::Base 的 GNU make 测试集。

    pgmake 和使用了 IPC::Run3 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Gmake 部分的原型(prototype)。

    该分支从 Makefile::DOM 0.1.x 起启用。

  • /branches/nmake

    用于开发 Perl 版本的 NMAKE 实现,pnmake,并将包含基于 IPC::Run3Test::Base 的 NMAKE 测试集。测试台框架将复用 /branches/gmake 中的 GNU make 测试台脚手架。

    类似地,pnmake 和基于 IPC 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Nmake 部分的原型。

    该分支从 Makefile::DOM 0.3.x 起启用。

Makefile::Parser

历史遗留的旧实现

Makefile::Parser 一年多以前发布在 CPAN 上的 0.11 版的旧实现仍将继续演化。其中的改进内容,主要包括:

  • 整合 Adam Beauchamp 提供的基于状态机设计模式的补丁。

  • 修复一个用户在 RT 中  报告的bug ,提供对 GNU make 函数引用的支持。

  • 简单介绍新一代 Makefile::Parser 的开发现状和蓝图。

这些将以 0.xx 的版本号发布到 CPAN。

全新版本的实现

全新的实现将基于 Makefile::DOM,并保持接口的向下兼容。由于旧实现同时支持 GNU make 和 NMAKE 的常用语法,故要实现向后兼容,必须实现 Makefile 格式的自动识别。最简单的做法也许是先尝试用 Makefile::Parser::Gmake 进行处理,如果出现错误,就改用 Makefile::Parser::Nmake. 至于该做法的实际效果如何,只有留待实践的检验了。

基于 CPAN 发布的版本号的里程碑列表如下:

  • 1.0.x_01

    它们将整合 Makefile::DOM 的 /branches/gmake 分支的实现。版本号中的 _01 后缀将之标识为``Developer Release\'\';一般的 CPAN 升级工具将会忽略这样的发布,从而不致于突然破坏向下兼容。

  • 1.1.x_01

    它们将整合 Makefile::DOM 的 /branches/nmake 分支的实现代码。

  • 1.2.x

    它们将首次实现向下兼容,从而是 1.0.0_01 以来第一批 CPAN 正式发布版。

  • 1.3.x

    该系列将致力于把基于 IPC 的测试集转换为非 IPC 的版本,从而提高效率,增加可移植性。关于测试集可移植性的一个关键子项目是 Bourne Shell 的仿真。毕竟像 Win32 这样的平台,/bin/sh 一般是没有的。

Makefile::Parser 的 SVN 仓库位于:

http://svn.openfoundry.org/makefileparser/

未来该仓库将像 Makefile::DOM 那样分为 trunk 和若干个 branches.

Makefile::GraphViz

Makefile::Parser 类似,CPAN 上已有的 Makefile::GraphViz 实现将以 0.xx 的形式继续演化一段时间。这些发布将着力解决 Ken Williams 于几周前报告的那个有关 plot_all 方法的 bug:

http://rt.cpan.org/Ticket/Display.html

1.00 开始,它将使用 Makefile::Parser 1.2.x 及其以上版本。

Makefile::Compiler

该模块将支持 GNU make 和 MS NMAKE 两种格式的 Makefile 作为输入;输出将支持  Java 的 ANT,CPAN 上的 PBS,以及 GNU make 和 NMAKE 自身。该模块在早期将从 Makefile::Parser 产生的 AST 发射目标代码。该做法实现起来非常简单,虽然无法得到很``地道\'\'的翻译,但却是``足够好的\'\'。

有关该模块的计划目前无法确定下来,因为它强烈地依赖前几个模块的成果和经验。

\"\"\"\"
','agentzh','2007-02-28 12:26:00',0),(19,'毕业设计开发周记(第 1 周)','

从现在起,每周三我都将为毕业设计拟定下一周的工作计划,同时对前一周的相关工作进行总结。

过去一周已完成的工作

  • 先后发布了 Makefile::GraphViz 0.11, 0.12 和 0.13 版,主要是旧内核的例行维护,包括 为 gvmake 脚本添加了有用的 -a 选项(从而能绘制 Makefile 中所有的根目标),以及修复了 RT bug #24828#15070

  • 开发了针对 Module::Install 的脚本 releng , 用于自动化 CPAN 模块发布前繁杂的准备工作。

    我的 Makefile 项目涉及多个 CPAN 模块,每个模块需要发布的版本又是不计其数,因此 releng 脚本无疑会为我节省大量的时间。

  • 基于 Linux::Smaps 开发了一个在 Linux 上统计任意 shell 命令所占用的最大内存量的脚本,名为 smem . 测试显示,Ubuntu 的 System Monitor 使用的也是来自 smaps 的内存占用信息。我在该脚本中首次实用了 Perl 的 fork 函数(一直想用都没用上,因为前面一直用的都是 Windows)。

    鄙视 Linux 内核,因为至今它都没有完整地实现 getrusage 函数 , 从而使得 GNU time 在 Linux 上只能用来计时。同样的原因,CPAN 上的 BSD::Resource 在 Linux 上也没有太大的用处。

    我的 smem 脚本可用于统计 Makefile 项目中各模块的内存占用情况。

下一周的工作计划

  • 修改和应用 Adam Beauchamp 今年 1 月 13 日提供的针对 Makefile::Parser 的补丁到 SVN 仓库branches/states/ 分支 。 该补丁将使得 Makefile::Parser 内核基于标准的状态机模式。

  • branches/states 分支 成熟以后,将之融合到主流的 trunk/, 然后在不影响 Makefile::GraphViz 测试集的前提下,发布为 Makefile::Parser 0.12 版。随后取消 states/ 分支。

  • 开辟 /branches/refs 分支,以比较完整地实现 GNU make 的函数引用(function reference)和变量引用(variable reference),主要面向 RT bug #18229

  • 在 /branches/refs/ 分支成熟后,融合进主流的 trunk/,并发布新的 Makefile::Parser 至 CPAN.

  • 在最近的 Makefile::Parser 模块的 POD 文档中交代全新实现的基本计划。

  • 将已有的基于 Test::Base 的 GNU make 测试集加入到 Makefile::DOM 模块的 SVN 仓库gmake 分支 ,并进行简单的重构:

      t/Shell.pm
    t/Gmake.pm
    t/lib/Test/Make/Gmake.pm
    t/lib/Test/Make/Base.pm
    t/lib/Test/Make/Util.pm
    t/lib/Test/Util.pm
    t/gmake/syntax/
    t/gmake/features/
    t/gmake/...
  • 将新补充的测试用例添加进 Makefile::DOM 的单元测试集,将失败的测试标成``SKIP\'\',并为各个主要 .pm 文件添加 POD 文档,直至发布该模块的第 一个 CPAN 版本 0.0.1

  • 编写 newpm 脚本以自动为我创建 .pm 文件的代码和 POD 文档的骨架。

\"\"\"\"
','agentzh','2007-03-07 17:06:00',1),(20,'毕业设计开发周记(第 2 周)','

过去一周计划的完成情况

  • 将已有的基于 Test::Base 的 GNU make 测试集加入到了 Makefile::DOM 模块的  SVN 仓库 的 gmake 分支 ,并进行简单的重构:

    http://svn.openfoundry.org/mdom/branches/gmake/t/

  • 放弃了整合 Adam Beauchamp 的状态机模式补丁的计划,因为我还是比较喜欢目前的解析策略。

  • 暂时取消了发布 Makefile::DOM 0.01 的计划。因为 Makefile::DOM 的设计还有许多问题,它的设计与实现均需要 未来用 Makefile::Parser 和 GNU make 测试集来进行指引和验证。

  • Makefile::Parser 0.11 的基础上比较完整地实现了下列 GNU make makefile 内建函数:

    subst, patsubst, strip, findstring, filter, filter-out, sort, word, words, wordlist, firstword, lastword, dir, notdir, suffix, basename, addsuffix, addprefix, join, wildcard, realpath, abspath, shell, if, and, or, error, warning, info, foreach

    另外还实现了所谓的“替换引用”(Substitution References),比如:

        $(c_files:.c=.o)

    它们的实现代码直接添加进了 Makefile::Parser 的 SVN 仓库的 trunk/ .

    限于 Makefile::Parser 旧引擎不支持“递归展开变量”,下列 GNU make 内建函数暂时无法恰当地实现:

    origin, value, call, flavor, and eval

    已支持函数的测试目前放置在 Makefile::DOM 的 gmake 分支中:

    http://svn.openfoundry.org/mdom/branches/gmake/t/gmake/sanity/func-refs.t

  • Makefile::Parser 模块实现了  plmake  脚本。 它是基于该模块的 make 命令行工具。该工具使得我可以在实现 GNU make 内建函数的时候运行基于  t::Gmake 的测试台。TDD 万岁!

  • Makefile::Parser 模块的 POD 文档中简单地提及了全新实现的基本计划,并对其中过时的和不准确的地方进行了更新。

  • 上述对 Makefile::Parser trunk 的扩展与改进先后以 0.12, 0.13, 0.14, 0.15, 0.16, 和 0.17 版的形式发布到了 CPAN.

  • 发布了 Makefile::GraphViz 的一些更新版本(当前 CPAN 上版本号为 0.16), 稍稍改进了一下 POD 文档,同时提升了所需的 Makefile::Parser 的最低版本号。

下一周及以后的工作计划

  • 继续发挥 Makefile::Parser 0.xx 旧引擎的余热, 借助于  plmake 实现基本的基于拓仆图的目标更新算法以及一些 GNU make 命令行选项。

  • 利用  plmake  编写 和运行更多的基于  t::Gmake 的 GNU make 测试,不断改进 Makefile::Parser 0.xx 的相关部件。

  • 利用 GNU make 的 -p 选项(即 --print-data-base 选项)取得它内部的数据库结构信息,以此为基础设计 出下一代 Makefile::Parser (即 1.x.x)所使用的 Makefile AST 结构。

  • 针对 Makefile AST 设计出纯 Perl 的运行时(Runtime),同时对 GNU make 进行包装,使之能 作为 makefile AST 生成器来使用。由此可以得到全功能的以 GNU make 为前端的 pgmake, 从而可以运行 GNU make 测试集。

    以 GNU make 为前端的 pgmake 的使命是为了得到纯 Perl 的 GNU make runtime (或者说是 AST Evaluator)

  • 另一种复用 GNU make 的技巧是将之用作纯的 Runtime. 具体做法是,从 Makefile AST 发射出 makefile 源代码,它只使用最最基本的 Makefile 语法结构,然后用下面的命令让 GNU make 去执行它:

        make -Rr -f foo.mk

    这儿的 foo.mk 便是 AST Dumper 生成的``基本 Makefile\'\'.

    利用这种技术,我们可以得到以 GNU make 为后端,以 Makefile::DOM 和全新版 Makefile::Parser 为前端的 pgmake。同样也可以去运行整个 GNU make 测试集。

    该版本的 pgmake 的使命是驱动并验证 Makefile::DOM 和 Makefile::Parser 1.x.x 这两个模块的开发工作。

\"\"\"\"
','agentzh','2007-03-16 09:58:00',0),(21,'毕业设计开发周记(第 3 周)','

过去一周工作的完成情况

过去的这一周大部分时间用来找工作了,呵呵。好在工作比想象中的好找, 所以也没有花费我太多的精力。

这些日子在毕业设计项目上取得了以下进展:

  • Makefile::Parser 开辟了 gmake-db分支
  • 在 GNU make database 的基础上设计出了 GNU make AST 的结构。它由下列几个类组成:
    • Makefile::AST

      总的 AST 类,提供节点的添加与查询,比如 add_implicit_rule,apply_implicit_rules,add_explicit_rule,apply_explicit_rules,add_var,add_auto_var,get_var,还有许多其他工具函数,比如计算变量最终值的方法 eval_var_value,有关局部变量作用域 Pad 的 enter_scopeleave_scope 方法,等等。

    • Makefile::AST::Rule::Base

      它是 AST 中规则节点的基类,包含 normal_prereqs,order_prereqs,commands,colon 这些属性。

    • Makefile::AST::Rule

      该类表示非隐式规则以及隐式规则“应用”之后的形式,从 Makefile::AST::Rule::Base 继承,并新增了 targetother_targets 属性。

    • Makefile::AST::Rule::Implicit

      该类表示 AST 中的隐式规则节点,从 Makefile::AST::Rule::Base 继承,并新增了 targets,match_anything,is_terminal 等属性。

    • Makefile::AST::StemMatch

      该类封装了含 % 的文件模式的匹配与 stem 替换算法。

    • Makefile::AST::Variable

      它表示 AST 中的变量节点,包含 name,value,flavor,origin 等属性。

  • 添加了 ast-basic.t,ast-rule.t,ast-var.t,和 ast-stem.t 脚本用于对 AST 及其相关类进行单元测试。
  • 实现了 Makefile::Parser::GmakeDB 类,用于解析由 make -qp 命令生成的 GNU make database,并构造出对应的 Makefile::AST 对象(即 GNU Make AST).

    有趣的是,GNU make 生成的 database 报表也是完全合法的 Makefile 格式,而且只使用最最基本的语法结构,因此 Makefile::Parser::GmakeDB 直接使用 MDOM::Document::Gmake 进行解析。

  • 实现了 Makefile::AST::Evaluator 类,用于按照 GNU make 的语义“执行”给定的 GNU make AST。

    值得一提的是,包括显隐式规则的应用在内的拓朴图的构建算法其实大部分实现在了 Makefile::AST 及其子节点类中了。

  • `make -pq`,Makefile::Parser::GmakeDB,和 Makefile::AST::Evaluator 三者串联了起来,组装成了一个完整的 make 工具,即 pgmake-db.

    该工具可以运行基于 IPC 的 GNU make 测试集。目前已通过了 sanity/func-refs.t 测试文件中 95% 以上的测试用例。

下一周的工作计划

下一周可能没有太多时间用来 hack 了,因为需要应付学校的结欠考试。但是顺着上一周的工作继续往下走应该是很容易的。我立刻能想到的工作有:

  • 添加 Makefile::AST::Command 类,用于将 Makefile 命令相关的处理封装起来,并为之添加文件名和行号的属性支持(file 和 line).
  • Makefile::AST::Variable 类添加 file 和 line 属性,以便能通过 func-refs.t 中余下的那些测试。
  • pgmake-db 通过尽可能多的 GNU make 测试集,同时根据 GNU make Manual 设计更多的有关变量和规则应用的综合测试用例,从而不断地完善 AST 的结构以及 AST 执行组件(evaluator)。
\"\"\"\"
','agentzh','2007-03-25 13:50:00',0),(22,'解决 RealPlayer 在 ubuntu 中没声音的问题','
记得一个月前我徒弟就报告过 RealPlayer 在 ubuntu 中光有图像没有声音的问题;没想到现在我自己却撞上了。好在经过反复的 Google,终于找到了下面的解决方法:

* 首先安装 ALSA OSS 驱动程序:\n

$ sudo apt-get install alsa-oss\n

* 然后编辑启动脚本 (/usr/lib/realplay-10.0.8/realplay) 并将第 73 行从

$REALPLAYBIN “$@”\n

改成
\n

aoss $REALPLAYBIN “$@”

对于我自己的 feisty fawn 而言,装的是 RealPlayer 10.0.7 版,需要修改的 realplay 文件中的那行位于第 70 行,而不是 73 行,呵呵。现在播放 .rmvb 文件终于有声音了!好棒哦~~~不必再通过用 VirtualBox 跑 WinXP 来看电影了,呵呵。

\"\"\"\"
','agentzh','2007-03-25 17:50:00',1),(23,'我对 Perl 6 开发的贡献汇集','
今天在看网上一篇关于我的评论的时候找到下面这个 URL:

http://groups.google.co.uk/groups?as_ugroup=perl.*&as_uauthors=Agent+Zhang

它汇集了有关我在过去一年中对 Perl 6 开发的贡献。可惜我没早些发现它,要不我的简历会更有力一些
,呵呵。

包含了该链接的 use perl 评论也很有趣:

http://use.perl.org/comments.pl?sid=33843&op=&threshold=0&commentsort=0&mode=thread&cid=52032
\"\"\"\"
','agentzh','2007-04-18 05:43:00',0),(24,'UML::Class::Simple 的用户反馈','

没想到我发布到 CPANUML::Class::Simple 模块居然得到了用户如此之好的反馈,开心哦:

http://cpanratings.perl.org/dist/UML-Class-Simple

通过 Google ,我又在世界上找到了两个 UML::Class::Simple 用户:

我一定要继续努力,开发出更多更好的 CPAN 模块!耶 !:D

\"\"\"\"
','agentzh','2007-04-18 06:43:00',0),(25,'为什么一个字节是 8 个比特?','
记得我们班的“超级天才”宝权同志曾在大一学 C++ 的时候问过一个很特别的问题,即“一个字节为什么是 8 个比特?”

昨晚,我将此问题贴到了 irc.freenode.net 的 #perl6 通道上,Larry Wall (TimToady), jerry gay ([particle]), moritz 参与了讨论。下面是当时的聊天记录(agentzh 就是我啦,呵呵):

<agentzh> a friend of mine once asked me why a byte is of 8 bits.
<moritz> agentzh: what did you answer?
<moritz> agentzh: \"computer scientist love powers of two\"?
<agentzh> moritz: i told him because ASCII code has 7 bits and the people want to feel safer and add one more
<TimToady> lol
<moritz> *g* nice explanation ;-)
<agentzh> thanks :D
<TimToady> and then the Europeans all added one more, and did we feel safer?
<TimToady> I don\'t think so...
* agentzh wants to hear TimToady\'s explanation.
<TimToady> I think the ASCII explanation is basically correct, from a cultural point of view. When people started programming PDP-11s and doing a lot of string processing, they decided it was convenient that it came close to a power of two, and stuck with it.
<TimToady> and it was also fairly obvious about then that the next generation would be 32-bit processors, and then you get 4 chars into it.
<TimToady> but I think the powers-of-two argument was kind of a post-facto rationalization of the ASCII culture
<TimToady> basically, Pascal and C thought in bytes, so everything else followed along.
* TimToady remembers various contortions of trying to rationalize the type system of C on some weird old architectures that were not amenable to bytes...
<TimToady> and the term \"byte\" itself had not yet settled on 8 bits
* moritz thinks of \"mix\", Donald E. Knuth\'s assembler, that doesn\'t rely on a fixed byte size
<TimToady> yes. 36-bit computers tended to use 6 bit characters
<[particle]> octet is the correct term, but byte has become a synonym
<TimToady> byte is now the correct term. octet will die eventually
<TimToady> and go back to being 8 singers.
<TimToady> except for in standards documents, where it will likely remain a shibboleth

原始的聊天记录位于:

http://colabti.de/irclogger/irclogger_log/perl6?date=2007-04-17,Tue&sel=451#l672

包括上面这段记录的上下文,呵呵。昨天晚上 Larry 真是妙语连珠,Joke 不断啊。不愧是大师级人物……

章亦春
\"\"\"\"
','agentzh','2007-04-18 07:43:00',0),(26,'给唐凤的生日礼物','

今天是 唐凤 的生日,真的很开心啊,祝 Audrey 生日快乐!

根据  Gaal 的提议 , 这几日我成功地在  feather  服务器上建立了 Pugs 的自动化 smoke 设施, 算作是 给唐凤的生日礼物 。 :D

现在 feather 上的 cron 程序每隔 24 个小时就会自动运行最新版本的 Pugs 测试集,并生成包含“灵巧链接”的 Perl 6 Synopses 文档:

http://perlcabal.org/syn/

比如其中的 S04:

http://perlcabal.org/syn/S04

你在其中会看到,我的  smartlinks.pl 程序会将一组一组的测试插入到文档的对应位置上,并根据 Smoke 生成的测试报表,用 × 在对应的行上,标记每一个特定的测试。

唐凤的 Pugs 博客上的几篇文章就是介绍这种 smartlinking 技术的:

前两篇是我写的,第三篇是  Mark Stosberg  写的。Mark 为我们的 feather 网站做了许多工作:

http://use.perl.org/~markjugg/journal/30739

markstos++ ;)

在 feather 上运行无人监管的自动化 smoke 在技术上需要一些特别的考虑:

  • cron 自动运行时刻的选择

    显然应该 smoke 的时间选在 feather 服务器一天当中负载最轻的时候。feather 的主人 Juerd 告诉我 在欧洲中部时间的晚上,一般会比较空闲,而白天 feather 的备份系统会比较地繁忙。因此我就在 crontab 中指定了 CET 1:00 AM.

  • CPU 和 RAM 资源的控制

    由于 Pugs 处于活跃的开发当中,在测试集运行的过程里,有些测试可能会陷入死循环,或者消耗掉所有内存, 而最终挂起或者让系统崩溃。由于 Juerd 并未对 feather 用户的资源进行限制,所以我需要自己使用 nice 和 ulimit 来进行资源限制。利用 nice 可以让 smoke 系统中的进程处于比较低的优先级,从而确保系统的其他用户仍能比较快地获得系统的响应。 而 ulimit 则可以限制 shell 实例中允许使用的总的内存量和 CPU 时间。

    目前,我为 smoke 系统中的进程分配的 NICE 数为 5 到 10 的样子, 而每一个 ./pugs 进程实例只允许使用最多 800 MB 的虚拟内存和 10 分钟的 CPU 时间。 一旦某个 ./pugs 实例超过了规定的时间或空间限制,系统就会 KILL 掉它,但这并不会中断整个 smoke 过程, 只不过对应的那组测试被标记为失败而已。

    说实话,nice 和 ulimit 还是 Juerd 向我介绍的 。 惭愧啊,呵呵。

    将 nice 和 ulimit 结合到一起,我便得到了一个“受限Pugs”,也就是下面这个 limited_pugs 脚本:

    http://svn.pugscode.org/pugs/util/limited_pugs

    关于其中一些 Bourne Shell 记法,我还 专门请教了 #perl6 频道中的高手们。

  • cron 活动的监视和诊断

    令人高兴地是, cron 在指定的时刻自动运行指定的命令的同时会记录下所有的 stdout 和 stderr 输出,并将之发送到我的 Gmail 信箱。 这样,监视和诊断远程 feather 服务器上的 auto-smoke 过程就是轻而易举的事情了。cron++

    今天早上我已经收到了 feather cron 发送给我的第一份 auto-smoke 的报告。看起来它工作得非常好。Yay!

\"\"\"\"
','agentzh','2007-04-18 08:43:00',0),(27,'Custom List: 更多个人信息','

更多个人信息

\"\"\"\"
','agentzh','2007-04-18 11:43:00',0),(28,'Want a commit bit?','

As seen on #perl6 today:

  <zxagent> agentzh: hello master
<agentz> zxagent: hello, boy :)
<agentz> zxagent: nice to see you here.
<agentz> zxagent: want a commit bit?
*** zxagent left the room (quit: Remote closed the connection).
<agentz> oops, too late
<TimToady> maybe you scared him off
<agentz> TimToady: *nod*

人物介绍

  TimToady: Larry Wall
zxagent: 我徒儿张星
agentzh: 我

结论

我徒弟实在是太有个性啦!

\"\"\"\"
','agentzh','2007-04-20 13:13:00',0),(29,'CPAN is kid-safe? (关于 Ingy 的 XXX 模块)','

As seen on #perl6 recently:

 <ingy> agentzh: http://rafb.net/p/I2uDsd35.txt
<ingy> try running that
<agentzh> looking
<ingy> you\'ll see that you can easily inspect all the things you want
<agentzh> what is XXX?
<ingy> a module
<ingy> :P
<ingy> it dies with a YAML dump
<ingy> it is arguably my most useful module
<agentzh> 1..1
<agentzh> Can\'t locate XXX.pm in @INC
<ingy> install it
<agentzh> wow
<agentzh> it\'s a real module?
<ingy> yes
<agentzh> awesome
<ingy> http://search.cpan.org/CPAN/authors/id/I/IN/INGY/XXX-0.10.tar.gz
<ingy> you can stick an XXX just about anywhere
<ingy> also comes with WWW YYY and ZZZ :)
<ingy> unfortunately XXX won\'t index
<gaal> CPAN is kid-safe?

不幸的是,就在这段聊天结束以后几个小时,Ingy 在台湾的公路上遭遇了一起严重的交通事故, 现在还在医院里急救。哀心地祝愿 Ingy 能够转危为安,早日康复!

\"\"\"\"
','agentzh','2007-04-20 15:13:00',0),(30,'三叶草','
昨天在校园里漫步的时候,偶然间发现路旁的绿地上竟满是我最爱的三叶草。圆圆的叶子是那么娇嫩,那么雅致。我仿佛能觉出一缕淡淡的幽香……
\"\"\"\"
','agentzh','2007-04-29 16:20:00',0),(31,'ulimit++','

As seen on #perl6:\n\n

    <agentzh> oh, if i restrict each ./pugs instance to 100 MB RAM, only 77.25% of the test suite is in green.
<agentzh> when assigning 800 RM, the passing rate returns to the normal level (97.09%)
<agentzh> ulimit is so handy :)
<moritz> ulimit++ ;-)
<TimToady> careful, you might exceed ulimit\'s karma limit...
<agentzh> lol
<moritz> @karma ulimit
<lambdabot> ulimit has a karma of 1
<gaal> and then what, it\'ll kill itself? under some beliefs, that lowers its karma
<moritz> what was ulimit\'s limit again?
\"\"\"\"
','agentzh','2007-05-01 12:21:00',0),(32,'[OT] 搬家了','
今天 live.com 慢得直接就点不进去,一气之下,决定搬家 :)

如今我的博客已搬到了 Google 的 Blogger 上了:

http://agentzh.blogspot.com

呵呵,网址比原来用的那个 agentzh.spaces.live.com 还要短一些,耶,好棒!

而且 Blogger 响应很快,功能丰富,比如支持直接通过电子邮件发表文章,有人发表评论时会自动发送电子邮件提醒我,另外允许匿名访问者发表评论,模板也觉得很漂亮,呵呵。

我已经通过 email 将这个 live.com 博客中有点儿价值的文章都导入到那个新的主页上去了。欢迎继续关注和发表评论!谢谢!

大家可以通过 http://agentzh.blogspot.com/feeds/posts/default 在你最喜爱的 RSS 阅读器(比如 Google Reader中)订阅我的新博客 :)

(说实话,我不太理解为什么身边有这么多朋友使用 live.com……受不了……)

\"\"\"\"
','agentzh','2007-06-04 07:29:00',0),(33,'我又回来了...','
我心爱的 agentzh.blogspot.com 被 GFW 掉之后,无奈之下我又回来了。

人生就是这样充满了无奈……
\"\"\"\"
','agentzh','2007-06-23 19:33:00',0),(34,'毕业设计开发周记(第13周)','

2007年6月4日

毕业论文交稿日期在即,而我还在努力奋斗,呵呵。

几天前刚刚发布了通用事情仿真引擎 Sim 到 CPAN:

http://search.cpan.org/dist/Sim

可惜与我的毕业设计并无直接关系。

这\n两日我正工作在从 GNU make 生成的 makefile 数据库列表解析生成 makefile AST 的\nMakefile::Parser::GmakeDB 以及 AST 库 Makefile::AST 和 makefile 运行时(即 AST\n的执行器) Makefile::AST::Evaluator.

从最高的尺度上讲,它是一个 gmake 和我的 Makefile\n库所组成的``混血儿\'\'。后端借用了 GNU make 的 C\n实现,完成绝大部分的词法分析和词法分析的任务,以及在那个阶段上完成的执行动作;后端从 AST 开始一直到运行时,都是我自己的 Perl\n代码。中间的对接复用了我的那个``不怎么好的\'\' Makefile 解析器,即 Makefile::DOM,外加一些 AST\n构造代码,这便构成了 Makefile::Parser::GmakeDB. 所有部分合在一起便是一个比较完整的 make 工具(我已将之命名为\npgmake-db)。

我现在正以测试驱动(TDD)方式不断完善 pgmake-db 脚本及相关组件,特别是 AST 的设计及 AST 以后的运行时实现。到写这封邮件的时候为止,我已让 pgmake-db 通过了 50% 以上的 gmake 测试集:

http://svn.openfoundry.org/mdom/branches/gmake/t/gmake/

Makefile::Parser::GmakeDB, Makefile::AST, 和 Makefile::AST::Evaluator 的源代码(gmake-db分支)都位于下面这个位置:

http://svn.openfoundry.org/makefileparser/branches/gmake-db/

Makefile::DOM (gmake分支)的源代码位于:

http://svn.openfoundry.org/mdom/branches/gmake/

短期目标

  • 在未来几天中,让 pgmake-db 程序通过 GNU make 90% 以上的测试集(并将官方测试集中未移植到 Test::Base + IPC::Run3 测试台的部分移植过来)。这样就可以得到比较完美的 AST 及 Evaluator 部件了。

  • 在\n未来两周中对 Makefile::DOM 进行改写,并在之基础上开发 Makefile::Parser::Gmake(可借鉴\nMakefile::Parser::GmakeDB 的一些代码和算法),从而能取代 Makefile::Parser::GmakeDB 而与\nAST 及运行时后端实现对接。

长期目标

  • 以全新的 AST 和 Evaluator 为基础改写 Makefile::GraphViz 模块,从而使之趋近``完美\'\'

  • 从全新的 AST 出发,发射 NMAKE, PerlBuildSystem 格式的配置代码。

  • 从 DOM 出发,发射``地道而无损的\'\' NMAKE, PerlBuildSystem 格式的配置代码

  • 为 Makefile::DOM, Makefile::Parser 以及其他后端部件添加对其他格式的 makefile 的支持(如 NMAKE, BSD make, 和 dmake)

  • 尝试将 NMAKE 格式的 makefile 翻译到 GNU make 格式

短期目标希望能在答辩之前完成,并写进我的毕业论文。长期目标目前看来只能放到毕业之后继续了,呵呵。

唉……这学期大部分时间都放在考试复习、找工作和其他的事情上了……所以现在时间紧得不得了。\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(35,'pgmake-db通过官方测试集的35%','
2007 年 6 月 5 日

昨\n天我继续以测试驱动(TDD)方式完善我的基于 Makefile::Parser::GmakeDB 的 pgmake-db 程序,结果在调试\nGNU make 官方测试集中的 features/escape.t 和 features/export.t 的时候遇到了 GNU make\n的 database 输出支持上的两个 bug.


一是 gmake 在输出的 makefile 语法的数据库列表中没有对目标和依赖项中的元字符进行转义,比如 :, \\, 和 #. 该 bug 已作为 Savannah bug #20067 报告给了 GNU make 团队。先前我还另外发了一封 email 到 bug-make 邮件组:

http://www.mail-archive.com/bug-make@gnu.org/msg04650.html

从 GNU make 的“看门人” Paul Smith 的回复中可以看到,没有多少人会将 `make -pq` 命令的输出喂给其他程序(包括 gmake 自己),因此其记法上的合法性并没有经过很好的测试。

该问题在 gmake 那边尚未修复,我已在本地通过预处理 db 输出的方法绕开了这个 bug.

二\n是 gmake 生成的 db 输出中缺少 export/unexport 指令的信息,这使得 GmakeDB 模块构造的 AST\n亦缺少这样的信息,从而使得 features/export।t 测试文件暂时无法通过。更糟糕的是没有简单的方法能绕开它。该问题我已经以\nSavannah bug #20069 的形式报告给了 GNU make 团队,目前尚无回复。

除\n了和 GNU make 的限制角力之外,我还修复了 pgmake-db 中的一些小问题,从而使 Makefile::DOM 的 gmake\n分支中基于 t::Gmake 的测试集的(文件)通过率从 50% 提高到了 60% ~ 70%.余下的拦路虎是\nfeatures/order_only.t 所需的 order only prepreqs 支持和 features/override.t\n所需的 Canned Command Sequences 和 Defining Variables Verbatim\n支持。这些改动都比较大,所以最好还是放到学校图书馆去构思吧,呵呵。

另外,features/double_colon.t 中还有一个测试在前天跳过了,即 Savannah bug #14334,该行为实现起来相当有难度,但我已想到了一种解决的方法,即该 bug thread 中所说的\"postponing this timestamp propagation until after all individual rules have been updated \".

昨\n天晚上我还 checkout 了一下 GNU make 的 CVS 源代码仓库,并想办法让官方测试集能运行我的 pgmake-db.\n经过一番努力,终于得到了 35% 的测试通过率。由于官方测试集使用的是 Perl 4 代码,根本未利用现代 Perl 5 基于\nTest::More 的测试台技术,所以它并不适合我进行 TDD. 而且所有的测试脚本都运行在和测试台 Harness 相同的进程中,导致\nulimit 在杀死挂起的测试脚本的同时也杀死了测试台 Harness,从而得不到最后的测试报表。现在已知\nfeatures/patternrules.t 会限入死递归,并吃掉所有内存,另外 functions/sort.t 也很占用 CPU\n时间。这些都有待于后续工作来修复。

目前官方测试集仅有不到一半的用例移植到了我的基于 t::Gmake\n的测试平台上。这些还是从前我手工进行转换的。昨天晚上我终于想到了一种非常巧妙的自动转换方法,即利用 mocking 的方法运行那些用 Perl\n4 写成的官方测试集脚本,从而采集到所有数据,并生成 Test::Base\n的声明性的用例格式。该方法的优点是可靠、安全、快速,同时也非常容易实现。原先我考虑的转换方法是去解析那些 Perl 4 代码。显然即便是\nPerl 4,其语法也是相当复杂的(使用 PPI 也需要许多代码),至于其语义分析那就更加困难了。

通\n过 mocking 工具函数运行待解析代码,来提取所需信息的技术很像 Perl DSL(Domain Specific\nLanguage),比如 CPAN 上的 Template::Declare 和 Object::Declare 模块就是\"借用\" Perl\n语言来生成 HTML 或者其他东西。很有些\"借尸还魂\"的味道哦。借用现有的 Perl 语言或者 Perl\n解释器可以大大减少对自定义编译器的需求。无论如何,编写一个解析器都不是轻而易举的事情。

所有这些有趣的东东都打算今天在图书馆里搞出来。祝我自己好运啦 :)

P.S. 发送 email 的同时亦能发表博客文章,实在太帅,呵呵。\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(36,'挤进CPANTS前50强','
2007年6月5日

今天在 CPANTSKwalitee 排名列表中看到自己的 CPAN ID AGENT 已是第 45 名了:


http://cpants.perl.org/highscores/many

而且已经在 chromatic 的前面了,呵呵。

当然了,这既不是 quantity 也不是真正意义上的 quality,而是 kwalitee,呵呵。

以后有时间一定把我那些模块中余下的红色区域修复:

http://cpants.perl.org/author/AGENT

这样我就可以达到 100 分了,呵呵。

\"\"\"\"
','agentzh','2007-06-23 19:33:00',0),(37,'毕业设计开发周记(第14周)','
2007 年 6 月 10 日

过\n去的一周集中了几乎所有力量于 pgmake-db 的开发,修复了 DOM 解析器、GmakeDB AST 构建器,AST,和 AST\n执行器(runtime) 中的许多 bugs,包括那个曾经让我非常头疼的 double-colon 测试(即 Savannah bug #14334),并且在各个组件中实现了许多重要的 GNU make 特性,包括:


* Pattern rules
* Target-specific rules
* Order-only prerequisites and normal prerequisites
* Phony targets

* Canned sequence of commands
* Command modifiers \'@\' and \'-\' and their various combinations
* Line-continuations (\"\\\\\\n\") in commands

* Automatic variables $@, $<, $^, $*, $|, and $+
* Verbatim variables defined by the \'define\' directive
* Simply-expanded variables and recursively expanded variables
* Most of the builtin function references

* -f --file --makefile command line option
* -n --just-print --dry-run --recon command line option
* -s --silent --quiet command line option
* -i --ignore-errors command line option

* Circular dependency checking

还有许多特性是我复用的 GNU make 前端\"免费\"提供给我的 pgmake-db 的:

* Syntax issues like variations of comments, line-continuations outside commands
* Variable overridding by the override directive
* Variable overridding by the command-line variables
* Conditional directives like ifdef/ifeq
* Global makefile variable assignment using \'+=\', \'?=\', and redefining

目前已知 GNU make 的数据库输出功能()存在下列 bugs:

* Savannah bug #20067: Unescaped meta characters in makefile database outputs
* Savannah bug #20069: Request for unexport/export info in makefile database outputs
* Savannah bug #20133: \'make -p\' always uses \':=\' for pattern-specific variable assignments
* Continued commands\' leading whitespaces are missing in the DB output

这\n些 bugs 使得至少 export/unexport 和 Pattern-specific variable assignment\n这两个特性无法实现,阻止了官方测试集中对应的那 2 个测试文件的通过(即 features/export 和\nfeatures/patspecific_vars)。

目前 GNU make 官方测试集已通过近一半的测试用例(约48%),其中完全通过的测试文件列表如下(共 36 个文件):

features/comments
features/conditionals
features/default_names
features/double_colon
features/echoing
features/errors
features/escape
features/include
features/mult_rules
features/mult_targets
features/order_only
features/override
features/patternrules
features/quoting
features/varnesting
features/vpath2
features/vpathgpath
functions/abspath
functions/addprefix
functions/addsuffix
functions/basename
functions/dir
functions/filter-out
functions/findstring
functions/join
functions/notdir
functions/realpath
functions/substitution
functions/wildcard
targets/PHONY
targets/clean
variables/CURDIR
variables/MAKEFILES
variables/MFILE_LIST
variables/negative
variables/special

事\n实上,functions/, variables/, 和 targets/\n目录下的不少失败的测试,稍加调整就可以通过,但目前那些测试尚未导入到我的基于 t::Gmake\n的测试台中,故还需要先编写一个自动转换程序。(该程序昨天上午的时候已经在学校图书馆里打好草稿了,呵呵。)

我自己现有的基于 t::Gmake 的测试集的文件通过率已达到 90% 以上,只有 3 个测试文件失败了,而且其中有两个文件还是因为 GNU make 的 bugs,而不是我的问题 :)

现在剩下的时间真的不多了……必须得赶快开始写毕业论文了……我晕……今天打算把那个测试集升迁程序准备好,把官方测试集中余下的测试导入到我的测试台中,然后把那些本该通过却未通过的测试调通,这样不费多少气力,就可以进一步地提高测试通过率。

其\n实现在从我的 Makefile::Parser::GmakeDB 构造的 AST 出发,结合 Makefile::AST::Evaluator\n中的算法,已经可以开发出许多非常有趣的应用了,比如从任意复杂度的 GNU makefile 生成最最简单的只含简单规则的\"基本\nMakefile\",从而可以为所有其他版本的 make 正确处理,再比如利用类似的技术生成其他非 make 构建工具的配置文件,如 Ant 和\nPBS。另一个例子就是全新版的 Makefile::GraphViz 了,从任意复杂度的 GNU makefile 生成拓朴树的示意图。

这些应用看起来好像很复杂,但其实从现有的 pgmake-db 各个环节的代码出发,只需要几十行代码就可以搞定!

可是……我现在缺的只有时间!

P.S. 毕业论文就用 Perl 6 的 POD 来制作吧!该是在我自己的工作中实用一下 Damian 的 Perl6::Perldoc 模块的时候了!耶!\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(38,'\"Ant is clumsy\"','
2007 年 6 月 10 日

LOL. From the page \"tools useful for A-A-P\" :
          Ant
Java based build tool, like make, but uses classes and XML. Portable over systems, but requires Java.
\nWriting a build file in XML file is clumsy. XML is nice for computers\nto parse and produce, not for humans. Flow control is even more clumsy,\nXML is not a scripting language.
Can be used for ideas how recipes work.
Well, I must say I totally agree but I won\'t try to advocate make against Ant to those conservative Java programmers ;)

And...make\n*can* be evil, but not necessary, just like Perl. It depends on the\nmonkeys who are using them, not on the language or the tool itself :)

So, take care...\"\"\"\"
','agentzh','2007-06-23 19:33:00',0),(39,'从Perl 4到Test::Base','
2007 年 6 月 11 日

昨天经过好几个小时的努力,终于完成了GNU make官方测试集到我的基于 Test::Base 测试台的自动转换程序p4_to_t.pl:


http://svn.openfoundry.org/mdom/branches/gmake/script/p4_to_t.pl

哇,\n440 行Perl 5代码耶,比我想象得长多了,也比我想象得复杂多了……但它也比我想象得有用多了!该脚本已将官方测试集中所有的用Perl\n4写成的测试脚本转换成了对应的 .t 文件,并且其中有 70% 以上的 .t 文件完全通过了GNU make程序的测试。

其基本原理如下:

1. 使用 PPI 模块解析Perl 4测试文件,提取出其中的 Perl 注释(不包括makefile注释!),并将之替换成函数调用形式。比如原文件中的

# Test #1: Test the order-only prerequisites

将被识别并替换成下面这一行:

comment(\"# Test #1: Test the order-only prerequisites\");

其目的在于在翻译后的 .t 文件中也能保留原始文件中的这些注释。而一般情况下Perl注释是无法流过perl解释器的,除非使用source filter. 但source filter本质上也需要对这些注释进行识别和提取。

值得一提的是,由于 PPI 的当前版本不能处理下面这种形式的 Perl heredoc

print MAKEFILE <<\\EOF;
all: ; @echo hello
EOF


所以在把Perl 4源代码喂给 PPI 之前需要用正则替换把上面这几行预处理为下面这种等价形式:

print MAKEFILE <<\'EOF\';
all: ; @echo hello
EOF


我昨天已经发了一封 email 给 PPI 的作者 Alias,报告了该问题。

2. 给经过注释转换的Perl 4文件加上一个文件头,在这个文件头中提供了GNU make测试驱动提供的那些工具函数的mocking版本,主要包括: rmfiles, utouch, touch, run_make_with_options, compare_output, run_make_test. 同时还需要 mock 一下测试文件可能调用到的\"Perl内建函数\"和Perl标准模块,比如 unlinkCwd. Mocking像Cwd这样的Perl模块,我用到了Test::MockClass模块。

这\n些mocking版本的函数的功能主是让原始的Perl 4测试脚本\"感觉\"自己好像运行在了GNU\nmake官方的测试平台上,但事实上,我的这些函数根本不执行任何测试动作,而是记录下所有的调用历史,特别是参数和上下文变量的值,然后生成一个与\nTest::Base 块/段结构相应的数据结构。

另外,还需要定义一下测试文件所需的配置变量,比如$mkpath, $make_name, $makefile, $delete_command等等。

文件头中还包括了一个 END 块,用于在测试脚本退出时,从采集到的数据结构生成 Test::Base 格式的 .t 源代码。

3. 通过 IPC::Run3 模块将进行修改的Perl测试脚本喂给perl解释器执行之,并将它的 stdout 输出采集起来,写入到 .t 文件。

由于官方测试集的格式相当整齐(请参考GNU make团队成员所使用的 测试文件模板),所以绝大多数的的测试用例都可以完美地翻译过来,而且质量可以与我手工翻译的质量相媲美。但也有两方面的限制:

1. 原始测试用例都是上下文有关的,而我的基于 Test::Base 的测试用例都是上下文无关的,即前一个测试的结果和环境不会影响到下一个测试。虽然 p4_to_t.pl 脚本采用了许多技巧自动跟踪和隔离上下文信息,但难免会有一些特殊情况无法跟踪到。

2. 如果一个测试用例涉及多个 makefile,则无法正确翻译--事实上此时手工翻译都需要动一翻脑筋的。

最后欣赏一下直接由p4_to_t.pl脚本生成的全新版的测试集吧(未经过任何手工编辑):

http://svn.openfoundry.org/mdom/branches/gmake/mech_t/

呵呵 :)\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(40,'Pod::POM::Web','
2007 年 6 月 12 日

Found today on Perl.com:

CPAN Module Review: Pod::POM::Web

For years, my schoolmates and I have been relying heavily on my \"viewpod\" script based on Catalyst (Yes, search.cpan.org is slow and way too scattered!). Now there is a better alternative.

I\'ve\ngiven it a shot in my ubuntu box and it\'s *really* impressive. Not sure\nabout its Win32 compatibility though. Reports welcome ;)\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(41,'makesimple: 从GNU makefile到“简单makefile”','
2007 年 6 月 12 日

或许我真的应该开始写论文了,但我还是忍不住实现了一个 GNU makefile 的翻译程序makesimple:

http://svn.openfoundry.org/makefileparser/branches/gmake-db/script/makesimple

该程序能将非常复杂的 GNU makefile 转换成最最基本的形式,即所谓的\"简单makefile\"。

\"简单makefile\"中只有单目标的显式规则,没有变量赋值,没有变量引用,没有条件指令,没有模式规则,没有所有其他看上去\"高级\"的东西。因此它可以不加修改地为其他版本的 make 正确处理,比如 nmake 和 dmake.

而作为输入的 makefile 则可以使用GNU make手册中描述的绝大部分的高级特性,包括

  • 多目标规则 (multi-target rules)
  • 双冒号规则 (double-colon rules)
  • 隐式规则 (implicit rules/pattern rules)
  • 链式隐式规则 (chained implicit rules)
  • 静态模式规则 (static pattern rules)
  • 仅顺序依项目 (order-only prerequisites)
  • 自动变量 (automatic variables)
  • 目标局部变量 (target-specific variables)
  • 由 define 指令定义的逐字句变量 (verbatim variables)
  • 简单展开变量 (simply-expanded variables)
  • 递归展开变量 (recursively-expanded variables)
  • 命令序列束(canned sequence of commands)
  • 命令修饰符 @, - 和 +
  • 利用续行符 (\"\\\\\\n\") 跨越多行的命令 (commands spanning multiple lines)
  • 绝大多数内建函数引用 (built-in function references)
  • 条件指令 ifdef/else/...
详情请见下面这个测试文件中的测试用例(只需看 __DATA__ 那行之后的内容就可以了):

http://svn.openfoundry.org/makefileparser/branches/gmake-db/t/makesimple.t

另外 include 指令和其他词法/语法层面上的特性也应该工作得很好,因为那是前端提供的\"免费功能\",呵呵。

这些特性都是我的 Makefile::ASTMakefile::AST::Evaluator 模块提供的实现。我的 makesimple 脚本只是利用了 Class::Trait 模块,在 Makefile::AST::Evaluator::make_by_rule 方法里定义的锚点位置上,把 Makefile::AST::Rule 对象和对应的 Makefile::AST::Command 对象全部记录下来。 Class::Trait 简直就是天赐之物,实在想不出能让我的 Evaluator 代码保持整洁,同时又提供给用户应用足够大的灵活性的更理想的解决方案了!难怪 Jesse 会在 Jifty 项目中大力推动该模块的应用呢。

目前 makesimple 脚本会自动轮询 makefile 中所有出现的目标,而且用户可以在命令行上指定额外的目标。额外的目标对于隐式规则的应用而言至关重要,毕竟 GNU make 中有太多的\"魔法\"。

Audrey 的 Module::Install 模块生成的庞大的 GNU makefile,经过 makesimple 转换后,仍然工作得很好。这是第一个现实世界中的测试用例啊。

makefilesimple\n在翻译时会保持\"默认目标\" (default goal),包括用 .DEFAULT_GOAL 显式指定的默认目标以及出现在输入\nmakefile 中的第一个非隐式规则的目标。默认目标如果对应一个双冒号规则集 (set of double-colon\nrules),也能正确地处理 :)

makesimple 的 TODO:
  • 对用户显式指定的某些变量不进行第二\n次遍历 (the second pass) 中的展开操作,除非它是某个 GNU make\n内建函数的参数,代之以变量赋值语句,从而提高“简单makefile”的灵活性,这样使用翻译版本的最终用户可以自己修改这些变量的值,比如\nCC和CFLAGS 这样的变量就经常需要自己进行调整。但是,第一次遍历过程中的变量展开操作必须进行,否则解析器很可能无法继续。
  • 对用户显式指定的某些变量的某些取值进行轮询,并将由此得到的不同版本的\"简单makefile\"作为一个一个的代码块,填进\"目标 make\"支持的条件语句中。(这让我想起\"程序设计方法学\"中结构化程序的正确性证明中用到的\"分支展开\"技术,呵呵)
  • order-only 依赖项需要更理想的翻译方法,目前是直译。
  • 提供 shell 命令翻译的解决方案。可以尝试类似 sh ==> cmd 这样的自动转换,以及类似国际化支持中的用户自定义翻译。(见 Locale::Maketext 模块。)
正如你可能已经猜到的,makesimple 脚本就是“传说中的” Makefile::Compiler 模块的一个原型实现!Come on!

与 makesimple 相似的另一个有趣的应用就是在全新的 makefile AST 和 Evaluator 的基础上改写我从前发布在 CPAN 上的 Makefile::GraphViz 模块。现在从任意复杂的 GNU makefile 生成依赖图的 PNG 图片已经是很容易很容易的一件事情了!

毕竟依赖关系示意图本质上只是\"简单makefile\"的另一种表示形式而已,技术上实现起来极为类似,呵呵。

但现在--论文高于一切!\"\"\"\"
','agentzh','2007-06-23 19:33:00',0),(42,'pgmake-db通过官方测试集的50%以上','
2007 年 6 月 12 日

由于前面为实现 Makefile \"脱糖\" 程序 makesimple,我为我的 pgmake-db 程序添加了 --question (-q) 和 --always-make (-B) 选项,并在 Makefile::AST::Evaluator 中提供了相应的支持,与此同时还修复了隐式规则搜索算法的实现代码中的两处严重的 bug。这些改进最终使得我的 pgmake-db 对官方测试集的通过率首次超过了 50%. 万岁!


事实上,以目前 AST 和运行时的架构,完全足以通过 90% 以上的官方测试集,只不过不少小东西还需要花时间去打磨。只要给我满满一周的时间,我有信心让它达到 90% 以上。但目前条件并不具备。

从目前的实现出发,可以开发出许多很酷的应用。关键就看我们的想象力了。我的 makesimple 脚本已经掀开了从 GNU makefile 到其他格式的项目配置文件的序幕。事实上,makesimple 程序最终将演化为\"传说\"中的 Makefile::Compiler 模块中的一个部分。呵呵。

将当前 pgmake-db 借用的 GNU make 前端 Makefile::Parser::GmakeDB\n模块替换为纯 Perl 实现(即未来的 Makefile::Parser::Gmake 模块)也可以推动 DOM parser\n的开发工作,特别是提高我整个工具链的可移植性和整体可靠性。与此同时,纯 Perl 的 GNU make 工具链,有助于横向上开发其他种类的\nmakefile 的工具链,比如 MS nmake 的从 DOM 到 AST 再到 Evaluator\n的工具链。届时,项目的可复用性、开放性和灵活性将超过我目前的想象能力,呵呵。

Alas, time is always a problem :(

.oO( 论文...论文...论文... )\"\"\"\"

','agentzh','2007-06-23 19:33:00',0),(43,'大学四年回顾...','
2007 年 6 月 13 日

今天填了一些表格,需要写自我鉴定和个人小结之类的东西。想想把我写的发给大家看看也蛮有趣的,呵呵。全文如下:


经过四年的学习,终于顺利完成了大学里那些数量众多同时难度颇深的课程的学习,并自学了许多课外的知识和技能。

对\n我来说,学校能教给我的东西是极为有限的。更多地,学校扮演着这样的一个角色:她为我提供一个学习、思考和实践的平台,是我大量地积累知识和技术的主要推\n动力之一,她为我创造了许多软件项目和科学研究的原始需求和灵感源泉,同时也为我提供了极为丰富的图书资源。说实话,四年来,学校的课程对我的不间断的巨\n大压力迫使着我不断地攀登技术高峰,不断地补充自己在众多不同领域的基础知识,不断地完成越来越复杂、越来越重要的项目和课题。

相信与\n否?我大学中最重要的时光是在英特网上度过的。和身边许多同学在网络游戏中沉沦不同的是,我积极地参与到了国际 Perl\n编程社区的活动中,投身到了包括 Pugs 和 Jifty 在内的开源软件项目的开发工作中,与包括 Audrey Tang , Larry\nWall, Adam Kennedy, Luke Palmer 在内的许多世界知名的程序员进行过比较深入的交流,并建立起良好的关系。

我\n与世界各地的程序员保持着广泛的沟通与联系,甚至进行协同开发。从他们身上,我学到了太多太多。我学到的不仅仅是许多具体的技术和技巧,还包括他们的似火\n般的热情,绅士般的风度,朋友般的友善、君子般的谦逊……更重要的是他们面对问题、处理问题和解决问题时的发散式、跳跃式的思维方法,以及一丝不苟、一切\n务实的行事原则。当然,还有英语表达上的许多技巧。在这种场合下,我才发现原来熟悉英语是一件非常幸福的事情。和不同国家、不同肤色的志同道合的朋友无障\n碍地交流,细细想来,还真是一件不可思议的事情,呵呵。

我这个人喜欢体验创新,喜欢冒险,喜欢不断尝试各种有趣而新奇的想法和事物。我也\n喜欢一个人静静地坐在图书馆里潜心阅读计算、数学、物理、生物、化学和历史方面的英文原著,抑或是坐在风和日丽的山头,思索科学和人生中一些有趣而重要的\n问题,或者和大学和中学里结交的好朋友们呆在一起,畅所欲言,天马行空,热烈地讨论技术和科学中已经发生的、正在发生的、和将要发生的那些不可思议的事\n情……\"\"\"\"

','agentzh','2007-06-23 19:33:00',4),(44,'My name appears on Wikipedia!','
2007 年 6 月 13 日

Quoted from http://en.wikipedia.org/wiki/Parser_Grammar_Engine :

References

  1. Michaud, Patrick R. (2004-11-22). Parrot Grammar Engine (PGE).
  2. ^ Michaud, Patrick R. (2004-11-08). First public release of grammar engine.
  3. ^ \"Agent Zhang\" (2006-09-17). PCR replaces PGE in Pugs.

Huh, I posted the article \"PCR replaces PGE in Pugs\" to Audrey\'s blog site about one year ago:

http://pugs.blogs.com/pugs/2006/09/pcr_replaces_pg.html

Hey, it\'s really exciting. Yay!\"\"\"\"
','agentzh','2007-06-23 19:33:00',0),(45,'YAPC::Beijing 2007','
2007-06-24

连夜用 Perl 6 的 Pod 赶好了我的 GNU make 类库的毕业论文,15 日下午便登上了前往北京的火车去参加 YAPC::Beijing 2007 大会--带着 0 张幻灯片却申请了 2 场演讲!

第一次一个人出这么远的门,刚上火车的时候还真有些神经质,呵呵;脑袋里浮现出电影《天下无贼》中的画面……还好,我这一路上运气不好,没遇上那样的贼中高人。没过多久,我就被困倦打倒了,睡了一路。

16 日早上路过天津的时候确实有些伤感,但很快在杉哥的帮助下挺过去了,呵呵。

到了北京站,见着了 cnhackTNT(王晖),\nhoowa(孙冰), 和另一个叫做张建军的大连的朋友。一道打车去了东三环附近的百子湾路上的如家国贸店安顿了下来。这一路上,hoowa\n说的都是他的 Asterisk 技术。可以通过 Perl 脚本向任何一部手机和任何一部固定电话打电话,并且能给接听方播放 mp3\n文件。的确很酷哦!

我和 TNT 住一间,他们俩住一间。TNT 真是极好的人哪,得知我还是 0\n张幻灯片以后,主动提出将他随身带过来的笔记本电脑借我使用。由于如家酒店提供了网线,再加上 TNT 的笔记本又是\nubuntu,幻灯片的制做过程非常地顺利……但却仍然用了一下午加上一晚上的时间……这是真正意义上的向唐凤学习--JIT\nslide-making!

16 日在开始做幻灯之前,我和 TNT 去雅虎中国见了 nomas 和\nyuting,并一起用了午餐。nomas 有些富态,非常和蔼可亲的人哦;而 yuting\n则是不修边幅、踩着拖鞋啪哒啪哒的大男孩。

YAPC::Beijing 大会是在第二天,即 17 日在雅虎中国举行。早上过去就觉得身体很虚那种,因为前一晚上为做幻灯片的事情折腾到凌晨 4 点才睡下,然后早上 6 点多又起来了。TNT 也陪着我不睡觉,真是太对不起他了。

值\n得一提的是,大会开始之前,我终于见到了孙磊(laye)。他专门为这次大会从上海赶过来。这一回算是我们的第一次见面,但我们在网上交流已经很久了。想\n来也有趣,我和他最终是在一个叫做 xptop 的 C/C++\n论坛里认识的,后来一问才晓得,原来大家都是一个学校一个专业的!哈哈!另外,在会场上我还有幸遇见了 #perl6 频道里的 dolmans\n并和他聊了不少。此前我一直以为他是德国人,呵呵,失误啊!dolmans 一直给我的是一种世外高人的感觉哦。

大会开始以后,第一\n个 talk 就是我的\"Contribute to Pugs\"。当然又是一场激情四射的讲演了啊,呵呵。也算是代表唐凤和 Pugs\n团队吧。听众的反响相当热烈。末后,fkiori(陈正伟),TNT,和传说中的小林当场向我提了几个很不错的问题。由于对 S12\n的无知,fkiori 问的 Perl 6 中 protected 类型成员的声明记法我没有答上。TNT 问的有关 Pugs 与 parrot\n等其他 Perl 6 相关项目的关系问题我早有准备。小林问的有关如何处理我的学业与 Pugs\n团队开发之前的关系,回答起来也是颇有意趣的。演讲结束后,又有不少与会者私下问了我许多有关 Perl 6 和 Pugs\n的问题,其中不乏\"Perl 6 何时问世\"这样的经典问题。我听到了有关 Perl 6 本身的唯一不满是,新的面向对象的记法\"太像 Java\n了\"。这是真正的 Perl 5 程序员的反应,哈哈!

下午又听了 Joe, fkiori,\n小林, hoowa 等高手的演讲。Joe 的演讲中提及的不少 DBI 相关的有趣模块我还是第一回听说,感觉很有收获。fkiori 的 P3P\n也很有新意。小林提及的通用 Web 后台系统让我有一种想介绍 Jifty 的冲动,呵呵。hoowa 的演讲是最有个性的,现场演示用它的客户端程序拨通观众的手机--一个字:帅!他的\nAsterisk 模块看上去妙趣横生哦。 临近结束时我又作了一个有关 UML::Class::Simple 模块的闪电演讲。\n

最后大家一起合了影,开心哦,呵呵。我记得还见到了一个女性程序员,她说他们部门从主管到普通员工,很多都是女孩子--实在是太强了!

晚上又和 PerlChina 的不少朋友在百子湾路上的一家小饭馆一起用了晚餐。认识了好几个新朋友。饭后回到如家,又听了三明治介绍他的精彩历史,听他讲\"长发怪物\"和\"赤脚怪物\"的离奇故事……

18 日起来,一个人逛了北京永安里、天安门和王府井等地方。觉得最有趣的还是永安里 LG 大厦附近的居民小区。在那里见着了北京的鸽子和猫咪哦。

19 日我就坐火车回来了。

感觉像记流水帐哦……没办法,想记录的事情太多,而我的汉语又有所退步……

P.S. 如果下一届 Audrey 能来,那可就更帅了哦,呵呵。\"\"\"\"
','agentzh','2007-06-23 21:33:00',0),(46,'YAPC::Beijing 大会上拍的相片','
YAPC::Beijing 2007 大会上拍的相片集:

http://yapc.org.cn/album-bin/index.pl

穿深绿色上衣正在做演讲的就是我啦,呵呵。

这是我和小林的合照:

http://yapc.org.cn/album-bin/index.pl?mode=view&photo=/dsc_0336.nef_01.jpg

可惜我那天胡子没刮,头发也没理……狼狈哦,呵呵

还有 Yahoo China 的朋友们以及 nomas:

http://www.yapc.org.cn/album-bin/index.pl?mode=view&photo=/dsc_0292.nef_01.jpg

\"\"\"\"
','agentzh','2007-06-27 13:13:00',0),(47,'Photo Album: YAPC::Beijing 2007','

YAPC::Beijing 2007

我和牛人们

小林和我

我的UML::Class::Simple演讲

和 laye, dolmans 等等大家在一起

Yahoo的朋友们和nomas

“情圣”在主持

\"\"\"\"
','agentzh','2007-06-27 14:08:00',0),(48,'Ubuntu下的音频转换','
今天晚上找到了Ubuntu下的一款极好的音频转换工具,叫做 Perl Audio Converter:

http://viiron.googlepages.com/screenshots

我已经成功地将 .ram 文件转换为了 .mp3 格式。它支持的格式实在太多,甚至可以将 .rm 视频文件转为 .mp3 音频。\n

不过安装不是那么直截了当。

wget http://linuxappfinder.com/debian/pool/main/p/pacpl/pacpl_3.3.1-1_i386.deb\n
sudo dpkg -i pacpl_3.3.1-1_i386.deb
\nsudo apt-get install libaudio-flac-header-perl
sudo apt-get -f install
\nsudo cpan MP4::Info Audio::APETags Audio::WMA MP3::Info

安装完毕之后,转换 .ram 至 .mp3 则通过下面这个命令:

pacpl --convertto mp3 *.ram\n

其他格式与之类似 ;)
\n\"\"\"\"
','agentzh','2007-06-29 16:08:00',0),(49,'终于拿到了学位和毕业证','
经过四年的努力,最近终于拿到了计算机专业的学士学位和毕业证书……不容易啊,特别是对于像我这样的“差生”来说,呵呵。大家鼓励我一下吧!;)

这样一来,我的个人简历里就不用再写“expected to graduate in June, 2007”这样的话了,Yay!
\"\"\"\"
','agentzh','2007-06-30 14:00:00',0),(50,'Setting up Selenium on Ubuntu feisty fawn 7.04','
OKay, I\'ve spent huge hours tonight and finally got Selenium servers and clients running on my Ubuntu Feisty Fawn 7.04 + Firefox 2.0.0.4. Here are the steps involved:

* First of all, download the latest Selenium Remote Control package snapshot from:\n

    http://maven.openqa.org/org/openqa/selenium/selenium-remote-control/0.9.2-SNAPSHOT/

For example, \nselenium-remote-control-0.9.2-20070707.164746-46-dist.zip works for me :)

Note that there is a serious bug in the current latest version 0.9.0: firefox hangs after server issues \"Preparing Firefox profile...\". See details at:\n

   http://jira.openqa.org/browse/SRC-225?decorator=printable

Don\'t download the .zip from the following location,

  \nhttp://www.openqa.org/selenium-rc/download.action

unless 0.9.2 is released ;)

The downloaded .zip file contans both the server and the client-side libraries in various languages.

* And then we need to set up the Sun Java environment if we haven\'t. Note that ubuntu uses gij (GNU Java bytecode interpreter) by default and this \"java\" doesn\'t work with the selenium server. (We\'ll get a lot of Java exceptions if we use it.)\n

  $ sudo apt-get install sun-java5-jdk

Then we can update the default \"java\" our shell sees:

\n  $ sudo update-alternatives --config java

Make sure the default one is something like

  /usr/lib/jvm/java-\n1.5.0-sun/jre/bin/java

rather than something like

  /usr/bin/gij-wrapper-4.1

* Selenum server needs firefox-bin, so let\'s visible in our PATH:\n

  $ sudo ln -s /usr/lib/firefox/firefox-bin /usr/bin/

Also, firefox-bin needs some shared library, and we need to tell the system where those libraries are by adding the following line to /etc/ld.so.conf\n

   /usr/lib/firefox

Then running the following command to update the .conf setting:

\n   $ ldconfig

If we don\'t update ld\'s configuration, we will probably get the following error while running firefox-bin:

    /usr/lib/firefox/firefox-bin: error while loading shared libraries: \nlibmozjs.so: cannot open shared object file: No such file or directory

* Then we can unzip the Selenium Remote Control\'s .zip package, cd into the selenium-remote-control-0.9.2-SNAPSHOT/selenium-server-0.9.2-SNAPSHOT\n directory and start the server like this:

    java -jar selenium-server.jar -port 4444

where 4444 is the port the selenium proxy server will listen to.\n

For other options for this Java program, look at

   http://www.openqa.org/selenium-rc/options.html

* Now it\'s time to play with the client-side stuff. Let\'s install the excellent Selenium IDE addon to our Firefox from here:\n

   http://www.openqa.org/selenium-ide/

Go to Firefox\'s \"Tools\" menu, and then click the \"Selenium IDE\" item to start it.

It\'s able to record our actions in Firefox and generate source code in various languages, including Perl! Just go to the [Optons] -> [Clipboard Format] in the Selenium IDE window.\n

After record a series of actions, you can copy the commands generated into a text editor, it will automatically converted to the right language format before entering the clipboard. :)

If we select Perl, then the generated code might look like this:\n

    $sel->open_ok(\"/\");
    $sel->type_ok(\"q\", \"\\\"Agent Zhang\\\"\");\n
    $sel->click_ok(\"btnG\");
\n    $sel->wait_for_page_to_load_ok(\"30000\");
    $sel->click_ok(\"link=Next\");
\n    $sel->wait_for_page_to_load_ok(\"30000\");

* Then it\'s time to install the Test::WWW::Selenium module from CPAN to actually run this code:\n

    $ sudo cpan Test::WWW::Selenium

* After installing this module, we can add the following header to that piece of Perl code generated by Selenium IDE:\n

   use Test::More \'no_plan\';
   use Test::WWW::Selenium;\n
   my $sel = Test::WWW::Selenium->new(
                host => \"localhost\",

\n                port => 4444,
                browser => \"*firefox\",\n
                rowser_url => \"http://www.google.com\",
\n                default_names => 1,
   );

And then run this .t file:\n

    $ perl google.t
    ok 1 - open, /
\n    ok 2 - type, q, \"Agent Zhang\"
    ok 3 - click, btnG\n
    ok 4 - wait_for_page_to_load, 30000
\n    ok 5 - click, link=Next
    ok 6 - wait_for_page_to_load, 30000
\n    1..6

Yes, it\'s a bit horrible but it works :)

\n\"\"\"\"
','agentzh','2007-07-10 17:41:00',1),(51,'\"No More Passwords (with SSH)\"','
Entering a password everytime logging into a remote machine via SSH is very annoying, especially when using unison to sync stuff using SSH. Here is how to save us:

    \nhttp://www.cvrti.utah.edu/~dustman/no-more-pw-ssh/

Note that the dsa thingy is unnecessary for me :) And don\'t forget changing the permisson of the .ssh/ directory on the server side to 700, or you\'ll still be prompted with password queries.\n

And this one may be helpful too:

    http://www.linuxproblem.org/art_9.html

Enjoy!
\n\"\"\"\"
','agentzh','2007-07-11 03:41:00',0),(52,'Re: [jifty-devel] Idea for Template::Declare::XML','
Hi, I\'ve coded up a small script to use Template::Declare to generate some XML code (it\'s actually XUL, to be more specific):

    http://perlcabal.org/agent/xul/buttons.pl.txt\n

The output file is

    http://perlcabal.org/agent/xul/buttons.xul

The script used to run buttons.pl.txt is

    \nhttp://perlcabal.org/agent/xul/xulgen.pl.txt

It\'s a lot of fun. Essentially, I extended the tag set in Template::Declare::Tag by the following lines of code:

\n    Template::Declare::Tags::install_tag($_) for qw(
        window textbox hbox vbox radio radiogroup\n
        groupbox spacer
\n    );

The tag list given above is by no means exhaustive. It\'s just an experiment. :)

Here\'s another trivial example:

    http://perlcabal.org/agent/xul/findfile.xul\n
    <=
    http://perlcabal.org/agent/xul/findfile.pl.txt

Enjoy!
agentz\n\"\"\"\"
','agentzh','2007-07-19 14:05:00',0),(53,'Template::Declare now (partiallly) supports XUL and custom XML dialects','
I\'ve refactored Template::Declare::Tags and introduced the long over-due TagSet feature to TD.

HTML tag list and other related info have been moved to HTML::TagSet, and XUL::TagSet is also added. We can now control which tag set to use by the following lines of code:

package MyApp::Templates;
use Template::Declare::Tags qw/ XUL::TagSet /;
use base \'Template::Declare\';

     template foo => sub {
         window { attr { ... } groupbox { .... } }
     };

And it\'s also possible to specify multiple tag sets:

use Template::Declare::Tags qw/ XUL::TagSet HTML::TagSet /;

(This example is not very realistic BTW.)

By default, Template::Declare::Tags uses HTML::TagSet so that existing code won\'t break.

The user can define their own tag set classes as long as these classes subclass Template::Declare::TagSet and implement the corresponding methods (i.e. get_tag_list, get_alternate_spelling, and can_combine_empty_tags).

See the POD in these classes for more info :)

Now I\'m considering adding the XML namespace support to TD. I\'m proposing the following design:

     package html;
     use Template::Declare::Tags \'HTML::Tags\' => { tag_prefix => \'html:\' };

     package MyXulApp::Templates;
     use Template::Declare::Tags \'XUL::Tags\';
     template foo => sub {
         groupbox {
             html::p { \'hello, XML!\' }
             html::table {}
         }
     };

And show(\'foo\') will give:

  <groupbox>
    <html:p>hello, XML!</html:p>
    <html:table></html:table>
  </groupbox>

Thoughts? Comments?
\"\"\"\"
','agentzh','2007-08-09 08:00:00',0),(54,'New life in Beijing','
I\'m currently working for Yahoo! China\'s EEEE department. Like Zorpia, lots of smart Perl guys are around here ;)

$job is fun and I\'m allowed to spend a lot of my $working time on my favorite open source projects such as Jifty and Pugs :) That\'s exactly\nwhat I want.

I\'ve been mostly hacking on the XUL/XML support for Template::Declare over the last few weeks. And I now have a plan to develop a HTML/XUL/XML DOM builder for SpiderMonkey.pm. After that, cool things like WWW::Mechanize::AJAX or even a full-featured browser in pure Perl will also be possible. Hmm, I think it\'s wise to talk to \nSpiderMonkey.pm\'s author first ;)

Another project I most want to work on is a XUL-based Perl 6 regex tracer/debugger based on fglock++\'s Pugs::Compiler::Rule. The basic facilities on the PCR side are almost complete, such as positional info in the regex ASTs and hooks in the emitted Perl source...\n

With Jesse\'s Template::Declare and jquery.js under the belt, XUL hacking can be really enjoyable ;)

Happy hacking!

\"\"\"\"
','agentzh','2007-09-02 08:07:00',2),(55,'A plan for XUL::App','
I\'ve been mostly working on a Firefox extension last week and I\'ve already got a first (naive) implementation. My $boss got very happy when I offered him a link to my .xpi file.

The buzzword of this extension is that there\'s NO xul in the source tree. Template::Declare generates all the ugly XML/XUL/RDF stuff for me, including \ninstall.rdf. Hmm, maybe this will be the first Firefox extension in the world produced by Jifty\'s Template::Declare module. Hooray!

Also, jquery.js is a godsend for the Javascript part, it works seamlessly between XUL and HTML DOMs.\n

This extension will soon be open sourced and the resulting .xpi file will also been uploaded to addons.mozilla.org, according to my $boss :)

In the next week, I\'ll work on the architecture refactoring for this project. In particular, I\'d love to invent a new application framework for XUL development. It\'ll be called XUL::App. I\'m going to steal a lot of good ideas from Jifty. Here\'s some random thoughts:\n

   $ xulapp app --name MyExtension  # create a directory tree structure rooted at ./MyExtension/
   Creating new application MyExtension
   Creating directory lib
   Creating directory lib/MyExtension
\n   Writing file lib/MyExtension/App.pm
   Creating directory lib/
   Creating directory bin
   Creating directory doc
   Creating directory t
   Creating directory jslib

    $ cd MyExtension
    $ xulapp view --name TreeView --out \ntreeview.xul
    Writing file lib/MyExtension/View/TreeView.pm
    Updating file lib/MyExtension/App.pm

    $ xulapp debug treeview.xul  # will launch a Firefox window loading treeview.xul
    $ xulapp bundle  # will generate \ninstall.rdf, chrome.manifest, and then package related stuff into a .xpi file

And lib/MyExtension/Application.pm will probably look like this (Thanks to Audrey\'s Object::Declare!):

    package MyExtension::Application;\n
    use XUL::App::Schema {
        xulfule \'foo.xul\' =>
            generated from {
                 \'MyExtension::View::Foo\' => { template => \'foo\', arguments => [...] },\n
            },
            includes [qw( foo.js foo.cs )];

        xulfile \'browser-overlay.xul\' =>
             generated from \'MyExtension::View::Overlay\',
             overlays \'chrome://browser/content/browser.xul\';\n

        jsfile \'foo.js\' =>
            requires [qw( bar.js dom.js jquery.js )];

        xpifile \'foo.xpi\' =>
            id is \'myextension@foo.bar.org\n\',
            name is \'MyExtension\',
            version is \'0.0.1\',
            targets {
                Firefox => [\'1.5\' => \'3.0a5\'],
                Mozilla => [\'\n1.0\' => \'1.8\'],
            },
            creator is \'Agent Zhang\',
            developers are [qw( John Mary ... )],
            updateURL is \'\nhttp://foo.bar.org/update\';
    };

Currently XUL::App is focused on FF extension development, so there will be no server-side logic in the near future.

Modern Jifty apps use Template::Declare for their \"view\", and so will XUL::App :) Jifty also has cool concepts like \"model\" and \"actions\". Not sure how \"actions\" fit in the XUL world, but I can see XUL\'s RDF and its wrappers are good parallels to \"models\". Maybe XUL::App\'s model classes will simply emit JS and RDFS code for certain RDF schemes defined there.\n

Unlike Jifty, XUL::App will look more like a compiler. We\'ll use 100% Perl (as well as a lot of JS for sure) during the development phase, but 0% Perl in the final .xpi package for deployment. So there won\'t be any portability issues nor any big runtime that slows things down. Yay!\n

For the test suite part, I\'d really love to see a DOM lib for SpiderMonkey or even Test::WWW::Mechanize::AJAX on CPAN soon. Testing XUL/AJAX in bare command line w/o launching any real web browser will simply rock ;)\n

Yeah, I\'m writing down crazy plans...putter++ once said on #perl6 that such things are very bad for expectation management...but anyway...

Suggestions and comments will be greatly appreciated. Thank you :)\n

\n\"\"\"\"
','agentzh','2007-09-08 13:36:00',0),(56,'The SearchAll Firefox Plugin and XUL::App framework','
My first $job project is now opensourced. It\'s a Firefox extension named SearchAll.

SearchAll is a simple side-by-side search engine comparing tool which allows you to search at most 3 different search engines simultaneously and benchmark their performance in the status bar.\n

With this extension, you can compare 2 search engines or 3 search engines at a time. There\'s a long list of default search engines that you can choose from (including search.cpan.org!). And you can also enter search engines\' URLs which don\'t appear in the default list\nyourself.

Currently only the sites\' raw HTML pages are shown to the user. We\'ll add more comprehensive and more intuitive views and graphics for the search results in the near future. Please stay tuned!
\n
This project was initiated and has been regulated by the Yahoo! China ( http://cn.yahoo.com ) company and opensourced under the MIT license.

One of our buzzword (for extension developers) is that there\'s 0 line of XUL/RDF/XML in our project\'s source tree. The GUI stuff is totally scripted in Perl. Thanks to Jesse Vincent\'s Template::Declare module on CPAN.

You can always get the latest source code of this project from the following SVN repository:

   \nhttp://svn.openfoundry.org/searchall/

If you like to help, please let us know. We\'re very willing to deliver the commit bit like the Pugs team ;)

The XPI file that can be installed directly into Firefox can also be found here:\n

   http://svn.openfoundry.org/searchall/trunk/searchall.xpi

There\'s a XUL application framework named XUL::App sitting in the same repos and SearchAll is already using it. I\'d expect to move XUL::App to a separate repos and rename it to a cooler name (maybe Xifty or Xufty?).\n

Sorry for the lack of documentation. Please see README for some general ideas :)

I\'ve already submitted this extension to addons.mozilla.org and waiting for the editor\'s approval.\n

Enjoy!
\"\"\"\"
','agentzh','2007-09-18 10:10:00',0),(57,'Photo Album: SearchAll\'s screenshots','

SearchAll\'s screenshots

Startup view

Search results

Comparing only 2 sites

The Formatted View

\"\"\"\"
','agentzh','2007-09-18 10:57:00',0),(58,'SearchAll 插件的 0.0.6 版发布 :)','
大家好!

我的 Firefox 插件的 0.0.6 版发布。

主要的改进如下:

* 在原先的 Raw View 的基础上增加了 Formatted View,即对当前比较的三家网站返回的搜索结果进行解析,以统一的格式显示出来,以方便比对,同时界面布局有了较大的改善
* 修复了 checkbox 需要点击多次才响应的 bug

您总是可以从下面这个 URL 安装最新版本的 SearchAll 插件:\n

    http://svn.openfoundry.org/searchall/trunk/searchall.xpi

非常感谢各位兄弟姐妹先前对 0.0.2 所提出的那些宝贵意见和建议 :) 欢迎大家继续批评指正,以便不断地完善这个产品 :)

谢谢!
\n
P.S. 下一阶段的 TODO:

* 每次退出时保存用户对界面的主要修改,下次启动时自动予以恢复。比如默认打开的是 Raw View 还是 Formatted View, 默认比较的三家搜索引擎的 URL,checkboxes 的勾选状态,等等。
* 增加 \"Next page\" 和 \"Previous Page\" 按钮,以便于三家同时转到下一页或上一页。\n
* 增加第三个视图,即 Merged View,以一定规则将三家的搜索结果混合为单个结果列表。
\"\"\"\"
','agentzh','2007-09-20 09:19:00',0),(59,'Fwd: Mozilla Add-ons: SearchAll Nomination','
Yay! My SearchAll addon has been made public on addons.mozilla.org !!!

I\'ve put the mail from Mozilla Add-ons below. I don\'t quite understand what he/she meant by \"A shame it works only with censored search engines though.\" Actually SearchAll has been working with (almost) arbitrary search engines for long ;)\n

---------- Forwarded message ----------
From: Mozilla Add-ons <nobody@mozilla.org>
Date: Oct 2, 2007 11:56 PM\n
Subject: Mozilla Add-ons: SearchAll Nomination

Congratulations! Your nominated add-on, SearchAll, has been reviewed by a Mozilla Add-ons editor who approved your add-on to be public.

Your most recent version (\n0.1.4) has also been made public.

You can view your public add-on now at:

http://addons.mozilla.org/addon/5712

Review Information:
Reviewer: Oliver Saier\n
Comments: Pushing to public per my tests and the good reviews. A shame it works only with censored search engines though. Thanks.

If you have questions about this review, please e-mail \namo-editors@mozilla.org or join #addons on irc.mozilla.org.

Mozilla Add-ons
http://addons.mozilla.org

\n\"\"\"\"
','agentzh','2007-10-03 08:43:00',0),(60,'SearchAll 0.1.8 released on AMO!','
On behalf of the Yahoo! China EEEE hacking team, I\'m pleased to announce the 0.1.8 release of SearchAll on addons.mozilla.org\n (AMO), with the highlights of *many* more default search engines (including Taobao, eBay, Amozon, Answers.com, and image search engines!) and much improved performance, reliability, and user experience.\n

If you already have an older version of  SearchAll installed in your Firefox, the new version should shortly arrive at your side automatically. If not, please check the updates explicitly in your Firefox\'s extension manager (Tools menu => Addons menu-item).\n

If you have not yet got SearchAll before, you can install it directly from SearchAll\'s en-US homepage on AMO:

   \nhttps://addons.mozilla.org/en-US/firefox/addon/5712

Or its zh-CN homepage here if you prefer:

   \nhttps://addons.mozilla.org/zh-TW/firefox/addon/5712

I really appreciate the tireless project coordination, bug reports, and feature requests from my $boss, laser++ (何伟平). And I\'m also grateful to our professional UI engineer, yedan++ (叶丹). Personally I like her logo for SearchAll so much ;) Special thanks go to our PE, jianingy++ (杨家宁), for his all-encompassing technical support. Without his support, technically speaking, \n0.1.8 won\'t be released so fast. At last but not least, I appreciate all the help from other 4e colleagues that I haven\'t mentioned here, as well as the cool boy, yuanyin++ (何远银), from the content team . Thank you all!\n

Here\'s the detailed change log for version 0.1.8 (compared to the
previous 0.1.5 release):

       * Added the folowing new US search engines to the default URI list:
          \nwww.amazon.com
          www.ask.com
          \naddons.mozilla.org/search
       * Added the following new Chinese search engines to the default URI list:
          \ntaobao.com
          so.163.com
          \nwww.sogou.com
       * Added the following new image search engines to the default URI list:
          \nimage.cn.yahoo.com
          images.google.com
          \nimages.google.cn
          image.baidu.com
       * Fixed \nyisou.com so that SearchAll can work with it in \'page mode\'.
       * Fixed the timer for next/prev page button actions.
       * Fixed the hostname hash bug. Now 2 identical SE\'s (such as 2 \nyahoo.cn) can work at the same time.
       * Now we use \'<<Prev\' and \'Next>>\' labels instead of arrow icons in the navigation buttons.
       * Set clickSelectsAll for the toolbar\'s textbox (just like the Google toolbar :)).\n
       * Fixed a bug for Mac Firefox. Unlike linux and win32, Mac centers the tabs which breaks the UI. thanks cnhackTNT++ for reporting this.
       * Refreshing the .xul page in \'page mode\' now (mostly) works.\n
       * Fixed a bug that baidu.com will show loading animation forever when there\'s no results at all.
       * Hides \'please enter your queries above\' as early as possilbe in \'page mode\'.\n
       * Removed several setTimeout calls in the JS code so as to make things a bit faster.
       * Cached the html so that next/prev page switching is now much more smoothly.
       * Use WPL.STATE_IS_NETWORK\n instead of STATE_IS_WINDOW to eliminate bogus progressing actions.
       * Improved and optimzied the pattern mining algorithm and implementation.
       * Made the auto-form-submitting code much smarter.

\nEnjoy!

-agentzh

P.S. As a side note, 0.1.9 will get its way into AMO pretty soon as well ;) Stay tuned!\n

\"\"\"\"
','agentzh','2007-10-13 05:11:00',0),(61,'Jifty::I18N meets XUL development','
I\'ve just ported Jifty::I18N and something in Jifty::Script::Po over to my XUL application framework, XUL::App. And my Perl-based Firefox extension, SearchAll ( \nhttps://addons.mozilla.org/en-US/firefox/addon/5712 ), is already using it.

Because XUL::App is also using Template::Delcare as its templating language, the port is rather straightforward. For example, one of SearchAll\'s view looks like this:\n

   http://svn.openfoundry.org/searchall/trunk/lib/SearchAll/View/Main.pm

Note that I\'m also using _(\"...\") calls in the view ;)\n

Extracting these string literals is a single command in XUL::App (just like Jifty):

    bin/xulapp po --lang us_en

It will scan all the .pm files and generate po/us_en.po for you.

For example, here is the Po file directory for my SearchAll extension:\n

    http://svn.openfoundry.org/searchall/trunk/po/

Unlike Jifty, XUL::App tries to behave more like a compiler than a runtime. So these po files won\'t appear in the final XPI bundle. XUL::App will carefully convert these .po files to the corresponding DTD entities required by XUL\'s own L10N mechanism. So still, there\'s *0* Perl in the \"runtime\".\n

Testing I10N within Firefox is straightforward as well:

    bin/xulapp overlay --profile dev --lang zh_cn

Or just testing a particular .xul file in Firefox using a specified profile named \"dev\":\n

    bin/xulapp searchall.xul --profile dev --lang zh_cn

See http://svn.openfoundry.org/searchall/trunk/README for more \"xulapp\" usage in the SearchAll project if you\'re interested :)\n

In XUL::App, I\'ve been trying very hard to follow Jifty\'s best practices. Jifty is so great that every fundamental component has been keeping me very excited ;)

Once XUL::App gets matured enough, I\'ll push it onto CPAN. If you like to help, please let me know ;)\n

Thanks!\n\"\"\"\"
','agentzh','2007-10-18 06:42:00',0),(62,'A graphical tracer for Perl 6 regexes based on PCR','
Tracing parse failures by hand while developing a compiler can be really a nightmare, since the real problem can appear everywhere -- the grammar definition, the input string being matched, or even the regex engine itself. \n

So I\'ve implemented a graphical tracer for Perl 6 regexes atop PCR (Pugs::Compiler::Rule). You can find some small online demos here:
\n

\n

To generate the HTML pages (say, the first demo) yourself, simply check out the Pugs repository , ``cd\'\' into perl5/Pugs-Compiler-Rule, and enter the following commands:

  $ perl util/compile_p6grammar.pl -D examples/digits.grammar > Digits.pm
$ echo \'7c3d54\' > digits.input
$ perl -Ilib -MDigits -e \'print Digits->count(<>)->(), \"\\n\"\' \\
digits.input > trace.out\n
$ perl util/gen-tracer-view.pl --outdir tmp/digits \\
examples/digits.grammar digits.input < trace.out
$ firefox tmp/digits/index.html
\n

The tracer interface still needs love and at the moment I\'m adding cooler features like ``random jump\'\', ``stepping in a specified pace\'\', and ``stepping back\'\'. If you like to help, just join #perl6 and get a Pugs commit bit ;) \n

I think this tool should be very useful for both regex engine developers and compiler writers, especially when parsing fails in an unexpected way. And it can also be beneficial to Perl 6 beginners who want to learn the shiny new regex syntax and complicated matching behaviors by just ``stepping through\'\' the real parsing process. moritz++ said on #perl6 that he would build a CGI script to make my demos above ``alive\'\' when he had the tuits; let\'s just wait and see ;) \n

It should be warned that the regex syntax supported by the current PCR implementation is already a little out-of-date regarding the lastest Synopsis 5 . (Thanks TimToady++ for tweaking the regex syntax during the meantime ;)) I\'ll try to port KindaPerl6 \'s perl5rx backend over to PCR later. \n

Hey, it\'ll be nicer to have KindaPerl6, PGE , or even the Perl 5 regex engine to work with my tracer as well :) \n

Stay tuned! \n

-agentzh\n

P.S. This entry was originally posted as http://pugs.blogs.com/pugs/2007/10/a-graphical-tra.html \"\"\"\"

','agentzh','2007-10-24 11:45:00',2),(63,'Yak shaving','

Mostly been yak-shaving over the past few weeks. No significant visible progress yet. Refactoring the JavaScript (JS) part of my SearchAll extension using the best practices of JS seen in ``professional JS code\'\' from others. \n

Got 2 releases of PCR (Pugs::Compiler::Rule) out of door to CPAN. Just want to keep my feet wet in the Pugs team. Thanks Matthew ++ for reporting the test failures of PCR 0.27 on MS Win32. They were essentially coursed by cmd.exe\'s shell syntax incompatibility. Fixed in the 0.28 release. I\'m running VirtualBox with WinXP to test it. \n

Thinking a lot about web site testing and Firefox addon testing issues, also pondering the future of my XUL::App framework -- hey, it\'s exciting! I\'d like to add support for _(\"blah blah\") in plain .js code. Like what clkao++ is doing in Jifty: \n

http://lists.bestpractical.com/pipermail/jifty-devel/2007-October/001773.html \n

But I\'ll definitely reuse XUL\'s own .properties file and <stringbundle> mechanism to emulate it directly instead of using the costy AJAX approach taken by clkao. \n

laser++\'s ``postgres extension\'\' talk given yesterday is quite interesting. Will take a closer look at postgres and hack in something analogous to Perl\'s Inline::C. It\'s already in my ``learning queue\'\', which is already quite long though. \n

Also coordinating two projects mainly contributed by my former schoolmates, sal++ and xunxin++ , i.e., the ajaxperl and jslint projects. \n

sal\'s work on the DOM test suite helpfully indicates the status of the DOM support of various CPAN modules like HTML::DOM, XML::DOM, and XML::LibXML::DOM. Ajaxperl will eventually rely on these modules anyway. \n

I\'ve also taken a peek at the HtmlUnit project which essentially does what ajaxperl aims to do, except it\'s the darned Java. \n

Regarding the other project, jslint, it can be immensely helpful in applications like XUL::App. You know, I\'ve got tired of starting the slow Firefox up just to find a silly typo in my JS code. For such situations, jslint will come to rescue when it\'s mature enough. \n

As xunxin reported, jsshell can already check the syntax of .js files with a command-line option. But unfortunately jsshell does not respect the inlined JS snippets in .xul and .html files. Spidermonkey doesn\'t come with a DOM lib anyway. So I\'d love to see a new CPAN module named JavaScript::Lint born out of the jslint project. \n

Hopefully xunxin++ will make more progress in the next few weeks or so. Sadly he\'s got a Java $day_job ...Sigh. \n

Regarding my talk in the next ``hacking-hour\'\' meeting suggested by laser++ last afternoon, I\'m currently having several interesting topics in mind: ``The best practices in SearchAll\'\', ``XUL::App : the Jifty way of doing XUL\'\', ``Reusing Perl as an DSL\'\' and ``Abusing jquery for AJAX\'\'. I still tend to use XUL for my slides, but I\'m not 100% happy with ingy++\'s Sporx slide-making framework. Will probably tweak it to work the way I like. Yeah, another ``yak-shaving\'\' like job and it must be fun as well ;) \n


\"\"\"\"

','agentzh','2007-11-03 08:26:00',0),(64,'SearchAll 0.3.2 发布!','

经过 Yahoo! China EEEE hacking 小组近一个月的努力, SearchAll 0.3.2 版终于发布到了 AMO 官方网站

\nhttps://addons.mozilla.org/zh-TW/firefox/addon/5712

如果您已经安装了 SearchAll 的话,您的 Firefox 在启动时会自动检查更新,并按用户选择进行升级。

和上一个 AMO 公开发布版本 0.1.8 相比,SearchAll 积累了许多重大改进。其中的亮点包括:

  • 增加了对结果页中的链接进行本地测试的功能。SearchAll 现在会自动在``规格化视图\'\'中用可爱的小图标标记出坏链,好链,和慢链。由于使用 Ajax HEAD 请求,所以测试的速度很快。我们 team 的 \n杨家宁 当初做 \"易搜\" 的时候就想到实现这样的本地链接测试的功能,但受到 AJAX 跨域请求的限制而未能实现。谢谢杨家宁提的这个 feature!

  • 增加了 \n\"划搜\"功能 。用户可以在任意的网页中选定文本,然后右击,在弹出的快捷菜单中点击\"我搜去\"(或者SearchAll),进行搜索。感谢李晓栓的提议!

  • 增\n加了对简体中文(zh-CN),繁体中文(zh-TW), 法语(fr),和西班牙语(es-ES) 的国际化支持。如果用户使用的是简体中文版的\nFirefox,那么她看到的 SearchAll 界面也将是简体中文版的。其他语言支持依此类推 :) 感谢西班牙的 Gregorio\nVillarrubia 的西班牙文翻译。对于非中文用户而言,第一次使用 SearchAll 时默认的三家搜索引擎是 yahoo.com , google.com , 和 ask.com . 中文用户默认的原三家网站保持不变。\n

  • 为大部分默认列表中的搜索引擎实现了 OpenSearch 快捷方式 ,从而使第一次查询以及切换搜索引擎时的用时减少了至少 50%. 感谢服务于 IronPort 公司\ncnhackTNT 的提议!

  • 修复了多处内存泄漏问题。使用 SearchAll 的时候,Firefox 不会再占用越来越多的内存。界面响应也更迅速。感谢 Mozilla 官方网站的编辑 Archaeopteryx\n 的报告。

  • SearchAll 工具条上的搜索框现在支持快捷菜单方式下的\"复制\",\"剪切\",和\"粘贴\"操作。感谢尚尔迪的报告和修复。

  • 添加了下列新的默认搜索引擎:

我们仍然在考虑如何在 SearchAll 中展现 Omni Search 的问题。既要保持 SearchAll 在结果展示上的公平公正性,又要表现 Omni Search 丰富的内容,并不是一件容易的事情 ;) 欢迎大家多提宝贵建议 :)

我最近在看有关 \nAdobe Flex 方面的文档,一个基于 Flash 的 SearchAll 似乎更酷一些,因为它将能运行在 IE 和 Opera 这样的浏览器中,而不仅仅是 Firefox. 当然这仅仅是一个很模糊的想法,不知是否可行。有兴趣的朋友可以与我们联系 ;)

SearchAll 是一个基于 MIT 协议的开源项目。源码仓库位于台湾的 OpenFoundry 服务器\n 上:http://svn.openfoundry.org/searchall/trunk/. 如果您乐意参与到项目开发中来,请立即与我们联系;我们很乐意像 Pugs 团队那样递送 Subversion 提交权限。

感谢所有一直以来关注和使用 SearchAll 的朋友们;我们一如既往地欢迎各种新功能提议,bug 报告,和评论。\n

谢谢!

章亦春 (agentzh)

附:根据陈敬亮的报告,来自 FoxplusAlexa Sparky 扩展 会严重影响 SearchAll tab 的切换速度,因此对于安装了该版本的 Alexa Sparky 扩展的用户,请在使用 SearchAll 的时候暂时禁用 Alexa Sparky.\n\n\"\"\"\"

','agentzh','2007-11-10 10:21:00',0),(65,'写了一篇东西到\"雅虎搜索日志\"','
写了一篇东西到我们 Yahoo 自己的\"雅虎搜索日志\"网站上:

     http://ysearchblog.cn/2007/11/searchall.html

感谢咱们 content team 的何远银同学提供的初稿。毕竟发起一些东西不是我的长项,而大刀阔斧地修改现成的东西却是,呵呵。\n

另外还必须特别感谢一下我的编辑石杏岚小姐不厌其烦地反复修改这篇东西。在修改过 N 处之后,她终于说自己快崩溃了,呵呵。

这里顺便 spam 一下,SearchAll 的下一个版本将提供一个全新的视图,Mapping View:

   http://agentzh.org/misc/mapview.png

欢迎大家试用 Subversion 里的版本:

    \nhttp://svn.openfoundry.org/searchall/trunk/searchall.xpi

Enjoy!

-agentzh

\n
\"\"\"\"
','agentzh','2007-11-27 12:29:00',1),(66,'The slides for my XUL::App talk','
XUL::App is a nifty Firefox extension development framework based on Perl. It has a lot of parallels with Jifty. Recently I gave a talk to our Yahoo! 4e department for XUL::App and it went very well.

Here\'s the slides that I used in the talk:\n

    http://agentzh.org/misc/slides/xulapp/xulapp.xul  (a JS-enabled Firefox 2 is required to view these slides)

If you\'re having problems in displaying the slides given above, please try out the PowerPoint (PPT) version below:\n

    http://agentzh.org/misc/slides/xulapp.ppt

or the PDF version:

    http://agentzh.org/misc/slides/xulapp.pdf

You can always get the latest source of XUL::App from the following SVN repository:

    \nhttp://svn.openfoundry.org/xulapp/trunk/

There\'s very little POD docs, please read README and the slides for details.

Also, SearchAll is a real-world Firefox extension that is built upon XUL::App, which can serve as a big demo for the usage of the framework:\n

    http://svn.openfoundry.org/searchall/trunk/

Sadly XUL::App does not run on Win32 yet. I\'ve only tested it on Ubuntu Linux so far. If you have any problems or would love to help, please let me know ;)\n

Enjoy!



\n


\"\"\"\"
','agentzh','2007-11-28 03:11:00',0),(67,'Yahoo! 4e team 贺岁语录:','
\"妈呀,又是测试啊?\" -- leiyh

\"话说……你加的功能 work 了!\" -- carrie

\"这事咋办呢?让我想想。。。\" -- ting

\"每日常坐电脑前,每逢春秋必感冒。锻炼永远计划中,感冒一直在行动。\" -- jianingy

\"谁说我不乖的?我很乖的。\" -- ywayne\n

\"咦?是 exe 的。。。我来 hack 一下。。。\" -- shangerdi

\"哈哈!央视8套真好看,讲苍蝇飞行的原理 :D\" -- laser

\"锅得刚说了,铛铛铛,铛儿嘀儿嘀个儿铛!\" -- arthas

\"yay! it works! :D\" -- agentzh

\"春儿太猛了!整天写一坨一坨的没用的东西……\" -- luoyi



\"\"\"\"
','agentzh','2008-01-01 07:46:00',1),(68,'Introduction to the Yahoo! REST Base (aka OpenAPI) project','
Sorry for the lack of posting in the last few weeks. Been mostly focusing on the Yahoo! REST Base project (aka OpenAPI or OpenSearch within the company). The Chinese version of the API spec can be found here:

   \nhttp://svn.openfoundry.org/openapi/trunk/doc/spec.html

Sorry, there\'s no English version yet. But I\'ll surely work it out ;)

We\'ve stolen the spirit of Jifty\'s REST design and extend it to support a lot of cool features like models, actions, views, roles, minisql, and captchas.\n

Currently the best spec is the test suite though (and the knowledge of the Chinese language is not required ;)):

   http://svn.openfoundry.org/openapi/trunk/t/\n

Most of the test cases are declared in the Test::Base syntax, hence the readability.

We\'ve already set up a small demo app using our REST service:

   \nhttp://www.yisou.com/opi/post.html

Feel free to mud around there ;)

It\'s worth mentioning that the post board app itself is totally static; just a few .js files, 1 .html file, 1 .css file, and 1 image file.\n

It makes heavy use of cross-domain AJAX. So it also runs directly in the subversion repository:

   http://svn.openfoundry.org/openapi/trunk/demo/YisouComments/post.html\n

The source of the demo app can be found here:

    http://svn.openfoundry.org/openapi/trunk/demo/YisouComments/

The whole project but the Pg cluster backend is opensourced under GPL. You can always get the latest source from the following subversion repository:\n

    http://svn.openfoundry.org/openapi/trunk

If you like a commit bit, please let me know.

Have fun!\n\"\"\"\"
','agentzh','2008-01-09 02:36:00',0),(69,'Re: Intercepting access to a method/property','
On Jan 18, 2008 7:21 PM, AllSeeingI wrote:
> Is it possible (through an extension, XPCOM, other way) to call a
> particular JS function when a particular method or property is
> accessed by a user script (= script on a HTML page)?
>

Object.watch is the way to go for properties ;) Not sure about methods though.

> The reason I\'m asking is that I\'m trying to create an extension that
> intercepts JavaScript redirections:
>
> location.href = ...

Heh, I\'m afraid it\'s more browser-specific. So it might be OT here. But I\'d like to share some of my experiences (mostly from NSA++) in this mail.

I think the following code should work in Firefox 2 (i.e. the js 1.7 engine):

    top.watch(\"location\", function () { throw \"Permission denied.\" });
    top.location.watch(\"href\", function () { throw \"Permission denied.\" });

But unfortunately it won\'t work in Firefox 3 (i.e. the js 1.8 engine). AFAIK, Firefox has been trying much harder than IE to protect frame-busting sites.

> location.replace(...);
>

Well, I was trying very hard to defeat this one but with no luck. A good enough workaround for (static) sites is to (locally) disable JS for that particular frame loading the frame-busting page, as in:

    myBrowser.docShell.allowJavascript = false;

Basically, if you load the web page in a separate chrome window, frame-busting code will always fail. But if you\'re trying to load it in Firefox\'s own browser tab, you\'re not really \"chrome\" there.

Another trick that works is to use the onbeforeunload handler, as in:

    window.onbeforeunload = function (e) {
       e.returnValue = \"This action might be caused by a
        frame-busting site.\\nPlease click \'Cancel\' if you\'re not meant to quit me.\";
        return false;
    };

But this will pop up a confirmation dialog to the end user. There\'s no known way to bypass it without hacks ;)

There may exist much better solutions that I don\'t know.

Hope these help.

Cheers,
-agentzh


\"\"\"\"
','agentzh','2008-01-18 12:55:00',0),(70,'作秀中...','
最近又写了一篇东西到\"雅虎搜索日志\",题为\"从SearchAll看搜索引擎DNA\":

    http://ysearchblog.cn/2008/01/searchalldna.html

感谢杏岚的编辑工作 :)
\n
我的下一篇东西可能题为\"装在口袋里的网站\";我一直打算介绍一下我们的基于 OpenAPI 的纯客户端应用的开发技术。

我们的 M,yuting++,已经怪我\"染上了作秀不良风气\"了,哈哈。我看来是很难改正了,呵呵。tingting 一定要原谅我哦 ;)

-agentzh
\n\"\"\"\"
','agentzh','2008-01-30 07:59:00',3),(71,'SearchAll 0.4.15 is coming soon','
I\'ve just uploaded SearchAll 0.4.15 to the AMO site (and my AMO editor has just said he would review it in #addons). This update fixes the frame-busting problem of baidu in Firefox 3.0 and also fixes the default template selectors for YouTube and several image search engines.
\n
I\'m so glad to see the total downloads for SearchAll is now 24874. Hey, ~ 25k already! Yay!

I\'m going to include a simple BBS site powered by our OpenAPI in this Firefox extension so that my users can tell me what they feel directly ;)
\n
Stay tuned!

\n\"\"\"\"
','agentzh','2008-02-29 12:03:00',0),(72,'OpenAPI is now offically renamed to OpenResty and is now on CPAN','
The OpenAPI project mentioned in an earlier blog entry has now been renamed to OpenResty because there\'s hundreds of thousands of things that call themselves OpenAPI or so, which can be really confusing ;)

\nBut for backward-compatibility, I didn\'t change the name of the Subversion repository. So it\'s still located at http://svn.openfoundry.org/openapi/trunk.

\nI\'ve put OpenResty\nas well as its dependency modules onto CPAN to help people play with\nit. A third (fake) backend, PgMocked, was added just recently to make\nCPAN testers\' life easier.

The documentation still needs love\nvery badly. The work on the English spec for OpenResty\'s REST interface\nhas started in the form of OpenResty::Spec::REST and I need to translate most of the stuff in its Chinese version over here. And you may find the `` cheat sheet \'\' interesting too ;)\n

In the days of the Chinese New Year, I built a personal blog site using OpenResty\'s JavaScript client libary , Jemplate , and Audrey\'s Pugs blog\'s page templates:\n

http://blog.agentzh.org

It\'s\na very fast site at least here in China and the hand-written JavaScript\ncode for this site is remarkably clean (just around 300 lines):

http://blog.agentzh.org/blog.js

Due to the lack of RSS and email-to-blog support in OpenResty today, I\'ll still have to use the (slow) live.com space as my main blog site for a while.\n

Also carrie++ in our team has updated our Yisou BBS, taking advantage of OpenResty \'s Chinese captcha support:\n

http://www.yisou.com/opi/post.html

English captchas are also supported and I\'m pondering using this feature in my new blog site too.

It\'s\nworth mentioning that the deployment of these pure AJAX sites is 0\nbecause they\'re just a set of static files ;) The complexity all goes to the OpenResty server\n. The web services provided by an OpenResty server is completely\ngeneral-purpose and also scriptable by users (via the minisql\nlanguage). That\'s the beauty of this open architecture :)

Client library in Perl for OpenResty, WWW::OpenResty, is also on CPAN. It\'s just a thin wrapper around LWP::UserAgent.\nIn fact, most of the client-side operations can be done in a plain web\nbrowser\'s address bar ;) And yeah, special care should be taken while\nusing GET for writing/deleting operations for the sake of XSS attacks. Cookies\nfor sessions are now disabled by default in OpenResty (thanks\nEidolos++\'s reminding).

Both my $boss and I love to see OpenResty\'s REST design becomes a part of Jifty or let OpenResty be a funny component in Jifty\nor some other web application frameworks (as virtual models, for\nexample) in the future. And Eidolos++ on #jifty has already shown great\ninterest in OpenResty\'s API after taking a peek at its test suite .

I\'ll mostly focus on the documentation for all these cool stuffs in the coming weeks. Stay tuned!\n\"\"\"\"

','agentzh','2008-03-12 07:20:00',0),(73,'The upcoming OpenResty talk on D2 Forum','
I\'m going to talk about OpenResty and pure JavaScript web applications in the \"D2 Forum\" conference which will be held on 27 of this month:

   http://d2forum.cn

\n(Two Yahoo US colleagues will give presentations there as well :))

I\'d like to see the RSS feed and custom Action support landed onto OpenResty before this event. Let\'s wait and see :)
\n\"\"\"\"
','agentzh','2008-04-03 16:00:00',1),(74,'Overview document for OpenResty','OpenResty is a general-purpose scriptable web service platform for web applications, mostly developed by Yahoo! China EEEE Works.

It has its deep root in Jifty\'s REST design and currently supports standalone Pg and Pg cluster based on PL/Proxy. It is more or less similar to Facebook Datastore API, Amazon SimpleDB, and Apache CouchDB (at least in some aspects). Nevertheless, there\'s still several innovations in OpenResty for its own right.
\n\n
I\'ve finally come up with an overview document for OpenResty. The POD version of the document can be found at

   http://svn.openfoundry.org/openapi/trunk/lib/OpenResty/Spec/Overview.pod
\n\n
A rendered HTML version is on CPAN:

   http://search.cpan.org/perldoc?OpenResty::Spec::Overview

( OpenResty::CheatSheet also provides a good enough summary for the REST interface. )
\n\n
This is one of the materials that I\'m going to heavily rely on for my OpenResty talk at D2 forum ( http://d2forum.cn ) scheduled the next Sunday. So feedbacks (either positive or negative or just nit picking) will be highly appreciated ;)
\n\n
Now I\'m working on the GettingStarted tutorial for JavaScript programmers, Perl programmers, and Telnet users. Stay tuned!
','agentzh','2008-04-23 01:58:57',0),(75,'OpenResty versus Google App Engine','I finally get a chance to sit down and compare OpenResty with the recently announced Google App Engine\nproduct. I\'ve hesitated to do so in OpenResty\'s documentation in the\nfear of comparing apples to oranges. Well, they\'re very different\nthings from the perspective of a platform engineer.
\n
The key difference might be summarized by the following remarks:

   \"We run your applications!\"
                       -- Google App Engine

   \"You run your applications; we just fill in the blanks with REST\"
\n                       -- OpenResty

For what it\'s worth, both SimpleDB and CouchDB fall into the same category as OpenResty.
\n\n
The true buzzword for Google App Engine, however, is the BigTable monster behind it. But unfortunately it\'s not accessible by means of web services (directly).
\n
Following this reasoning, it would be really really cool if we turn\nthe Google App Engine (thus BigTable per se) into an OpenResty storage\nbackend, just like the existing Pg and PgFarm backends. But sadly\nOpenResty will have to downgrade into some kind of \"reduced mode\" in\nterms of functionalities due to the non-relational nature of BigTable.\nJoining two database tables (or \"models\" in Google App Engine\'s\nterminology) will result in a map/reduce process immediately, which may\nwell explain why it does NOT have join operations in its GQL language.\n(Well, feel free to prove me wrong ;)) And that\'s exactly why developers for Google App Engine have been manually\ndoing lots of stuff which used to be done automatically by a\ntraditional RDBMS, so as to gain amazingly good data scalability\noffered by BigTable. It\'s all about balance ;) Other semi-structured data\nstorage solutions like CouchDB and SimpleDB are suffering from similar\nissues here as well.

It\'s worth pointing out that I\'m by no means saying BigTable is\nweak. Please don\'t take me wrong ;) BigTable is indeed a godsend for\nwhat it\'s good for.

OpenResty\'s PgFarm backend distributes its user data across multiple Pg\nnodes in terms of \"accounts\". Joining tables in different accounts on\nthe PL/Proxy servers would be painful and (very) limited as well. It\'s\na fair game :) Just different distribution granularity, isn\'t it? ;)','agentzh','2008-04-23 08:43:31',0),(77,'A (potential) marriage of OpenResty and Prophet','The $boss of the Best Practical company ( http://www.bestpractical.com/\n) and the leader of the Jifty application framework, Jesse Vincent,\ncaught on me on the #jifty IRC channel, asking for the potential\ncollaboration between our OpenResty and their new baby, the Prophet\nproduct. Here\'s the related IRC log:
\n
\n(08:11:00 PM) obra: agentzh: ping
\n(08:11:10 PM) obra: agentzh: there may be interesting synergies between prophet and openresty
\n(11:29:11 AM) obra: svn://svn.bestpractical.com/Prophet
\n(11:30:06 AM) obra: http://fsck.com/~jesse/prophet.osdc.tw.pdf for a rough talk on it
\n\n(11:30:11 AM) obra: the app that uses it so far is \'sd\'
\n
\nTo me, Prophet looks very interesting. It gives me an impression of a\nRESTful svk ;) It supports off-line data checkout and true versioning like\nSubversion and CouchDB. Frankly speaking, the lack of (native)\nversioning support in OpenResty has been annoying me :)
\n
\nGoogle\'s BigTable supports a third dimension, namely the timestamp\ndimension, for data tables by means of their distributed file system.\nI\'m wondering how hard it would be to add \"native\" versioning support\nto a relational database like Pg. A (clumsy) solution used by mediawiki\nworks but not efficient enough IMHO.
\n
\nIf we can unify the two different worlds, relational world and version control world including git, that will simply rock! :D
\n
\nAnother intriguing feature in Prophet is the ability of synchronizing\nmultiple data sources automatically. It reminds me of the OpenSync\nthingy.
\n
\nWell, well, I think I need to look closer...
','agentzh','2008-04-25 07:37:07',0),(78,'The slides for my OpenResty D2 talk','My talk at the D2 conference was a big success. There\'s already some interesting discussions over the web. And there has also been a long long debate in my company\'s mailing list around the new web development mode based on OpenResty. Great!
\n
Unexpectedly, the rants from the opposite side has inspired some more exciting features for OpenResty. One example is the idea of a template API, which can be driven by an arbitrary OpenResty view to generate arbitrary contents, like HTML, JS, or any other thing that you can imagine, thus bringing the representation capability to OpenResty\'s services as well ;)
\n
The slides that I used at the talk can be downloaded from here:

    http://agentzh.org/misc/openresty-d2.pdf

Or the PPT version:

    http://agentzh.org/misc/openresty-d2.ppt
\n\n
You can also view the original XUL version in a Firefox browser if you prefer:

    http://agentzh.org/misc/openresty-d2/openresty-d2.xul

\nEnjoy!
','agentzh','2008-04-28 12:14:02',4),(79,'Google\'s crawlers captured OpenResty\'s API!','Google\'s crawlers inspect not only HTML contents, but also XML\nas well as other media types. Pure JavaScript web sites like\nhttp://eeeeworks.org are now in Google via their RSS feed provided by\nOpenResty:
\n
\n    http://www.google.com/search?hl=en&q=EEEE+works&btnG=Google+Search
\n
\nOr the screenshot here:
\n
\n\n    http://agentzh.org/misc/google-openresty.png
\n
\nThe second entry regarding api.eeeeworks.org in the result list comes from the OpenResty server:
\n
\n    api.eeeeworks.org/=/feed/Comment/count/100?user=eeee.Public
\n\n
\nThis is really exciting.
\n
\nThe google crawler even tried to access the OpenResty API that requires login. Hah!
\n
\nThe Jifty people will find the URLs there very familiar, right? ;)','agentzh','2008-04-30 03:24:46',4),(80,'Client-side web site DIY','(Sorry if you can\'t read Chinese...)
\n
\n好久没在 blog 上用中文写东西了,我的中国朋友们该抱怨了吧!呵呵.
\n
\n基于 OpenResty 的纯 JS 应用放哪儿都能跑,呵呵,包括你的桌面或者 U 盘。搁哪跑哪,呵呵。不信试一试:
\n
\n    http://blog.agentzh.org/site-binary.tar.gz
\n
\n我的整个 blog 应用都在这个 tarball 里了。下载到桌面解压后,双击里面的index.html 看效果,呵呵。还可以试试\"从本地留言\";)
\n\n
\n所以放 NCP 还是 facebook 上当然也好使。呵呵。如果未来 web app 都做成这样的就好啦,呵呵。美好的未来。。。畅想中。。。
\n
\n这种东西有趣的地方在于用户可以直接修改我的网站的展现和功能。所以没有必要让用户从我的主站去同步所谓的\"风格\"(他们只需要同步数据就可以了,只要对应的 OpenResty API 不发生变化)。
\n
\n叶姐就是这么分分钟把 http://blog.agentzh.org 网站的风格换成http://eeeeworks.org 那样的。呵呵。谢谢叶姐的工作!
\n\n
\n\n即在本地用一个写字板编辑器或者其他什么源码编辑器\"随改随跑\"。怎么着都比改PHP 这样的东西来得容易吧?呵呵。况且作为站长,我怎么可能把 PHP 给你呢?就算给了你 PHP,怎么可能让你直接连我的数据库?
\n
\n在 OpenResty 这样的架构下,网站 DIY 第一次成为可能。即使是像 TiddlyWiki 那样的东西,因为缺乏有效的数据持续和同步,只是一个 toy 而已,不能算是 web site.
\n
\n类似 GreaseMonkey 那样的插件允许用户通过挂 JavaScript 码的方式 DIY\n别人的网站,这也是一种不错的方式,缺点是依赖于 Firefox,很难作为一个独立的网站自己重新发布,而且其本质上也是一种打补丁的方式,DIY\n的程度也相当有限,经常还要面临 SearchAll 那样的解析 HTML 和抽取数据的头疼问题(问问任大侠的 GreaseMonkey\n使用体验吧!呵呵)。基于 OpenResty 的纯 JS 网站是直接运行在 web service\n之上的,所以最终用户和站长在数据展现和网站功能上的机会差不多是均等的。最终用户第一次有了可以把网站做成比站长的版本更炫更酷更强大的机会  :)
\n
\n我觉得这里没必要把我们的用户都想象成\"傻爪级\"的。呵呵。傻爪级的用户可以直接访问我的 http://blog.agentzh.org 而不会觉得和常规网站有什么大的区别。我们提供了更多的可能性和更诱人的用户自主空间。
\n\n
\n\n我觉得大家把这里的网站看成桌面应用程序就好了。不要有思维上的定势哦。
\n
\n当然了,如果一定要从我的主站同步展现的话,确实并不方便。传统的桌面软件的更新也面临同样的问题,呵呵。这是软件分发的概念,也是 DIY 网站的概念。
\n
\n我非常感激老何最初向我提出这样的理念。我一开始也比较难于接受哦,呵呵。(要怪就怪老何吧!哈哈!)','agentzh','2008-05-08 01:58:34',8),(81,'Video for my D2 talk about OpenResty and its nifty apps','Here\'s the video for my D2 talk about OpenResty (well, it\'s mostly a Chinese talk :P):

  Part 1: http://www.tudou.com/programs/view/3Tn42pPk0aU/
  Part 2: http://www.tudou.com/programs/view/Q5stEI3TSIc/
  Part 3: http://www.tudou.com/programs/view/peznAkBaJHA/
  Part 4: http://vimeo.com/1013264

Video for other speakers can be found here:

http://www.tudou.com/home/user_programs.php?userID=25459589&page=1

Enjoy!','agentzh','2008-05-16 11:11:27',5),(82,'Some Haskell love','I\'ve been reading the ``Types and Programming Languages\'\' ( TAPL ) book bought from Amazon.com and I\'ve been playing with functional languages. The TAPL book uses OCaml for sample interpreter implementations and I started by learning OCaml in the hope of using it in $work. Sadly OCaml\'s json-static and dbd-pg/postgresql libraries gave me too much pain to install and OCaml\'s restricted type system made me rather unhappy. So I turned to Haskell . Well, I should have said ``returned\'\' ;)

The syntax of Haskell is even cleaner than OCaml and its type system is much more powerful. I quickly got familiar with Parsec and monads in general by going through the famous tutorial ``Write yourself a scheme in 48 hours\'\'. Furthermore, the TAPL book\'s introduction to the lambda-calculus language helped me understand the functional programming paradigms ubiquitous in Haskell.

Great. Within just a few days, I came up with a working minisql parser for OpenResty which parses simple SQL select statements using Parsec. Building combinator parsers is really enjoyable. The whole parser is composed by several smaller ones which are in turn built upon even smaller ones and so on. Each combinator parser can also take parameters if necessary because they\'re essentially Haskell functions after all. The ability to do infinite look-aheads in Parsec gives me a lot of freedom to disambiguate my grammar without much hassles. Moreover, Parsec does not backtrack by default, so the parsing speed is still pretty good. Compared to the old minisql parser written in Perl (via the Parse::Yapp module), the Haskell version is at least 1 order of magnitude faster. Besides, the source of the Haskell one is also shorter and cleaner.

In the next few days, I happily mudded with the AST constructed by the parser and built four emitters atop it. These emitters are required by the new version of the OpenResty View API.

I successfully used Perl along with its modules Test::Base and IPC::Run3 to build a test scaffold for my Haskell compiler. The test suite is completely declarative and extensible. Surprisingly, I could still use the Haskell Program Coverage ( hpc ) toolchain to obtain a pretty HTML report for the code coverage of the whole test suite driven by Perl. So glad to have such a Devel::Cover equivalent on the Haskell land!

The source repository for my Haskell version of minisql compiler is located at

http://svn.openfoundry.org/openapi/trunk/haskell/

In the following journal or two I\'d like to share the experience of optimizing my minisql compiler and making it several times faster.

','agentzh','2008-05-29 13:11:13',1),(83,'Optimizing Haskell code: from String to ByteString','Haskell\'s built-in strings are notoriously slow. The String type in Haskell is [Char] per se. I was told that there was a much faster alternative provided by the bytestring (or fps) library by the Pugs blog a few years ago. (Thanks Audrey!)

However, it took me a while to figure out how to use it in my code. Eventually I found that All I needed were in the Data.ByteString.Char8 module rather than Data.ByteString. (Thanks Hoogle!) According to the document, it\'s recommended to import the module this way

   import qualified Data.ByteString.Char8 as B

to prevent name clashing with Prelude.

Converting String to B.ByteString is straightforward:

    B.pack \"Hello, world\"

where \"Hello, world\" is of type String.

Or in the other direction:

    B.unpack s

where s is of type B.ByteString.

Concatenating several bytestrings together can be done by the B.concat function:

    B.concat [B.pack \"hello\", B.pack \", \", B.pack \"world\"]

or just use B.append for joining two bytestrings for handy:

    (B.pack \"hello, \") `B.append` (B.pack \"world\")

Personally I like to define a ~~ operator for a bytestring version of ++ this way:

    (~~) :: B.ByteString -> B.ByteString -> B.ByteString
    (~~) = B.append

and then I can simply write:

    B.pack \"hello, \" ~~ B.pack \"world\"

Bytestring versions for most of the functions in Prelude are also provided. For instance, printing out a bytestring to stdout can be done directly by

    B.putStrLn bs   -- bs is of type B.ByteString

rather than the cumbosome and also slow

    putStrLn $ B.unpack bs

As bytestring\'s documentation points out, converting back and forth between bytestrings and Haskell\'s built-in strings could become the bottleneck of the program, especially when the source comes with lots of string literals like \"Hello, world\" shown above. Wouldn\'t it be nice if string literals get automatically interpreted by the GHC compiler to bytestrings without going through a B.pack? Fortunately, with bytestring 0.9.0.4 (or better) and GHC 6.8.1 (or better), it is possible to do that via the GHC option -XOverloadedStrings. So now we can write literals without mudding around with B.pack:

    B.concat [\"hello\", \", \", \"world\"]

or

    \"hello, \" ~~ \"world\"

Perfect! :D

Note that, as of this writing, the bytestring library in Ubuntu 8.04\'s debian repository is not new enough to support this. So ubuntu users have to install the latest version from HackageDB like this:

    $ wget http://hackage.haskell.org/packages/archive/bytestring/0.9.1.0/bytestring-0.9.1.0.tar.gz
    $ tar -xzf bytestring-0.9.1.0.tar.gz
    $ cd bytestring-0.9.1.0/
    $ runghc Setup.lhs configure -p
    $ runghc Setup.lhs build
    $ sudo runghc Setup.lhs install

By switching to B.ByteString in my code emitters for the minisql compiler mentioned in the previous blog post, the execution time dramatically reduced from 7.0 sec to 2.3 sec in my stress tests generated by the Perl module Parse::RandGen::Regexp. This is really an amazing improvement :) Furthermore, my UTF-8 regression tests kept passing as well.

In the next journal I\'ll present another optimization trick that further reduced the running time from 2.3 sec to 1.0 sec. (Well, it has nothing to do with -O2 BTW, and I turned on -O2 from the very beginning already ;))','agentzh','2008-06-12 02:18:04',1),(84,'UML::Class::Simple 0.10 released','I\'ve just uploaded UML::Class::Simple 0.10 to CPAN with the highlight of the XMI format support. It will appear on the CPAN mirror near you in the next few hours.

Thanks Maxim Zenin for contributing this feature :) A Japanese user was requesting this in his blog as well. If you\'re a XMI fanboy, feel free to try it out. ','agentzh','2008-06-20 02:30:56',0),(85,'基于 Perl 的 Firefox 插件开发框架 XUL::App 发布','我很高兴地宣布 XUL::App 已经发布到了 CPAN:

    http://search.cpan.org/perldoc?XUL::App

XUL::App 是 Yahoo! 4E team 开发的基于 Perl 的 Firefox 插件的开发框架,最初是为了简化搜索引擎平行比较工具 SearchAll 插件的开发工作而设计的。随后,我们又利用 XUL::App 框架开发了一款能从 Google Reader 中导出 RSS 数据项的小插件 ExportReader。有趣的是,ExportReader 总共只手写了约 10 行 Perl 代码和 20 行 JavaScript 代码。最近,我又花了几个小时的时间,把原来我们 FE 开发的\"雅虎收藏+\"插件移植到了 XUL::App 框架中,从而使得调试和打包工作都只是简单的一条命令。(引用晓栓同学的话说,就是\"今天下午看Agent 调程序,那是相当的酷:)\")

我在 4E team 内部作的 XUL::App 演讲所使用的幻灯片介绍了 XUL::App 的几个重要特性:

http://agentzh.org/misc/slides/xulapp.pdf

熟悉 Perl 酷炫的 Jifty 框架的朋友会发现 XUL::App 就是 XUL 星球上的 Jifty :)

XUL::App 是一个我们领导的开源项目,目前仍处于比较早期的阶段。我们目前需要一个完整的测试集,以及更多的文档(特别是更多的教程)。如果你有兴趣参与开发和自动化测试工作的话,请发送邮件给我们(agentzh@yahoo.cn),我们很乐意递送 Subversion 提交权限 :)

-agentzh','agentzh','2008-06-24 02:26:27',0),(86,'The first yahoo.cn feature that is powered by OpenResty','See the company blog post here for details:

    http://ysearchblog.cn/2008/06/post_120.html

especially my comment at the bottom of the web page.

Have fun!','agentzh','2008-06-27 05:49:36',1),(87,'Building (Ubuntu) debian packages for OpenResty and its dependencies','

I\'ve been building debian packages for OpenResty and its dependencies that are not already in the official Ubuntu debian repository. Here\'s what I got yesterday:

  http://agentzh.org/misc/debian/

For now only the i386 versions are provided :P I\'ll set up a personal debian repository for these deb files later.

During the process I found the following articles very helpful:

    \"Building Debian packages of Perl modules\" http://www.debian-administration.org/articles/78

    \"Debian New Maintainer\'s Guide\" http://www.debian.org/doc/maint-guide/

But still, I spent a lot of time to figure out the following details:

For CPAN modules based on Module::Install, dh-make-perl seems to fail to find proper dependencies. In this case, one has to edit the file debian/control manually, as in

    http://svn.openfoundry.org/openapi/trunk/debian/control

If the CPAN module wants to install configure files to places like /etc/..., then it\'s required to manually create the file \"conffiles\" under debian/, as in

    http://svn.openfoundry.org/openapi/trunk/debian/conffiles

And then modify the debian/rules makefile\'s \"install\" rule to put the default config files to $(TMP)/etc/..., as in

    http://svn.openfoundry.org/openapi/trunk/debian/rules

Another hack I have to do against rules\' \"install\" rule is that I have to remove the perllocal.pod file manually from $(TMP), since inclusion of this file in the .deb file will cause conflicts like this:

dpkg: error processing libjson-xs-perl_2.22-1_i386.deb (--install):
 trying to overwrite `/usr/lib/perl/5.8/perllocal.pod\', which is also in package libtext-table-perl

For modules which require doing some post-installation processing, we should create the file debian/postinst and put shell commands into it.

','agentzh','2008-07-17 02:35:20',2),(88,'OpenResty running directly in PostgreSQL via PL/Perl','A few hours\' hacking gives rise to the following funny stuff:

  test=# select openresty_init();
     openresty_init
  ---------------------------
   t
  (1 row)

  test=# select openresty_request(
  test=#   \'GET\', \'/=/view/PrevNextPost/current/79?user=agentzh.Public\',
  test=#   \'\',\'\');
          openresty_request
  ----------------------------------------------
   [{\"title\":\"The slides for my OpenResty D2 talk\",\"id\":\"78\"},{\"title\":\"Client-side web site DIY\",\"id\":\"80\"}]
  (1 row)

  test=# select openresty_request(\'GET\',\'/=/view/PrevNextPost/current/79?user=agentzh\',\'\',\'\');
       openresty_request                   
  ------------------------------------------------
   {\"success\":0,\"error\":\"agentzh.Admin is not anonymous.\"}
  (1 row)

The PL/Perl backend is not fully working yet but it\'s already functional as we see above ;)

The definition for the (thin) SQL wrapper functions openresty_init and openresty_request can be found in the following file:

http://svn.openfoundry.org/openapi/trunk/misc/plperl.sql

And the PL/Perl backend for OpenResty is

http://svn.openfoundry.org/openapi/trunk/lib/OpenResty/Backend/PLPerl.pm

The code is much cleaner than I ever expected ;)
','agentzh','2008-07-18 10:35:49',1),(89,'Filter::QuasiQuote 0.01 is now on CPAN','After reading Audrey\'s blog post mentioning GHC\'s upcoming quasiquoting feature (as well as that quasiquoting paper), I quickly hacked up a (simple) quasiquoting mechanism for Perl, hence the Filter::QuasiQuote module already on CPAN:

http://search.cpan.org/perldoc?Filter::QuasiQuote

I\'m looking forward to using sensible filters in my production code (e.g. OpenResty) and eliminating ugly Perl code for with embedded DSL. For example, instead of writing

    my $sql = \"alter table \" . quote_identifer($table) . \" drop column \" . quote($column) . \";\";

I can simply write

    use OpenResty::QuasiQuote::SQL;
    my $sql = [:sql| alter table $table drop column $column; |];

Also, a JSON-like DSL can be used to describe valid Perl data structures and to generate the Perl code doing validation.

Filter::QuasiQuote supports subclassing, so the OpenResty::QuasiQuote::SQL module mentioned above could be derived from it. Also, multiple concrete filter classes could be composed in a single Perl source file. Just put a series of use statements together:

    use MyQuote1;
    use MyQuote2;

and it should work. Because it\'s required that filters always return Perl source aligned in a single line, line numbers won\'t get corrupted.

Of course, lots of nice consequences of the Haskell quasiquotations will be lost in my implementation, such as type safety. But the Perl version is much more flexible and powerful (by some definition) ;)

It\'s still in alpha and could be buggy. Feel free to report bugs or send wishlist to the CPAN RT site or directly to me ;)

Enjoy!','agentzh','2008-08-05 10:24:52',0),(90,'GHC 6.8.3 binary for older linux','I ran into the following error while trying to run a binary generated by GHC 6.8.x on our production machines with a not-so-recent linux installed (kernel 2.6.9).

  $ ./restyscript
  restyscript: timer_create: Invalid argument
\n
Evan building a pure static-linking executable did not solve the problem.

Then I downloaded the binary GHC 6.8.3 from haskell.org on that machine, but the ghc crashes as well:
\n
 $ ghc
 Floating point exception

My teammate chaos++ found that the last time precision argument passed to the timer_create function was just too big. Manually editing the binary executable (the restyscript file in the previous example) solved this issue completely, but, yeah, it\'s terribly hacky.
\n\n
So I decided to build a GHC 6.8.3 from source on that old system using GHC 6.4.2. Fortunately, the binary GHC 6.4.2 from haskell.org does work there. The newly-built GHC solves all the problem. No floating-point exception nor invalid argument for timer_create. I\'ve put my binary distribution on my site here:
\n
  http://agentzh.org/misc/ghc-6.8.3-i386-old-linux.tar.bz2

Hopefully it\'ll be useful for someone else ;) Not sure if it\'s worth putting to the official download page as well :)
\n
Ideally GHC should inspect the kernel version and timer_create support at *runtime*, rather compile-time. It\'ll make our lives much easier ;)
','agentzh','2008-08-14 08:32:39',0),(91,'在 JavaScript 中使用 CPS 完成网站遍历','海维发到邮件列表的第一封邮件是非常值得仔细一读的,在那里我们可以看到 Lisp 程序员是如何思考的,特别地,如何通过显式调度栈的方式来串行化异步执行流。

昨晚我经过认真的思考之后,惊喜地发现,我们可以把海维的 continuation 用法进一步抽象到一种著名而且又很时髦的编程模式:Continuation Passing Style:

   http://en.wikipedia.org/wiki/Continuation-passing_style

在海维的抽取案例中,我们遇到的主要问题是,timeout handler 的串行链条很长,而且更有趣的是,这条链接本身是动态构造出来的。如果保证这条链条不因中间某个环节出错而中断,如果很优雅地把这条执行链构造出来,乃是这里问题的核心。我们首先需要遍历省份列表,然后是市级行政区列表,县级行政区列表,最后是中学列表。如果用 EBNF 记法来表示的话,是下面这个样子:

   top: province*

   province: city*

   city: district*

   district: school*

这里 * 表示 0 次或多次重复。当我们出发时,位于 top 符号的位置上,然后我们经过必要的初始化操作,抓出所有的省份列表。对于每一个省份,我们进入到 province 符号,点击那个省的链接,过一段延时后再抓出 city 列表,再依次地处理 city,依此类推。这里使用正统的面向过程的编程方法的一大困难是,执行流本身不是顺序的,在每一步点击链接后,需要用 setTimeout 断开。而在 CPS 中,我们处理第 i 个 province 时,我们不妨告诉处于该 province 的例程,在它完成自己的工作后应该继续去处理余下的 i + 1, i + 2, ... 个省。例如:

     function processProvinceList (c, provinceList) {
          //  终止条件,遇到空省列表直接调用当前的 continuation 对象 c 返回之
           if (provinceList.length == 0) return c();
           var province = provinceList.pop();   // 弹出当前的省份
           var cc = function () {   // 生成子 continuation 对象
               processProvinceList(c, provinceList);   // \"递归\"地调用自身处理余下的省份列表
           };
           clickAndRecord(province);  // 点击省份链接,并将之记录下来
           setTimeout( function () {
               var cityList = getCities();    // 一段延时之后抽取city列表
               processCityList(cc, cityList);   // 调用下一级 city 列表的处理函数
           }, delay);
     }

由于 city 在前面的 EBNF 定义与 province 完全相同,所以 processCityList 和上面的 processProvinceList 的形式几乎完全一样。同样的道理,processDistrictList 也是\"同构异形体\"而已。于是想到把它们合并为一个通用的 processList 函数:

    function processList (c, list, level) {
        var _this = arguments.callee;
        //终止条件,遇到空列表直接调用当前的 continuation 对象 c 返回之
        if (list.length == 0) return c();
        var obj = list.pop();   // 弹出当前的项目
        clickAndRecord(obj, level);  // 点击该项链接,并将之记录下来
        setTimeout(function () {
            var sublist = getList(obj, level-1);    // 一段延时之后抽取下一级列表
            _this(function() {return _this(c, list);}, sublist, level-1);   // 调用下一级列表的处理函数
        }, DELAY);
    }

这样我们只需要定义不同层次 (level) 上的 clickAndRecord 和 getList 函数就可以了 :)

这里比较有趣的是 processList 函数在\"根\",也就是 top 上的调用方法:

     var provinceList = getProvinceList();
     var c = function { return true; }
     processList(c, provinceList, 0);

这里我们创建了最根部的 continuation 对象 c,我们看到,它就是一个直接返回的空函数而已,呵呵。这 3 行代码开始了下面的 continuation 和 setTimeout 交织延伸到 c 的一条很长很长的链条,或许我们可以把这条链形象地看成从两边往中间生长的 ;)

我已经基于 XUL::App 框架将这做成了一个 Firefox 插件:

http://svn.openfoundry.org/xulapp/trunk/demo/ExtractX/extractx.xpi

安装后,在地址栏中输入 chrome://extractx/content/extractx.xul 然后登录一下(第一次使用时),再点一下 Extract! 按钮就出东西了。同时还实现了按指定的省份抓取,以及取消抓取,自定义抓取延时的 delay 等功能 :)

该插件完整的源代码位于

http://svn.openfoundry.org/xulapp/trunk/demo/ExtractX/

整个东东不过是几十行 Perl 外加一百多行 JavaScript 而已,呵呵。

前面介绍的 processList 函数,比上面的示范代码要稍稍复杂一些,主要考虑了剪枝优化等操作,但主干是完全一样的:

http://svn.openfoundry.org/xulapp/trunk/demo/ExtractX/js/extract.js

值得一提的是,CPS 是非常强大的编程技术,它一般可以带给程序员两样好处:

1. 使得程序能够自动回溯
2. 使用程序各个部分 composable,即像积木一样可以从小块搭成大块乃至更大)

基于 CPS 可以实现一个比较完整的 Perl 5 正则引擎。我就是通过阅读 putter 大拿用 Perl 书写的 Perl 5 正则引擎,才理解了 CPS 的用法。有兴趣的同学可以看一看 putter 的实现:

http://svn.pugscode.org/pugs/misc/pX/Common/regexp_and_parser_spike/regexp_engine_demo.pl

在前面的讨论中,我们已经注意到了网站抓取路径可以用 EBNF 语言,或者说正则语言来描述。

更一般地,我们可以定义 EBNF 中的符号 a 表示一项抓取任务,它由两部分组成:一是对应的 DOM 节点的 selector,即抽取模式,二是执行的动作,比如触发一个到 DOM 节点的点击事件,或者执行某些网页状态的测试操作,动作的返回值决定了当前抽取任务 a 是否成功。然后我们再定义连接操作: a b 表示抽取任务 a 与 b 必须同时完成,否则 a b 这个整体任务则是失败。类似地,a | b 表示先执行任务 a,若成功则整个任务成功,若 a 失败,则执行任务 b,若 b 成功,则整个任务成功,否则整个任务失败。最后再定义一下闭包:a * 表示任务 a 在抽取时得到的是一个 DOM 列表,而对于该列表中的每一个节点,都作为一个独立的抽取任务执行之。这些任务必须全部成功才算成功。a* 可以拥有一些变种,比如非贪婪的 a*?,还有显式指定重复次数的 a{n}, a{m, n} 等等。

在后面的工作中,我准备实现这样一个从 EBNF 描述自动生成基于 CPS 的 JavaScript 遍历网站代码的编译器。这样自动化一个网站的抓取和测试工作,也就差不多等同于书写一个 EBNF 描述甚至于一个小正则表达式了 ;)

Stay tuned!','agentzh','2008-09-01 04:45:33',0),(92,'My slides for the upcoming OpenResty talk at YAPC::Beijing 2008','I\'ve finished the first draft of my slides for my OpenResty talk at the upcoming YAPC::Beijing session:

    http://agentzh.org/misc/openresty-yes/openresty-yes.xul  (Firefox only)
\n\n\n
A pdf (but less pretty) version could also be found here:

    http://agentzh.org/misc/openresty-yes.pdf

I\'ve already given this talk to my colleagues on the company level and it was a big success :)
\n\n
Feedback, comments, or even nit-picking will be highly appreciated.

P.S. I\'m still wondering what to talk for the other presentation. Jemplate? XUL::App? Filter::QuasiQuote? Or Test::Base?','agentzh','2008-09-17 02:07:50',2),(93,'pod2html.js: Some JavaScript love for POD in a browser','It\'s fun to do POD (Plain Old Documentation) in a web browser and I\'ve hacked up a JavaScript implementation for the pod2html utility (actually the output is more like Pod::Simple::HTML).

The pod2html.js script is in OpenResty\'s SVN repository:
\n
   http://svn.openfoundry.org/openapi/trunk/demo/Onccf/js/pod2html.js

The API is straightforward, for instance,

   var pod = \"=head1 Blah\\n\\nI<Hello>, C<world>!\\n\";
\n\n    var html = pod2html(pod);

The following web site is already making use of it:

   http://agentzh.org/misc/onccf/out/

By sniffing the background AJAX requests (e.g. using Firebug), you can see raw POD is retrieved from the OpenResty server and converted to HTML on-the-fly in your browser.
\n
It\'s worth mentioning that I had a lot of fun combining Test::Base and JavaScript::SpiderMonkey to test this piece of JavaScript code in pure Perl. You can checkout the test script here:

   http://svn.openfoundry.org/openapi/trunk/demo/Onccf/t/01-pod2html.t
\n\n
By looking at the (declarative) test cases, it\'s trivial to see what it can do (and hopefully what it can\'t) :)

For the record, as of this writing, the following POD directives are supported:

  =headN, =over, =item *, =item NUM., =item TEXT, =back, =begin html, =end html, =begin ANY, =end ANY, =cut (it\'s a no-op), =encoding ANY (it\'s a no-op)
\n
and the following POD markups are implemented:

   C<...>, I<...>, B<...>, L<...>, F<...>

I\'ve also implemented the (non-standard) =image directive for convenience. For example,
\n\n
   =image gate.jpg

will be converted to

   <p><img src=\"gate.jpg\"/></p>

Have fun!
','agentzh','2008-09-28 02:30:01',0),(94,'Now we have Actions!','On behalf of the OpenResty team, I\'m happy to announce that OpenResty 0.5.0 has been released to CPAN, which means OpenResty has hit its 5th milestone indicated by a working Action API.
\n
Special thanks go to chaoslawful++ for acting as the pumpkin of the Action branch.
\n
It\'s worth mentioning that the hardest part of the Action handler, i.e., the RestyScript language compiler, is written in Haskell.
\n
I\'ve found Acitons very useful in grouping together concurrent AJAX requests, which will make webpages load much faster. Our blog sites are already taking full advantage of this trick:

    http://blog.agentzh.org
\n    http://www.eeeeworks.org

Also, Actions ensure cascaded requests run in exactly the expected order and the REST interfaces are called (mostly) in the expected way (e.g. from the end users\' web browser). There used to be a serious security hole in the above blog sites in past because I had to expose PUT /=/model/Post/~/~ to the Public role for updating the \"comments\" field in the Post model before we have Actions.
\n
The main server for OpenResty, api.openresty.org, has already been upgraded to 0.5.0. If you want to play with OpenResty directly on our servers, feel free to write to me (agentzh at yahoo dot cn) and get an account for free!
\n\n
Enjoy!','agentzh','2008-09-29 08:59:45',2),(95,'漫谈 Perl 的 web 应用开发框架','忍不住在 PerlChina 邮件列表中盘点了一下 Perl 里的 Web 应用框架(巧的是 PerlBuzz 最近也有一篇相关的讨论帖),于是乎,决定在我自己的 blog 上也贴一下 :)

原生 CGI/FastCGI 的 web app 对于较小的应用非常合适,但稍复杂一些就有些痛苦,但运行效率是最高的 ;) 如果是自己用 Perl 开发高性能的站,多推荐之。
\n
Catalyst, CGI::Application, 和 Jifty 是最流行的三大框架。CGI::Application 是 CGI 之上很薄的一层,非常 popular,呵呵,这里的许多哥们使用之。Catalyst 也见过许多网站应用,包括比较大的网站。从技术和想法上讲,Jifty 的创新点非常多,有许多非常酷的设计,甚至有些独创之处。唐凤,Jesse Vincent, clkao 都是 Jifty 的开发者,我也为 Jifty 贡献过一些补丁和文档。
\n
从架构上讲,这些框架与 Ruby 的 RoR 和 Python 的 Django 没有本质区别,甚至可以说是大同小异,只是许多细节和设计理念若有区别。比如 Catalyst 是典型的 N 种方式完成同一件事情,使用起来感觉更像是自组装的自行车;而 Jifty 则是 full-stack 那种,哲学是 One Best Way. 这些框架都存在一个问题,即多是\"解释型\"的,多是多层堆砌起来的。Web server 上都得跑一个很大的 runtime,都有 N 多 CPAN 依赖项,布署的成本都非常高(不是一般的免费租用空间能胜任的)。于是我发现,虽然我很喜欢 Jifty,但我却不愿在自己的 web 服务器上布署之,即使我有 root 权限。
\n\n
这让我陷入了很深的思考。。。我和 Jifty 的老大 Jesse 也交流过。。。我们的 web 应用框架是否应该学习一下 C/C++ 这些编程语言的编译器?是否应该做成\"编译型\"的框架,而非解释型的?这样,即使我们开发时使用很多库,很多 Perl,很多工具,但经过框架的处理,最终我们可以得到一个高性能的依赖项极少的很薄的而且高度自治的网络应用?而且这种应用还可以在多机集群的环境中很容易地 scale?

\n这个最终得到的\"二进制\"的网站是什么样子,就依赖我们的想象力和需求了。它可以是一个非常轻便的 CGI/FastCGI 的 Perl 脚本,或者根本不含 Perl,只有布署成本极易的 JavaScript 代码或者 PHP 代码。

在过去的一年内我做了许多有趣的尝试。XUL::App 就是这种思考的实践,我们在开发过程中可以使用许多 Perl,包括 Template::DeclareLocale::Maketext::Lexicon 这样的模块,但最终得到的 Firefox 插件产品中却不含一行 Perl 代码,可以安装在任何机器上。当然了,XUL::App 并非建站框架了,但有许多类似之处。
\n\n
随后,因为工作需要,开始开发 OpenResty。在这里,我们的\"最终的二进制网站\"是一种极端,即完全由 .html, .js, .css 等静态文件组成,但却是高度交互性的。所以这种网站的布署成本严格为 0,毕竟它是纯客户端的网站,完全运行于用户的浏览器中,因此即使没有 lighttpd 和 apache 这样的服务器,直接从桌面双击打开也能正确运行。

然而,我们同时必须解决中央数据源的问题,所以我们走了通用目的但同时又是用户可定制的 web service 平台和跨域 AJAX 的道路。我们已经成功地得到了纯 JS 的博客小BBS以及公司主页性质的网站。我们下面还要尝试纯 JS 的全功能论坛,纯 JS 的 Gmail 和 RSS Reader,以及原生 PHP 站的生成(不能否认 PHP 的布署在许多最一般的情况下比 Perl web app 要容易要经济,所以我们是朋友,不是敌人 ;) )关于这个主题,我可以一直说下去,呵呵,不过这次 Perl Workshop 上的 OpenResty talk 我还可以慢慢道来,呵呵。
\n
巧的是,clkao 也在我之前做过类似的尝试。他试图从使用了 Template::Declare 的 Perl 代码生成原生的客户端 JavaScript 代码,利用了一些 B::Deparse 模块的高级技巧。与 XUL::App 类似,他也把 perl 的 Maketext 的 I18N love 带给了客户端的 JavaScript 代码。必须承认,这一点也值得 XUL::App 学习,目前 XUL::App 的 I18N love 只限于 XUL 代码(虽然 JS 代码可以利用隐藏的 DOM 节点技巧而享受到 I18N,但无疑有些 hacky 了)。
\n\n
无论如何,Jifty (以及最近的 Prophet)都是非常值得一看的好东东。我参加工作以来的大部分 $project 的灵感都来源于 Jifty. 所以我曾和 Jesse 说过:\"I\'ve found myself stealing good ideas and even code from Jifty in $work but avoiding using Jifty directly.\"
\n
那么作为初学者,学习那个好呢?以鄙人之见,博采众家之所长方是\"万全之策\" ;)
','agentzh','2008-10-10 03:53:19',0),(96,'研究是一种习惯','我一直不太赞同研究必须先完成大量专业知识的积累。事实上,研究、创新和探索应该贯穿整个学习过程,甚至整个人的成长历程。
\n
所以指望上学上到研究生再正式开始做\"科研\"是可笑的。因为已经晚了。抱有这种想法的孩子多半已被二手知识洗过脑了,不能再做真正意义上的研究了,于是乎褪变成了\"为研究而研究\"。国内这才出现了那些质量差得令人哭笑不得的所谓的\"学士论文\"和\"硕士论文\",或许如今许多研究生能替导师打打短工就已经很不错了。。。这正应了小纳什的那句话:\"过度地接受二手知识只会损害自己的原创力.\"
\n
前一阵子和刚上大学的表妹说到了毕业论文的选题。我的意见是,论文的题目很可能是过去学习过程中某一个特别有趣但还没有充分发掘的\"延伸点\"或者说\"灵感源\"。在平时没有做过任何实际的研究和探索之前,就挖空心思去想具体的研究方向和论文的题目,是武断而荒谬的。做出象样的成果的可能性在我看来几乎没有,除非导师自己乐意代劳。

我在和妹妹的沟通过程中一直试图表达这样一个意思,那就是研究应当成为一种习惯--一种看书习惯,一种解题习惯,一种听课习惯,和一种思考习惯。我们可能在学习过程中的任何一个点上得到灵感(如果我们以学科主人的姿态进行学习的话),进而作出自己的创造和贡献。很多时候,随着我们学习的深入,我们会惊讶地发现自己先前的一些延伸思考和创新成果,可能会跟前辈大家们的结论不谋而合!事实上,这种撞车是幸运的,而且随着时间的推移,撞车会越来越少,那么原创也就会越来越多了。可惜的是,许多人的心是浮动的,而研究和探索需要绝对宁静的心 :)
\n\n
有趣的是,就当世界最顶尖的物理学家们仍对惯性定律和万有引力定律中的质量 (m) 的物理学本质百思不得其解时,中国的孩子们早已把\"质量是物体所含物质的多少\"这一句不是定义的定义,作为教条,背得滚瓜烂熟了,岂不悲哉?而根据我自己的经历,在中国的学校里如果对这样的细节问题追问老师的话,老师就会把\"爱钻牛角尖\"的大帽子扣在你的脑门上,而事实上这些问题多数在物理大家那里都是很重要的。

疑问,沉思,发散,和关联等等,都是研究的种子,而当研究已然成为一种习惯时,它便不再做作,不再神秘,不再喜大好功和脱离实际。
','agentzh','2008-10-13 04:34:25',16),(97,'Q4 is crazy!','

Yeah, Q4 is really crazy! I\'ve been hacking on several company projects in parallel over the last few weeks. Fortunately they\'re all very interesting stuffs.

We\'ve just kicked OpenResty 0.5.2 out of the door and I\'m preparing for the 0.5.3 release right now. My teammate xunxin++ has quickly implemented the YLogin handler for OpenResty, via which the users can use Yahoo! ID to login their own applications on OpenResty. Our Yahoo! registeration team helpfully worked out a sane design to allow us to reuse the Yahoo! Login system, which effectively turned Yahoo! ID into something like a passport, at least from the perspective of OpenResty users :) Big moment! Lots of company products using Yahoo! IDs could be rewritten in 100% JavaScript! Actually our team is already rewriting the Search DIY product using all the goodies offered by OpenResty.

Meanwhile, some guys from Sina.com are doing their personal projects in OpenResty. They said they really appreciated the great opportunities provided by the OpenResty architecture since various kinds of clients (e.g. web sites, cellphones, desktop apps, and etc.) could share the same set of API via OpenResty\'s web services). They also sent a handful of useful feedbacks and suggestions regarding OpenResty\'s design and implementation.

I\'ve also been working on an intelligent crawler cluster based on Firefox, Apache mod_proxy/mod_cache, and OpenResty. The crawler itself is a plain Firefox extension named List Hunter:

    http://agentzh.org/misc/listhunter.xpi

It\'s an enhanced version of the Haiway List Recognization Engine used by my SearchAll extension and also built by my XUL::App framework. You can install it to your Firefox and play with it if you like ;) What this extension does is very simple: recognizing \"list regions\" and \"text regions\" in an arbitrary web page and further deciding automatically whether it\'s a \"list page\" or a \"text page\". The latter functionality may sound a bit weird: why is it useful to categorize web pages that way? Anyway, our PM (Product Manager) has crazy ideas about that categorization in our Live Search project and knows better than us ;)

Turning such a Firefox extension into tens or even hundreds of Firefox crawlers running on a bunch of production machines requires a lot of work. I devised a prefetching system which prefetches HTML pages and CSS files included in them, and caches the headers and contents for a fixed amount of time in such a way that Firefox crawlers can later load pages and CSS stuffs directly from the same cache in our local network, thus significantly reducing the page loading time in Gecko. The cache is a heavily patched version of Apache2\'s mod_cache with mod_disk_cache as the backend storage. The way prefetchers and crawlers interact with the Internet and the cache is via HTTP proxies based on Apache2\'s mod_proxy. Pipeling the prefetching and crawling processes requires OpenResty with PgQ enabled. Well, I\'m still working on this cluster and my goal is 2 pages/sec for every single Firefox process. Firefox 3.1\'s amazing performance boost (more than 30% faster according to my own benchmark) makes me very confident in abusing Gecko to build efficient crawlers that takes advantage of the rich rendering information.

Another Firefox crawler project haunting my head is a similar one that automatically recognizes and extracts user comments from arbatrary web pages (if any comments appear, of course). Such tasks would be hard if my code has to run without the geometric informations of every DOM nodes provided by the browser rendering engine (in the form of offsetWidth, offsetHeight, offsetTop, and offsetLeft attributes of DOM elements). Some other collegues in our Alibaba\'s Search Tech Center are putting their head around Cobra, a pure Java HTML renderer. But I\'m doubting that it would run more correctly or more efficiently than Gecko. Oh well, I\'m not a Java guy anyway...

Finally, just a short note: I had a wonderful time with clkao and Jesse Vincent at Beijing Perl Workshop 2008. I learned pretty a lot about the Prophet internals during the hackation after the conference, and Jesse quickly hacked out a stub OpenResty model API for Prophet. Then we went to the Great Wall the next day. I was amazed to find Jesse hacking crazily on the Great Wall and enjoying the sunshines alone...Wow.

Enough blogging...back to hacking ;)

','agentzh','2008-11-29 12:58:25',2),(98,'Project Roadmap for OpenResty','Today I wrote down OpenResty\'s milestone list into its documentation because many people had asked me for that.

Well, the actual release numbers may vary as we go. But I\'d love to see all these happen sooner or later anyway ;)

Please don\'t hesitate to tell us what you think :)
','agentzh','2008-11-30 07:28:35',0),(99,'OpenResty now uses the BSD license','We\'ve migrated OpenResty to the BSD license since the 0.5.3 CPAN release, because my $boss laser++ wants to maximize code reuse and collaboration :)

Just as a side note: I\'ve created an #openresty IRC channel on irc.freenode.net. See you there ;)
\n','agentzh','2008-12-01 05:29:08',2),(100,'漂在北京','漂在北京的感觉有时真的很好。

喜欢一个人傍晚在优美的东直门外大街散步的感觉。。。高大的桦树,宽阔的街道,还有两旁一片片宁静的使馆小楼。。。特别是雨后,在这里,感觉整个世界都是那么清爽。每当这种时候,我便不由地回味起中学时代思考过的各种有趣的问题,重温从前浮在脑海中的人工智能世界的美妙愿景,抑或是回顾学生时代的各种酸甜苦辣。。。\"什么都可以想,什么都可以不想。\"

在住处附近的团结湖公园散步,则是另一番滋味。桃红柳绿之间是一汪清澈的小湖,远远地能听见老人们在湖边悠扬的歌声。北京人怡然自得的一面,在这里显露无遗。而我则喜欢周末时分,独自坐在湖边的长椅上,慵懒地晒着太阳,同时静静地,静静地思考工作中遇到的一些引人入胜的数学和工程学课题 :)
\n
每天午后,我也会偷偷跑到公司对面的首经贸大学漫步。这是一个很小的校园,却也算是在高楼林立的万达闹中取静了。与在清华散步时心中产生出来的对科学的崇敬和庄严感不同的是,在这里,我只选择凝视着树稍的小鸟上下跳跃,抑或是坐在高大的白杨树下的长椅上,看着这个学校的各种肤色的学生来去匆匆。

人生,或许就应该是一种悠闲的漫步历程吧。。。
','agentzh','2008-12-13 07:50:25',6),(101,'生活搜基于 Firefox 3.1 的 List Hunter 集群',' \n\n

NAME

\n\n

List Hunter Cluster - 我们自己的基于 Mozilla Firefox 3.1 的深抓爬虫集群\n\n

DESCRIPTION

\n\n

该文档介绍了我们的基于 Firefox 3.1 的 List Hunter 集群。目前是我们公司生活搜索引擎的一部分。\n\n

背景

\n\n

在我们的生活搜索项目中,需要对网页进行深层次的识别和抽取。基于文本内容的分类我们目前采用的是美国雅虎基于最大熵的 DCP 系统。而对于网页结构方面的分类(即这个网页是列表页呢,还是详情页?),以及主体链接列表、主体区域抽取,则一直缺乏比较好的解决方案。我的同事尝试过通过纯粹的结构化的方法(如海维算法)进行识别,准确率只有 60%,而基于 SVM 这样的机器学习的方法,对网页类型比较敏感,如目标网页与训练集相差较多,则准确率迅速下降。\n\n

于是我尝试把网页显示时的视觉信息结合到海维算法以及块合并算法中。于是准确率和召回率分别达到了 90% 和 80%。这里的视觉信息主要包括一个网页区域的大小、形状、和在整个页面中的位置。更多的信息还包括字体、颜色等等。这样,便诞生了 List Hunter 插件。于是如何将 Firefox 插件做成一个大规模的集群用于生产,便成为了重要问题。\n\n

在下面这篇 blog 文章中我介绍了更多背景方面的细节以及 List Hunter 插件本身的情况:\n\n

http://blog.agentzh.org/#post-97\n\n

该插件只依赖于 Firefox,可以即装即用:\n\n

http://agentzh.org/misc/listhunter.xpi\n\n

集群的架构

\n\n

该集群由四大部分组成:纯 Firefox 集群,Apache + mod_proxy + mod_disk_cache 集群,curl 预取器集群,和 OpenResty 集群。一共有十几台生产机\"全职\"或者\"兼职\"地参与了这个集群。下面逐一介绍一下哈:\n\n

\n
纯 Firefox 集群\n\n
\n

纯 Firefox 集群目前由 8 台 4 核的 redhat5 生产机组成。每台生产机运行 3 个 Firefox 3.1 进程实例。因为那 8 台机器同时服务于淘宝 VIP 搜索的商口图片显示接口(大约 600 万日 PV),所以我们没敢在这些机器上运行比较多的 Firefox 进程。\n\n

需要指出的是,Firefox 默认是\"进程复用\"的运行方式。即启动多次 firefox-bin 可执行程序,其实得到的还是单个 Firefox 进程。这种进程复用方式无法充分利用生产机的多核 CPU。因为在任意给定时刻,一个 firefox 进程(哪怕有多个窗口里的 JS 在同时打满运行)只能跑在一个核上,因为它不是多 OS 线程的。为了让 Firefox 以多进程方式运行,需要:\n\n

    \n
  1. 在调用 firefox-bin 程序时指定 -no-remote 命令行选项,或者设置环境变量 MOZ_NO_REMOTE=1\n\n
  2. 以不同的 profile 运行不同的 firefox-bin 进程(利用 -P 命令行选项)。\n
\n\n

我们平常看到的 Firefox 的主窗口并不启动,而以 chrome 方式单独运行 List Hunter 插件的界面,例如:\n\n

firefox -chrome chrome://listhunter/content/crawler.xul -P crawler2 -no-remote\n\n

以 chrome 方式运行的插件与 XULRunner 方式运行的 XUL 应用是很类似的。\n\n

由于 Firefox 3.1 还没有正式发布,我直接 checkout 官方 Mercurial 源码仓库内的最新版本,自己在我们的 redhat 生产机上编译的。我们目前几乎没有修改官方的 C++ 源代码,为了方便和官方版本保持同步。我们目前使用的是下面的 firefox 编译选项:\n\n

# My .mozconfig
mk_add_options MOZ_MAKE_FLAGS=\"-j2\"
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/ff-opt
ac_add_options --enable-crypto --enable-feeds --disable-profilesharing
--enable-rdf --enable-zipwriter --disable-tests --disable-gnomeui --disable-cookies
--disable-canvas --disable-gnomeui --disable-inspector-apis --disable-mailnews
--disable-mathml --disable-official-branding --enable-plaintext-editor-only
--disable-postscript --disable-printing --disable-profilelocking --disable-safe-browsing
--disable-startup-notification --disable-svg --disable-svg-foreignobject
--disable-updater --disable-javaxpcom --disable-plugins --disable-crashreporter
--disable-tests --disable-debug --enable-application=browser --build=i686-linux
--disable-jsd --disable-ldap --enable-strip --disable-accessibility --disable-ogg
--disable-dbus --disable-freetype2 --disable-optimize
\n\n

这里能禁用的功能我们都禁用了,这里的 feeds, rdf, crypto 这三个都不能 disable,否则源码编译不通过,会报一些 .h 头文件找不到,呵呵。--disable-ogg 实际上也不起作用,但从网上的材料看曾经有效过,呵呵。\n\n

事实上,目前我们还是给官方的源码打了一个 C++ 补丁,用于将 Error Console 中的 Errors 重定向到 stderr,这样方便我们在集群环境下通过 Firefox 进程的 log 文件捕捉和诊断一些异常。目前的补丁是下面这个样子:\n\n

http://agentzh.org/misc/191src.patch.txt\n\n

值得一提的是,Firefox 进程本身是\"无头\"的,即它运行在 Xvfb 这个 X server 之上,只在内存里执行渲染,而不需要任何显示硬件的存在。这些 Firefox 进程本身是挂在我们自己的一个 Perl 写的进程监控脚本之下。该脚本来自我们的 Proc::Harness 模块:\n\n

http://svn.openfoundry.org/xulapp/trunk/demo/ListHunter/misc/Proc-Harness/\n\n

Proc::Harness 会像 lighttpd 的 Fastcgi server 一样,维护一组指定数目的进程(通过 CPAN 上的 Proc::Simple 模块)。当子进程挂掉后立即重启,或者当子进程的 stderr/stdout 输出不再变化一段时限之后也杀之重启。Proc::Harness 脚本自身则是挂在了 deamontools 之下。\n\n

这些 Firefox 进程受安装在其中的 List Hunter 插件的完全控制。它们都是高度自治的 robot。它们内部有一个处理循环,一批一批地从 OpenResty 的 web service 接口取到 URL 任务,然后一个一个地在 Firefox 的 browser 组件里加载和分析,最后把分析到的结果一批一批地通过 OpenResty 提交之。\n\n

curl 预取爬虫集群与 Apache mod_proxy 集群\n\n
\n

该集群目前布署了 6 台双核的 redhat4 生产机。每台机器都安装了两个集群组件,一是预取器,一是 Apache mod_proxy. 预取器的作用是通过 curl (准确地说是 WWW::Curl 模块)将网页的 HTML 和 CSS 通过 mod_proxy 预取一遍,这样这些请求的结果就可以在 mod_proxy 中通过 mod_disk_cache 缓存住。于是当纯 Firefox 集群再通过 mod_proxy 去抓这些 URL 时,mod_proxy 就可以直接把缓存后的结果直接返回给 Firefox 了。\n\n

预取器和 Firefox 进程是同时工作的,但对于一个 URL 任务而言,只有通过预取器预取过之后,Firefox 进程才会进行处理。所以实际构成了一个两道工序的流水线。这种调度是由 OpenResty 集群来完成的。\n\n

预取器目前是以一个叫为 WWW::Prefetcher 的 Perl 模块的形式来实现的:\n\n

http://svn.openfoundry.org/xulapp/trunk/demo/ListHunter/misc/WWW-Prefetcher/\n\n

虽然 mod_cache 提供了许多选项,但其缓存行为还是比较遵守 RFC 的 cache 要求的。因此我对 mod_cache 模块进行了许多修改,使之可以无条件地缓存住请求过的所有网页,而不论其 URL 是否有 querystring,也不论其 response header 中的要求是什么。我们对最新的 httpd 2.2.11 的补丁如下:\n\n

http://agentzh.org/misc/httpd-2.2.11.patch.txt\n\n

特别地,mod_disk_cache 指向的不是磁盘目录,而是 RAM 中开辟的 tmpfs 分区。由于我们这 6 台机器都是很旧的 IDE 硬盘,因此直接用磁盘作 cache 存储时,高并发条件下,每台机器的 load 都在 20 以上,根本无法忍受。后来换为 tmpfs 结果 htcacheclean 工具之后,机器负载就降到 0.1 以下了。\n\n

OpenResty集群\n\n
\n

由于 OpenResty 的通用性,我们直接复用了同时服务于 yahoo.cn 和口碑网的那个生产集群,(3 台 FastCGI 前端机和1 台 PL/Proxy 机器),所以我就没有布署新的机器。在服务于 Firefox 集群的 OpenResty 接口中通过 View API 暴露了若干的 PostgreSQL 函数,以完成整个 List Hunter 集群的任务调度和结果汇总。目前的实现中,我们通过 Pg 的 sequence 摸拟了一种循环任务队列,并通过计数器完成流水线中两道工序之间的相对同步。\n\n

相关的 Pg 函数、sequence、以及索引的定义在这里:\n\n

http://svn.openfoundry.org/xulapp/trunk/demo/ListHunter/misc/init-db.sql\n\n

相关的 OpenResty 对象的定义则在这里:\n\n

http://svn.openfoundry.org/xulapp/trunk/demo/ListHunter/misc/init-resty.pl\n\n

\n\n

集群的性能

\n\n

集群目前每小时的产出稳定在 10 万网页以上,一天的产出在 240 万以上。Firefox 机器的负载在 3 左右,Proxy 的负载在 0.1 以下。\n\n

JS 基准测试显示 Firefox 3.1 加载一个页面的平均延时是 200 ~ 300 ms,机房间的网络延时在 10 ~ 20 ms(因为网页已被 mod_cache 缓存住,故无到外网的网络开销), List Hunter 插件的 DOM 分析代码的用时在 200 ~ 300 ms。其他 OpenResty 开销再计入,一个 Firefox 进程大约 1 sec 处理一个页面。\n\n

在 Linux 上一个 Firefox 进程的内存占用情况如下:\n\n

    VIRT 276m, RES 86m, SHR 34m
\n\n

已知瓶颈和缺陷

\n\n

当 OpenResty 中的 URL 任务表的行数超过 100 ~ 200 万时,调度查询容易超过 PL/Proxy 的 10 秒限制。因此,我们目前采取\"流式\"的任务导入和导出方式。通过 cronjob 定期地向库中导入任务,并同时把完成了的任务及时移出。\n\n

Apache 的 mod_proxy 在高并发条件下不够稳定,而且限于 Apache 自身的体系结构,无法实现 proxy pipelining. 因此计划在未来集群规模进一步扩大时,改用 Squid. 当然了,Squid 很可能也需要进行修改才能满足我们这里的强制缓存一段指定时间的需求。\n\n

同时,受限于 Apache mod_cache 后端的非分布式,代理服务器的调度是在 Firefox 进程和 curl 预取进程中完成的,导致前端代码比较复杂,还带来了代理服务器列表的定时同步问题。因此,未来可以考虑为 Apache mod_cache 或者 Squid 添加 memcached 缓存后端的支持。这样代理前端的多台服务器可以实现对集群内其他部件的\"透明化\"。\n\n

TODO

\n\n
    \n
  1. 换用 Squid + memcached 作为缓存用正向代理\n\n
  2. 通过 XULRunner 而非 firefox -chrome 方式运行 List Hunter 插件。(需要为我的 XUL::App 框架添加 XULRunner 支持)\n\n
\n\n

与相似产品的异同

\n\n

美国雅虎通过大量修改 Firefox 2 的 C++ 源代码,开发了叫为 HLFS 的爬虫集群,用于爬取 AJAX 网站的内容以及得到带有视觉信息的 DOM 树。他们将 Firefox 进程做成了 HTTP 代理的形式,对外部应用提供服务。\n\n

而我们的 List Hunter 集群中的 Firefox 进程则是高度自治的爬虫,它们自己从 OpenResty 中不断地批量取任务去完成。而外部应用则是批量地向 OpenResty 导入任务来让集群运转。由于 List Hunter 集群并没怎么修改 Firefox 的源代码,这使得我们可以很容易地与官方最新版本保持同步,从而第一时享受到官方优化带来的众多好处。\n\n

同时 List Hunter 集群本身是通用目的的,它可以作为各种 Firefox 插件的\"集群容器\"。换言之,这是一种将 Firefox 插件\"集群化\"的完整的框架。\n\n

由于 Firefox 插件开发本身已经通过我发布到 CPAN 的 XUL::App 框架得到了极大的简化,所以响应新的需求的成本是非常低的。\n\n

使用 Firefox 的利与弊

\n\n
\n
优点\n\n
\n

Firefox 是世界级的浏览器。作为最复杂功能最丰富的 Internet 客户端之一,我们将之作为爬虫可以享受到和最终用户一样的丰富功能,无论是 AJAX 还是视觉信息都不是问题。\n\n

Firefox 有基于 XUL 和 chrome JS 的灵活的插件机制,极易扩展。事实上,Firefox 主界面自身就是一个大插件。同时,Gecko 是基于 XPCOM 组件方式的,因此可以很容易地使用 C/C++/Java 等语言开发 XPCOM 组件,然后再用 JavaSscript 把它们粘合在一起。于是乎,JavaScript 成为了像 Perl 一样的胶水类语言。\n\n

运行于 Gecko 之上的插件 JavaScript 拥有最高权限,这种 JS 可以访问磁盘文件,可以访问系统环境变量,可以使用原生的 XmlHttpRequest 对象发出跨域 AJAX 请求。\n\n

Firefox 的性能随着新版本的发布总会有戏剧性的变化。Firefox 3.1 中的 Gecko 引擎的渲染速度就比 3.0 中的快了好几倍(根据 List Hunter 回归测试集的 benchmark 结果,前者为平均 60 ms,后者则长达 200+ ms)。(Firefox 3.1 中 TraceMonkey 的 JIT 支持倒并没有给 List Hunter 中的 JS 带来可测量的性能提升。)\n\n

纯 JS 写的 Firefox 插件可以在 Win32/Linux/Mac 多种操作系统上即装即用,所以方便和编辑及产品经理沟通行为细节,方便演示。如若计算过于复杂,亦可使用 C++ 语言改写插件中的计算密集的部分。\n\n

缺点\n\n
\n

Firefox 是高耦合的软件,这与 Google Chrome 及 Safari 浏览器的核心 Webkit 形成了鲜明对比。这意味着,我们比较难于对 Firefox 进行深层次的裁剪,无法轻易地免除一些比较大的功能部件,也很难将其中的某一个大部件剥出来单独使用(当然了,SpiderMonkey 是少数几个例外之一)。\n\n

\n\n

AUTHOR

\n\n

章亦春 (agentzh) <agentzh@yahoo.cn>\n\n

LICENSE

\n\n

Copyright (c) 2007-2008, Yahoo! China EEEE Works, Alibaba Inc. All rights reserved.\n\n

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n

\n\n

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


','agentzh','2008-12-25 08:53:27',6),(102,'The slides for my talk on Firefox cluster & vision-based web page extraction','I gave a talk at the Beijing Perl Mongers\' Feb Meeting last night. It was about my Firefox cluster and vision-based web page extraction technology. I had not expected to see so many people there. Wow. The talk was well received and people asked lots of interesting questions :)
\n
The slides can be freely downloaded from my site (open the ffcluster.xul file in the tarball via Firefox):

    http://agentzh.org/misc/slides/BJPW200902.tar.gz
\n
or browse directly online by Firefox:

    http://agentzh.org/misc/slides/BJPW200902/ffcluster.xul

Because it has many big pictures in it, it\'s recommended to download it to your local side first and display offline :)
\n\n
I\'ll also give this presentation again to those Ruby/Python/Java/C++ guys at Beijing OpenParty\'s Fox meeting:

    http://www.beijing-open-party.org/index.php/2009/02/beijing-open-party-2009-02-fox-event-begin.html
\n
As a side note: recently I\'m intrigued by Apache C hacking. My mod_libmemcached_cache\nis my first Apache module. And I\'d love to see more in the near future, such as\nmod_openresty ;)

Have fun!
','agentzh','2009-02-13 04:57:40',2),(103,'mod_libmemcached_cache is now opensourced :)','I\'ve opensourced my mod_libmemcached_cache project to GitHub.com with the permissions from my company:

    http://github.com/agentzh/mod-libmemcached-cache/tree/master
\n
It\'s a memcached storage provider for Apache2\'s mod_cache. In contrast to the mod_memcached_cache module on Google Code, we use the popular libmemcached library rather than apr-util\'s. Feel free to branch it and I\'m very willing to merge back any useful changes and I\'d love to send out commit bit as well :)
\n
Mind you, it\'s licensed under GPLv2. That\'s my company\'s decision, not me ;)
','agentzh','2009-02-26 04:11:47',4),(104,'My VDOM.pm & WebKit Cluster Talk at the April Meeting of Beijing Perl Workshop','Last night I gave a talk to our PerlChina folks at the April meeting in the Flow Bar. Here\'s the slides that I used:

The XUL format is the best among the three ;)

Just as the topic of the talk suggests, we\'re migrating from Firefox clusters to WebKit ones. I\'ll post more details here in the near future.

Enjoy!','agentzh','2009-04-10 03:52:47',3),(105,'SSH::Batch: Treating clusters as maths sets and intervals','System administration is also part of my $work. Playing with a (big) bunch of  machines without a handy tool is painful. So I refactored some of our old scripts and released SSH::Batch, a collection of useful parallel ssh scripts, to CPAN:
\n
    http://search.cpan.org/dist/SSH-Batch/

SSH::Batch allows you to name your clusters using variables and interval/set syntax in your ~/.fornodesrc config file. For instance:
\n
    $ cat ~/.fornodesrc
    A=foo[01-03].com bar.org
    B=bar.org baz[a-b,d,e-g].cn foo02.com
    C={A} * {B}
    D={A} - {B}
\n\n
where cluster C is the intersection set of cluster A and B while D is those machines in A but not in B.

And then you can query machine host list by using SSH::Batch\'s fornodes script:

   $ fornodes \'{C}\'
\n   bar.org
   foo02.com

   $ fornodes \'{D}\'
   foo01.com
   foo03.com

\nFurthermore, to run a command on a cluster at the concurrency level of 6:

   atnodes \'ls -lh\' \'{A} + {B}\' my.more.com -c 6

Or upload a local file to the remote cluster:
\n\n
  tonodes ~/my.tar.gz \'{A} / {B}\' :/tmp/

There\'s also a key2nodes script to push SSH public keys to remote machines ;)

A colleague in Alibaba B2B is already using it. And one of my teammates is going to use it to operate on those thousands of machines in our instance of the YST (Yahoo! Search Technology) cluster and I\'m ready to receive more feedback from him ;)
\n
Have fun :)
','agentzh','2009-04-23 02:37:51',1),(106,'Text::SmartLinks: The Perl 6 love for Perl 5','I\'m so glad to find this blog post while browsing the Iron Man planet:

   http://szabgab.com/blog/2009/04/1240827553.html
\n
Three years ago, I wrote the smartlinks.pl script to integrate the Pugs test suite with the Perl 6 Synopses documentation. Gábor Szabó now has done an excellent job in refactoring and packaging the tool into a general-purpose CPAN module. It had been my TODO until I was caught by accumulated schoolwork :P
\n
Enjoy his (well, also our) Text::SmartLinks module!

   http://search.cpan.org/perldoc?Text::SmartLinks
','agentzh','2009-04-28 06:07:00',3),(107,'Mailing list for OpenResty','After releasing several new releases of OpenResty.pm to CPAN, I created a mailing list for OpenResty users/developers on Google Groups:

    http://groups.google.com/group/openresty?hl=en
\n
This is for both OpenResty.pm and mod_openresty. You\'re very welcome to join us there ;) There\'s also a #openresty on freenode but it\'s been very quiet :P','agentzh','2009-05-11 07:28:23',0),(108,'OpenResty.pm has been moved to GitHub','As some of you may have already noticed, I\'ve moved the source repository of OpenResty.pm from the good old OpenFoundry to GitHub:

    http://github.com/agentzh/openresty/tree/master
\n\n
Feel free to branch it or ask me for a commit bit if you don\'t have one ;)

I\'ll destroy the stuffs in the old \"openapi\" repository on openfoundry and leave a note there to avoid potential confusion.\n','agentzh','2009-05-11 08:03:24',2),(109,'I\'ll talk in the upcoming Beijing Perl Workshop 2009 event','I\'ve submitted 3 talk proposals to this year\'s upcoming Beijing Perl Workshop conference scheduled at Sep 19. I\'ll publish my slides for my talks later here for your preview :)

The 3 talks are
  1. \nWonders of Perl automated testing
  2. Inventing mini languages in Perl
  3. Web Scraping based on Perl + WebKit + VDOM
If you feel like attending the conference, please register in the conference site below:
\n
   http://conference.perlchina.org/bjpw2009/

Don\'t forget to specify a T-shirt size in your profile setting there so that we can prepare a T-shirt for you in this event (well, it\'s for free!).
\n
See you there ;)','agentzh','2009-09-02 09:32:02',0),(110,'Our queue-size-aware version of memcacheq','Xunxin++ and I have been working on a fork of memcacheq (originally just within the company), adding support for queue length constraint.

In our scenario, a pipelined webpage information extraction cluster based on apple\'s WebKit core, it\'s important to limit the queue\'s length and to make the queue \"inform\" the queue item producers by some way in case the queue is full.
\n
We\'re not sure if it\'s worth merging back to the mainstream version because this new addition adds some cost (though the cost is low).

Here goes the project page on GitHub, with more explanation of the details (I won\'t repeat them here ;)):
\n
  http://github.com/agentzh/memcacheq/tree/master

The newly added code is also licensed under the same license as the mainstream memcacheq.

Enjoy :)','agentzh','2009-09-03 10:21:28',0),(111,'Slides for my VDOM + WebKit talk','I gave a presentation on VDOM + WebKit to the Taobao.com Search Frontend Team this morning. The slides are based on my talk in April\'s Beijing Perl Workshop, but with notable updates to reflect recent changes in the last few months:
\n
   http://agentzh.org/misc/slides/taobao-fe/vdomwebkit.xul   (Firefox required to open this link)

Be patient when it\'s downloading big images, or you can download the whole tarball to your local side, unpack the package, open the vdomwebkit.xul in it, and browse the slides locally:
\n
   http://agentzh.org/misc/slides/taobao-fe.tar.gz

Recent major development regarding our browser-based web scraping clusters are:
I\'ll use almost the same slides for my 3rd (lightening) talk at the annual Beijing Perl Workshop conference weeks later :)','agentzh','2009-09-04 08:05:49',0),(112,'A plan for nginx-openresty','Now that I\'ve joined Taobao.com\'s SDS department and will be able to work on OpenResty in a full time fashion, I\'ve just worked out a (somewhat) detailed plan for the next generation of the OpenResty server. Well, sorry, this draft is in Chinese since my $manager reads Chinese better:
\n\n
    http://www.pgsqldb.org/mwiki/index.php/Nginx_openresty_plan  (still being actively updated)

After talking with my friend and colleague chaoslawful++ for possible designs of a high performance implementation of the OpenResty server, we finally decided to rewrite OpenResty.pm in pure C and in the form of an nginx module.
\n\n
Here\'s some highlights of the Chinese project plan given above:
\n\n\nI\'ll create a git repository on GitHub for the nginx-openresty\'s development. Participation will always be appreciated :) I\'ll keep you posted.
\n\n
Update: Special thanks go to kindy++ for his detailed review of the nginx-openresty-plan document and helpful suggestions :)
','agentzh','2009-09-14 10:32:12',0),(113,'Slides for my perl testing & VDOM.pm talks in Beijing Perl Workshop 2009','I really enjoyed the talks in BJPW2009. Here\'s the slides for my two talks in this conference:

Hopefully you\'ll find them interesting ;)','agentzh','2009-09-22 08:10:18',0),(114,'Hacking on the Nginx echo module','Over the recent weeks, I\'ve been reading a lot of Nginx and its modules\' C source code and it\'s really enjoyable. I\'ve got lots of good ideas in implementing the next generation of OpenResty server based on the Nginx architecture. Well, it\'s currently my full-time $work anyway.
\n
For the sake of testing other modules, experimenting the Nginx internals, and for fun, I\'ve started my first Nginx module named \"echo\":

   http://github.com/agentzh/echo-nginx-module
\n
It\'s already quite usable, and it also has a declarative test suite based on Perl\'s Test::Base. At the moment, LWP is used for simplicity and it\'s rather weak in testing streaming behavior of Nginx (I\'m using \"curl\" to test these aspects manually for now). I\'m considering coding up my own Perl HTTP client library based on IO::Select and IO::Socket (there might be already one around?).
\n
Along the way, I\'m intentionally heavily commenting my C source in this \"echo\" module in the hope that newcomers would find it a \"live tutorial\" or something like that. I\'ll write more about the details here in subsequent posts. After all, it\'s able to do a lot more thingies other than just \"echo\" stuffs directly, such as sleeping and flushing output buffer. And it will be capable of outputing subrequests\' responses as well.
\n
Happy hacking Nginx C modules and stay tuned!

Update: I\'ve also added a wiki page for it: http://wiki.nginx.org/NginxHttpEchoModule','agentzh','2009-10-15 03:01:00',0),(115,'The \"chunkin\" module: Experimental chunked input support for Nginx','Pushed by those cutting-edge users on the Nginx mailing list, I\'ve quickly worked out the \"chunkin\" module which adds HTTP 1.1 chunked input support for Nginx without the need of patching the core:

    http://github.com/agentzh/chunkin-nginx-module
\n
This module registers an access-phase handler that will eagerly read and decode incoming request bodies when a \"Transfer-Encoding: chunked\" header triggers a 411 error page in Nginx (hey, that\'s what you have to pay for avoiding patching the core ;)). For requests that are not in the \"chunked\" transfer encoding, this module is a \"no-op\".
\n
To enable the magic, just turn on the \"chunkin\" config option like this:

    chunkin on;
    location /foo { ... }
    ....

No other modification is required in your nginx.conf file. (The \"chunkin\" directive is not allowed in the location block BTW.)
\n\n
This module is still considered highly experimental and there must be some serious bugs lurking somewhere. But you\'re encouraged to play and test it in your non-production environment and report any quirks to me :)
\n
Efforts have been made to reduce data copying and dynamic memory allocation, thus unfortunately raising the risk of potential buffer handling bugs caused by premature optimizations :P

\nThis module is not supposed to be merged into the Nginx core because I\'ve used Ragel to generate the chunked encoding parser for joy :)

The following Nginx versions have been successfully tested by this module\'s (very limited) test suite:
\n
   0.8.0 ~ 0.8.24
   0.7.21 ~ 0.7.63

The test suite definitely needs more test cases and the code is hacky in various places. If you\'re willing to contribute, feel free to ask me for a commit bit in a private email :)

Update: I\'ve also added a wiki page for it: http://wiki.nginx.org/NginxHttpChunkinModule','agentzh','2009-11-15 10:25:00',0),(116,'The \"headers more\" module: scripting input and output filters in your Nginx config file','I\'ve been working madly on the \"headers more\" module:

   http://github.com/agentzh/headers-more-nginx-module

And got everything that I want working now. It also has a nice wiki page (which also has brief explanation of the underlying implementation):
\n
   http://wiki.nginx.org/NginxHttpHeadersMoreModule

Our buzzword is that it can rewrite the \"Server\" output header dynamically! See this:
\n
   location /foo {
        more_set_headers   \"Server: $arg_server\";
   }


Then GET /foo?server=Foo will get a response with the \"Server: Foo\" header set ;)

Input headers can be trivially rewritten as well, including the \"Host\" header:
\n\n
    more_set_input_headers   \"Host: some-other-host\";

Well, the full practical power of this module is out of my current imagination. If you have some crazy uses, please drop me a line ;)

Happy Nginx hacking!','agentzh','2009-11-18 10:09:00',0),(117,'Major updates to ngx_chunkin: lots of bug fixes and beginning of keep-alive support','Prompted by the bug reports from one of my users, the J guy, I\'ve made lots of improvements into the ngx_chunkin module:

  http://wiki.nginx.org/NginxHttpChunkinModule
\n\n
Please see the change log for the new v0.07 release:

  http://wiki.nginx.org/NginxHttpChunkinModule#v0.07

It\'s worth special mentioning that it\'s really a shame that older versions do not work with chunked data with non-ascii octets. This was caused by incorrect alphtype definition in my Ragel spec. Thanks J for reporting it.
\n\n
Also, I\'ve introduced a new directive spelled \"chunkin_keepalive\", which will make ngx_chunkin work in the non-pipelined keep-alive context. Preliminary support for HTTP 1.1 pipelining is also introduced but has not been tested very well. (For technical details, see this nginx-devel thread )
\n\n
As before, this module is still considered experimental but you\'re encouraged to try it out and report any issues that you encounter. I promise I\'ll fix bugs as fast as I can :)

Happy chunking nginx!','agentzh','2009-12-04 10:14:00',0),(118,'ngx_memc: an extended version of ngx_memcached that supports set, add, delete, and many more commands','I\'m happy to announce the first release of the ngx_memc module, an extended version of the standard \"memcached\" module that supports almost the whole memcached TCP protocol:

   http://wiki.nginx.org/NginxHttpMemcModule
\n
I know the state of the art in the nginx community is to manipulate contents in memcached from within a backend (fastcgi) application while just use the nginx memcached module as a frontend that simply \"serves\" the content to the outside world. But read on...
\n
Our motivation here, however, is to build an efficient and flexible memcached TCP client component for nginx itself  so that we can reuse it in an non-blocking way by means of an nginx subrequest or a \"fakerequest\" [1].
\n
As always, special thanks go to Igor Sysoev for all his heavy lifting work already done in ngx_http_upstream and ngx_http_memcached_module in the nginx core.

At last but not least, thanks my current employer, Taobao.com, for allowing me to opensource this work, as well as other nginx modules I have already announced or am going to announce here ;)
\n
Enjoy!

References
[1] See http://github.com/srlindsay/nginx-independent-subrequest','agentzh','2009-12-06 10:27:00',0),(119,'Test::Nginx::LWP and Test::Nginx::Socket are now on CPAN','I\'ve just released the Perl modules Test::Nginx::LWP and Test::Nginx::Socket as a single Test-Nginx distribution to CPAN (it may still require some more time to reach the CPAN mirror near you):

   http://search.cpan.org/perldoc?Test::Nginx::LWP
\n
   http://search.cpan.org/perldoc?Test::Nginx::Socket

The latter is still a hack using while (1) with non-blocking sysread/syswrite. I\'ll rewrite it using IO::Select at some point in the future.
\n
These two Test::Base-style modules are driving the test suites of the following Nginx C modules:
ngx_echo
\n

http://wiki.nginx.org/NginxHttpEchoModule

\n\n
ngx_headers_more
\n\n

http://wiki.nginx.org/NginxHttpHeadersMoreModule

\n\n
ngx_chunkin
\n

http://wiki.nginx.org/NginxHttpChunkinModule

\n\n
ngx_memc
\n

http://wiki.nginx.org/NginxHttpMemcModule

\n

And our ngx_drizzle module, started by my friend and colleague, chaoslawful++, will soon be on that list as well ;)

Happy testing nginx modules with Perl!','agentzh','2009-12-08 05:36:00',0); /*!40000 ALTER TABLE `posts` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2010-03-19 13:51:56