-- 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,'完美之夜,完美之旅','
我在网上经常看到程序员们(当然还有许多非程序员)在他们的电子邮件、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
我们看到,英语中的不少词汇也是很值得细细品味的。呵呵
今天下午,我继续在母亲办公室中抄写 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::Rule 和 Pugs::Compiler::Perl6 以及 clkao 的 Data::Bind 和 Sub::Multi, 当然还有 Stevan 的 Moose 和 Ingy 的 Module::Compile,从而知晓他们是如何实现的. 最后,我才可能真正参与到 v6-alpha 的开发工作中去.
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!
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! :)
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?
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!
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. :)
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. :)
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!
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?
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? :)
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.)
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. :)
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. :)
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.
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 &
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? ;-)
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. :(
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...
huh! google++
i will definitely look into its shiny source code search engine the other day. thanks for the info. :)
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! ;)
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.
Moose. will you come to my class this friday evening? :)
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...
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.)
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.
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. :(
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? ;-)
这几天每天都要上讲台,而且一上就是 2 节,感觉好累哦。 不过上课时也时常有灵感出现,把平时很多只能意会的东西概念化、理论化, 从而也就可以很好地传达给我们学院的同学们了。
另外就是做了许多幻灯片,它们像是连环画,又像是小小说,都很精致, 都很漂亮。它们是我从高一开始积累的编程思想的一些汇总与整理,真是有趣的很哦~ 我的朋友们上过我的课后都说收获很大,呵呵, 我觉得再没有什么比这个更让人激动的了。耶!
……谢谢。明天下午还要给我们学院的研究生做一次讲座。振奋哦~~~哈哈!:D
我昨晚的课上得还行么?是不是太悠闲,节奏太缓慢了?
> 呵呵,虽然这会才看到你的消息,但我的思维却始终没有离开你。我想你的课让
> 我对自己后面的路该如何走,有了全新的认识,就像赵鹏说的有种豁然开朗的感
> 觉。
如此之高的评价我真是担当不起呢。看来我算是遇到知音了。 我最期待有人能对我说:“Oh, great! that\'s really important!”
哈!我想人生最幸福的事莫过于此!
> 悠闲嘛,开始是觉得有一点慢的感觉,没那么带劲儿,下课了,我还和鹏说,
> 你不知道他充满激情的讲话是多么的有煽动性...后来你就进入状态了,特棒。
> 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. ;)
> 真的吗?呵呵,好,我会一直走下去的。现在我真的喜欢上编程了,我对优秀程序员
> 所具有的品行狂热的向往。谢谢你的鼓励与帮助。耶!
> 用 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. :)
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. ;-)
Take care. translating may drive you mad some day. just have appropriate amount of fun, dude!
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. ;-)
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
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.
电子政务老师过分……居然在当中打断我……我才讲到第 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
前些日子我本打算为本周的专家系统课程制做两组幻灯片。一组是《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 的无限循环的困挠中解放出来,从而将主要力量放在知识库本身的表达以及推理过程的自动化解释的核心问题上,而不是时时刻刻去关心像消除左递归,避免规则回路这样的枯燥而琐碎的事情。耶~~~
我们说的学习,其实并不是学习,只是叫做学习。
我们说的课业负担重,其实并不是课业负担重,只是叫做课业负担重。
我们说的烦恼多,其实并不是烦恼多,只是叫做烦恼多。
我们说的世间罪恶,其实并不是世间罪恶,只是叫做世间罪恶。
我们说的聪明智慧,其实并不是聪明智慧,只是叫做聪明智慧。
我们说的成就高,其实并不是成就高,只是叫做成就高。
我们说的美丽,其实不是美丽,只是叫做美丽。
为什么呢?我们看到的都只是事物的表相而已,不是真相。美好与丑陋,烦恼与自在,幸福与痛苦,都只在我们的一念之间。
是啊,就是一念之间,就是如此容易。
即便我们拥有再多的财富,取得再大的成就,学习再多的知识,也可能不及一个普通的乡村农夫来得快活自在,来得幸福安乐。 因为幸福只是一种感受,只是一种心理体验。掌控了自己意念,其实也就掌控了自己的幸福。什么成就啦,财富啦,地位啦,学问啦,都不过是过眼云烟,换不来真正的快乐。
公平是什么?我们拥有纯洁的心地,清净的生活,善良的灵魂,这便是上天对我们最大的恩赐,对我们来说,也就是最大的公平。
现代人生活得太苦了。虽然,如今的物质文明超越了过去一切世代的总和,但人们其实还不及过去的人们生活得幸福。巨大的精神压力,飞快的生活节奏,膨胀的贪著欲望, 缠缚身心的烦恼……这些都将唾手可得的幸福赶跑了。
身体上的苦真算不上什么,精神上的苦楚,才是最大的悲哀。自然界中的其他物种,其实大部分时间都饱受饥饿之苦,但我们又不得不羡慕它们的快活自在。
宇宙中最捉摸不透的便是我们的心了。它总会生出如此之多的念头,如此之多的妄想,如此之多的烦恼。但是我们却无法得到自己过去的心,自己现在的心,和自己未来的心。
这听起来似乎有些不可思议。但事实上确是极为明显的。当我们觉察到自己心中的一个念头的瞬间,其实这个念头已经在心中灭去了。“贼后兴兵”,了无所得。因此,我们一定要处处留心,时时在意,以避免我们的心随着烦恼而行。
随顺烦恼,便是自寻烦恼。烦恼本来是没有的,烦恼是我们自己的心造出来的。
记得高中的时候,我向一个同学抱怨说,“我怎么会这么痛苦呢?”对方的回答让我惊愕: “其实人大多数的痛苦都是自己造成的。”我如今才明白了她的意思。
仔细地观察,痛苦确确实实都是自己“伪造”出来的。没有人,没有事,能真正让我们痛苦,只有我们自己才会让自己痛苦。因为痛苦本来就是自己的,痛苦本来就是一种内心感受,痛苦本来就是没有的。
而我呢?一直以来,总是在诅咒教材,诅咒学校,诅咒教育制度,诅咒身边的环境,诅咒除了自己以外一切可以诅咒的东西。结果呢?随顺了烦恼,增长了烦恼。于是成了自己和自己过不去,岂不贻笑大方?而所谓的“自己”,其实也是没有的。
Overview - VRG 专家系统概览
章亦春 <agentzh at gmail dot com>
计算机科学与通信工程学院 江苏大学
Maintainer: Agent Zhang <agentzh at gmail dot com>
Date: 24 Dec 2006
Last Modified: 24 Dec 2006
Version: 0.01
VRG 是一个立体几何定性问题证明系统。比如下面这样的问题都可以使用VRG 进行证明:
若直线 l // 平面 alpha, 则 l 平行于 alpha 内的所有直线吗?
设 alpha、beta 表示平面,a、b 表示直线,则 a // alpha 的一个充分条件是不是 alpha 垂直于 beta, 且 a 垂直于 beta ?
判断平行于同一个平面的两个平面是否平行
一个平面内的两相交直线与另一个平面内的两条相交直线分别平行,则这两个平面平行吗?
若平面 alpha 垂直于 平面 beta, 直线 n 在 alpha 上,直线 m 在 beta 上,m 垂直于 n, 则同时有 n 垂直于 beta 和 m 垂直于 alpha 成立吗?
PA、PO 分别是平面 alpha 的垂线、斜线,AO 是 PO 在平面 alpha 内的射影,且 a 在 alpha 上,a 垂直于 AO,则 a 垂直于 PQ.
上述问题都引用自 VRG 的自动化测试台的用例。VRG 可以对任一个用户问题作出 2 种基本判断:Yes (即可以证明)和 No(即无法确定),并且给出提示信息和证明过程。
用户通过一种类似几何语言的“用户语言”向 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
作为文件扩展名。然后使用下面的命令行进行求解:
$ 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 在内部使用 AT&T 的自由软件库 Graphviz 来生成所有的有向图。
对于多证明目标的题目,VRG 在判断不成立时,会显式地指出具体是哪些目标是未决的。而对于题目自身的条件是彼此冲突的,比如两个几何元素既平行又垂直了,VRG 也会显式地指出冲突所涉及的细节(比如哪两个元素冲突了,是哪两个关系冲突了)。
我已使用高中数学教材中所有的公理、定义、定理和推论对 VRG 进行了测试(在 VRG的测试集中即对应 sanity.t 文件),此外,我还使用高三时候积累的所有相关的高考复习题对 VRG 进行了测试(在测试集中即对应 senior.t 文件)。
对于涉及定量关系的几何问题是无法用 VRG 进行求解的,比如角度计算问题、线段长度之类。VRG 是定性求解系统,它只能处理“垂直”、“平行”、“线在面上”这样的定性关系。
VRG 的知识库全部是使用我自主设计和实现的通用目的专家系统编程语言 XClips 进行描述的,在 VRG 源代码目录中,对应 knowledge/*.xclp 这些文件。
由于使用了可扩展的 XClips 语言,VRG 的知识库非常简洁,非常清晰。
VRG 在底层使用了美国航空航天局约翰逊太空中心开发的正向链推理机 CLIPS. 事实上,VRG 系统与 CLIPS 的交互全部是通过 XClips 系统来完成的。XClips 正是建筑在CLIPS 之上的。
值得一提的是,CLIPS 是发布在公共域(public domain)中的,因此可以将之用于任何目的。
VRG 的构件和依赖项都是高度可移植的,包括 CLIPS, perl, Graphviz, 因此可以不加修改地运行在包括 Windows, Linux, FreeBSD, Solaris 在内的多种操作系统上。目前,我只在 Windows XP 和 Windows 2000 上进行过测试。
您总是可以从下面的 SVN 仓库获得 VRG 最新版本的源代码:
http://svn.berlios.de/svnroot/repos/unisimu/VRG
如果您想帮助完善 VRG 系统,请发送电子邮件告知作者。谢谢!
Copyright 2006 by Agent Zhang (章亦春). All rights reserved.
KB - VRG 知识库简介
Agent Zhang (章亦春) <agentzh at gmail dot com>
Maintainer: Agent Zhang <agentzh at gmail dot com>
Date: 26 Dec 2006
Last Modified: 26 Dec 2006
Version: 0.01
这篇文档将简要地介绍一下 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
之类;否则为常量,如beta
和 l
.
变量一般用于规则,而常量一般出现在事实中。
这些其实都是 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 不重合”这样的断言,同时也会增加了用户输入已知条件的负担,增加了因人为的已知条件不充足而无法求证的可能性。
知识库从物理上分为 4 个 CLIPS 模块(module),亦对应推理流程的 4 大阶段:
Vectorize 模块是由 preprocess.xclp 和 vectorize.xclp 这两个文件实现的。该模块负责完成从几何空间内的线线关系、线面关系、面面关系及其他复杂关系到向量空间内的向量关系的转换。
Eval 模块是由 vector-eval.xclp 文件实现。该模块负责在向量空间内执行推理,从已知的向量关系不断推出新的向量关系。
此模块由 anti-vectorize.xclp 文件实现。它负责执行 Vectorize 模块的“逆操作”,即将新的向量关系还原为几何空间中的线线关系、线面关系和面面关系。
GoalMatch 模块完成用户给定的证明目标在所有已知事实中的匹配及相关的解释工作。
当推理机的焦点处于某个模块时,只有属于该模块的规则和事实才能被参与推理。
有关立几空间的事实由 Vectorize 模块,AntiVectorize,和 GoalMatch 模块共享;有关向量空间的事实由 Vectorize 模块,Eval 模块,和 AntiVectorize 模块共享。
推理机运行的具体流程如下
用户输入的已知条件所对应的“初始事实”被导入到 Vectorize 模块。
推理机焦点 (focus) 从默认模块 MAIN 切换至 Vectorize 模块,执行立几空间内的关系演算和“向量化”操作。
上一步运行完毕后,再将焦点移至 Eval 模块,执行向量空间内的关系演算,推出更多的向量关系。
将焦点移至 AntiVectorize 模块,对所有新的向量关系执行反向量化,还原出立几空间中的语义。
焦点被切换至 GoalMatch 模块,使用用户给定的证明目标对所有已知事实进行匹配,并生成解释和评价。
知识库由下列 XClips 源文件构成:
该文件定义了知识库中所使用的特殊的运算符,例如前缀 \\
和中缀 //
.该文件为知识库中所有其他 .xclp 文件所包含。详情请参与 记法约定.
例如前缀 \\
的定义如下:
prefix:<\\> line
而中缀 //
的定义如下:
infix:<//> parallel
该文件定义了 VRG 的“预处理规则”。这些规则的主要工作是在立几空间内部进行关系演算,其目的在于将 project(投影)和 meet(相交)这样的复杂关系转换为平行、垂直之类的简单关系,同时为某些基本关系生成“同构异形体”,以简化后续的匹配工作。
具体说来,此文件包含下列几条规则:
当两个平面 alpha
和 beta
相交于直线 l
时,则 alpha
与 beta
不平行,并且 l
同时在 alpha
和 beta
上.
#?alpha, #?beta, meet(?alpha, ?beta, ?l)
=> ?alpha [~//] ?beta, ?l [on] ?alpha, ?l [on] ?beta.
这儿的前缀问号(?)表示为变量,而非常量。
当两条直线 l
和 m
相交于一点时,则存在一个平面 alpha
使得 l
和 m
都在 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) l
与 alpha
斜交,(2) l
在 theta
上, (3) theta
与 alpha
相交于 m
, 并且(4) theta
与 alpha
垂直:
\\?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, 则 l
与 alpha
亦满足(交换律):
#?alpha, \\?l, ?alpha [?R] ?l => ?l [?R] ?alpha.
本文件包含了执行“向量化”步骤的所有规则。
若直线 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
, 则在向量空间中,alpha
与 beta
亦满足关系 R
.
#?alpha, #?beta, ?alpha [?R] ?beta => ?alpha <?R> ?beta.
此文件中的规则都是向量空间内的“求解规则”,用于从已知的向量关系推出全新的向量关系。这些规则是整个 VRG 系统知识的核心。
已知 a
, b
, c
都是向量,若 a
// b
, b
与 c
满足关系 R
,且 c
不同于 a
,则 a
与 c
亦满足关系 R
.
?a <//> ?b, ?b <?R> ?c, ?a \\= ?c
=> ?a <?R> ?c.
这一条规则的意义是,向量间的关系可以通过“平行”关系进行传递。在立体几何空间中,许多定理、定义和推论都对应于这一条规则。
比如高中数学课本``立体几何\'\'一章有下列公理和定理是本条向量规则在立几语义中特殊的表现形式:
我们看到,一条向量化规则对应到如此之多的立几定理和公理。从这个意义上讲,向量化方法有效地揭示出立体关系的本质。
已知 a
和 b
都是向量,若 a
垂直于向量 b
, 或者 a
与 b
斜交,则 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
,则 b
与 a
亦满足关系 R
.
?a <?R> ?b => ?b <?R> ?a.
这条规则揭示的是向量关系满足交换律。
本文件中的几条规则执行“逆向量化”操作,正好是 vectorize.xclp 中规则的“反函数”,比如逆向量化规则
\\?l, #?alpha, ?l <T> ?alpha => ?l [~T] ?alpha, ?l [~X] ?alpha.
的含义是:如果在向量空间中,向量 l
垂直于向量 alpha
,且在立体几何空间中,l
是直线,alpha
是平面,则有在立几空间中,直线 l
不垂直于平面 alpha
,且直线 l
不斜交于平面 alpha
.
本文件中的规则使用用户给定的证明目标对已得到的事实进行匹配。
若用户求证 a
与 b
在立几空间存在关系 R
, 且事实库中确实存在该事实,则生成 solved 事实指示目标已解决。
?a *[?R] ?b, ?a [?R] ?b
=> solved(space-relation, ?R, ?a, ?b).
若用户求证 a
与 b
在立几空间存在关系 R
,且事实库中不存在该事实,则生成 pending 事实以指示该目标“未决”。
?a *[?R] ?b, ~exists(?a [?R] ?b)
=> pending(space-relation, ?R, ?a, ?b).
若用户给定的有关 a
和 b
的一求证目标未决,且事实库中存在 a
与 b
之间确定的某种关系,则生成 hint 事实,以提示用户。
pending(space-relation, ?, ?a, ?b), ?a [?R] ?b
=> hint(space-relation, ?R, ?a, ?b).
除了上述规则之外,知识库中还收录了许多自检测规则,用于检测事实库内部的完整性。这些设施可以有效地检测出用户给定事实之间的冲突、知识库规则之间的冲突,以及其他形式的 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 (SVN) 仓库取得最新版本的 VRG 知识库:
https://svn.berlios.de/svnroot/repos/unisimu/VRG/knowledge
在 line
和 plane
谓词的基础上引入 point
谓词用于显式地声明几何点。
虽然当前知识库已通过使用隐式的点对象来处理类似“两线交于一点”的条件,但显式的点对象无疑会提高规则的可读性和知识库的可扩展性。
Copyright 2006 by Agent Zhang (章亦春). All rights reserved.
在这个应用中,我需要一个 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)。
在 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 了。
该项目将由下列三部分组成:
该模块将 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 实现不会在 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::DOM 和全新的 Makefile::Parser,同时保持向后兼容。
该模块就是进行不同格式 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 之间的编译工作……
第一阶段的工作将集中在 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::Run3 和 Test::Base 的 GNU make 测试集。
pgmake 和使用了 IPC::Run3 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Gmake 部分的原型(prototype)。
该分支从 Makefile::DOM 0.1.x 起启用。
/branches/nmake
用于开发 Perl 版本的 NMAKE 实现,pnmake,并将包含基于 IPC::Run3 和 Test::Base 的 NMAKE 测试集。测试台框架将复用 /branches/gmake 中的 GNU make 测试台脚手架。
类似地,pnmake 和基于 IPC 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Nmake 部分的原型。
该分支从 Makefile::DOM 0.3.x 起启用。
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::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
及其以上版本。
该模块将支持 GNU make 和 MS NMAKE 两种格式的 Makefile 作为输入;输出将支持 Java 的 ANT,CPAN 上的 PBS,以及 GNU make 和 NMAKE 自身。该模块在早期将从 Makefile::Parser 产生的 AST 发射目标代码。该做法实现起来非常简单,虽然无法得到很``地道\'\'的翻译,但却是``足够好的\'\'。
有关该模块的计划目前无法确定下来,因为它强烈地依赖前几个模块的成果和经验。
从现在起,每周三我都将为毕业设计拟定下一周的工作计划,同时对前一周的相关工作进行总结。
先后发布了 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 文档的骨架。
将已有的基于 Test::Base 的 GNU make 测试集加入到了 Makefile::DOM 模块的 SVN 仓库 的 gmake 分支 ,并进行简单的重构:
放弃了整合 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 这两个模块的开发工作。
过去的这一周大部分时间用来找工作了,呵呵。好在工作比想象中的好找, 所以也没有花费我太多的精力。
这些日子在毕业设计项目上取得了以下进展:
总的 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_scope
和 leave_scope
方法,等等。
它是 AST 中规则节点的基类,包含 normal_prereqs
,order_prereqs
,commands
,colon
这些属性。
该类表示非隐式规则以及隐式规则“应用”之后的形式,从 Makefile::AST::Rule::Base 继承,并新增了 target
和 other_targets
属性。
该类表示 AST 中的隐式规则节点,从 Makefile::AST::Rule::Base 继承,并新增了 targets
,match_anything
,is_terminal
等属性。
该类封装了含 %
的文件模式的匹配与 stem 替换算法。
它表示 AST 中的变量节点,包含 name
,value
,flavor
,origin
等属性。
make -qp
命令生成的 GNU make database,并构造出对应的 Makefile::AST 对象(即 GNU Make AST).有趣的是,GNU make 生成的 database 报表也是完全合法的 Makefile 格式,而且只使用最最基本的语法结构,因此 Makefile::Parser::GmakeDB 直接使用 MDOM::Document::Gmake 进行解析。
值得一提的是,包括显隐式规则的应用在内的拓朴图的构建算法其实大部分实现在了 Makefile::AST 及其子节点类中了。
`make -pq`
,Makefile::Parser::GmakeDB,和 Makefile::AST::Evaluator 三者串联了起来,组装成了一个完整的 make
工具,即 pgmake-db.该工具可以运行基于 IPC 的 GNU make 测试集。目前已通过了 sanity/func-refs.t 测试文件中 95% 以上的测试用例。
下一周可能没有太多时间用来 hack 了,因为需要应付学校的结欠考试。但是顺着上一周的工作继续往下走应该是很容易的。我立刻能想到的工作有:
$ 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 来看电影了,呵呵。
没想到我发布到 CPAN 的 UML::Class::Simple 模块居然得到了用户如此之好的反馈,开心哦:
http://cpanratings.perl.org/dist/UML-Class-Simple
通过 Google ,我又在世界上找到了两个 UML::Class::Simple 用户:
[Perl] UMLクラス図の自動生成(UML::Class::Simple)
http://usuilog.blogspot.com/2006/12/perlumlumlclasssimple.html
这位日本的程序员还在他的博客里为我的这个模块专门写了一篇 review 耶,感动死了;虽然他对我的东东的评价并不是太好。 我在他的文章末尾留了言。
[Perl] UML::Class::Simple & Catalyst
http://f.hatena.ne.jp/tomyhero/20061107093526
这位仁兄用我的模块为 Perl 中非常流行的 Web 应用程序框架 Catalyst 绘制出了 UML 类图,并贴在了网上。 哈哈,好棒哦。
我一定要继续努力,开发出更多更好的 CPAN 模块!耶 !:D
今天是 唐凤 的生日,真的很开心啊,祝 Audrey 生日快乐!
根据 Gaal 的提议 , 这几日我成功地在 feather 服务器上建立了 Pugs 的自动化 smoke 设施, 算作是 给唐凤的生日礼物 。 :D
现在 feather 上的 cron 程序每隔 24 个小时就会自动运行最新版本的 Pugs 测试集,并生成包含“灵巧链接”的 Perl 6 Synopses 文档:
比如其中的 S04:
你在其中会看到,我的 smartlinks.pl 程序会将一组一组的测试插入到文档的对应位置上,并根据 Smoke 生成的测试报表,用 √
和 ×
在对应的行上,标记每一个特定的测试。
唐凤的 Pugs 博客上的几篇文章就是介绍这种 smartlinking 技术的:
Integrating the Pugs test suite into the Synopses
Check smoke results while reading Synopses
The Benefits of Smart Linking
前两篇是我写的,第三篇是 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!
更多个人信息
我们的国际 Perl 博客
这里是我贡献 Perl 模块的地方
agentzh@yahoo.cn
我过去的演讲所使用的幻灯片
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: 我
结论
我徒弟实在是太有个性啦!
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 能够转危为安,早日康复!
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?
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 格式
短期目标希望能在答辩之前完成,并写进我的毕业论文。长期目标目前看来只能放到毕业之后继续了,呵呵。
唉……这学期大部分时间都放在考试复习、找工作和其他的事情上了……所以现在时间紧得不得了。
一是 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 的同时亦能发表博客文章,实在太帅,呵呵。
http://cpants.perl.org/highscores/many
而且已经在 chromatic 的前面了,呵呵。
当然了,这既不是 quantity 也不是真正意义上的 quality,而是 kwalitee,呵呵。
以后有时间一定把我那些模块中余下的红色区域修复:
http://cpants.perl.org/author/AGENT
这样我就可以达到 100 分了,呵呵。
* 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 模块的时候了!耶!
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标准模块,比如 unlink和Cwd. 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/
呵呵 :)
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 ;)
http://svn.openfoundry.org/makefileparser/branches/gmake-db/script/makesimple
该程序能将非常复杂的 GNU makefile 转换成最最基本的形式,即所谓的\"简单makefile\"。
\"简单makefile\"中只有单目标的显式规则,没有变量赋值,没有变量引用,没有条件指令,没有模式规则,没有所有其他看上去\"高级\"的东西。因此它可以不加修改地为其他版本的 make 正确处理,比如 nmake 和 dmake.
而作为输入的 makefile 则可以使用GNU make手册中描述的绝大部分的高级特性,包括
事实上,以目前 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( 论文...论文...论文... )
经过四年的学习,终于顺利完成了大学里那些数量众多同时难度颇深的课程的学习,并自学了许多课外的知识和技能。
对\n我来说,学校能教给我的东西是极为有限的。更多地,学校扮演着这样的一个角色:她为我提供一个学习、思考和实践的平台,是我大量地积累知识和技术的主要推\n动力之一,她为我创造了许多软件项目和科学研究的原始需求和灵感源泉,同时也为我提供了极为丰富的图书资源。说实话,四年来,学校的课程对我的不间断的巨\n大压力迫使着我不断地攀登技术高峰,不断地补充自己在众多不同领域的基础知识,不断地完成越来越复杂、越来越重要的项目和课题。
相信与\n否?我大学中最重要的时光是在英特网上度过的。和身边许多同学在网络游戏中沉沦不同的是,我积极地参与到了国际 Perl\n编程社区的活动中,投身到了包括 Pugs 和 Jifty 在内的开源软件项目的开发工作中,与包括 Audrey Tang , Larry\nWall, Adam Kennedy, Luke Palmer 在内的许多世界知名的程序员进行过比较深入的交流,并建立起良好的关系。
我\n与世界各地的程序员保持着广泛的沟通与联系,甚至进行协同开发。从他们身上,我学到了太多太多。我学到的不仅仅是许多具体的技术和技巧,还包括他们的似火\n般的热情,绅士般的风度,朋友般的友善、君子般的谦逊……更重要的是他们面对问题、处理问题和解决问题时的发散式、跳跃式的思维方法,以及一丝不苟、一切\n务实的行事原则。当然,还有英语表达上的许多技巧。在这种场合下,我才发现原来熟悉英语是一件非常幸福的事情。和不同国家、不同肤色的志同道合的朋友无障\n碍地交流,细细想来,还真是一件不可思议的事情,呵呵。
我这个人喜欢体验创新,喜欢冒险,喜欢不断尝试各种有趣而新奇的想法和事物。我也\n喜欢一个人静静地坐在图书馆里潜心阅读计算、数学、物理、生物、化学和历史方面的英文原著,抑或是坐在风和日丽的山头,思索科学和人生中一些有趣而重要的\n问题,或者和大学和中学里结交的好朋友们呆在一起,畅所欲言,天马行空,热烈地讨论技术和科学中已经发生的、正在发生的、和将要发生的那些不可思议的事\n情……
References
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
http://agentzh.org/misc/tracer/digits/index.html (Firefox only) \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\n
$ 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
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
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
经过 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 公司\n 的 cnhackTNT 的提议!
修复了多处内存泄漏问题。使用 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)
附:根据陈敬亮的报告,来自 Foxplus 的 Alexa Sparky 扩展 会严重影响 SearchAll tab 的切换速度,因此对于安装了该版本的 Alexa Sparky 扩展的用户,请在使用 SearchAll 的时候暂时禁用 Alexa Sparky.\n\n
\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
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
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!)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/
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-
\"Debian New Maintainer\'s Guide\" http://www.debian.org/doc/
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/
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/
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/
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.
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 ;)
List Hunter Cluster - 我们自己的基于 Mozilla Firefox 3.1 的深抓爬虫集群\n\n
该文档介绍了我们的基于 Firefox 3.1 的 List Hunter 集群。目前是我们公司生活搜索引擎的一部分。\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
该集群由四大部分组成:纯 Firefox 集群,Apache + mod_proxy + mod_disk_cache 集群,curl 预取器集群,和 OpenResty 集群。一共有十几台生产机\"全职\"或者\"兼职\"地参与了这个集群。下面逐一介绍一下哈:\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
我们平常看到的 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这里能禁用的功能我们都禁用了,这里的 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
该集群目前布署了 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 的通用性,我们直接复用了同时服务于 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
集群目前每小时的产出稳定在 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
当 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
美国雅虎通过大量修改 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 是世界级的浏览器。作为最复杂功能最丰富的 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
Firefox 是高耦合的软件,这与 Google Chrome 及 Safari 浏览器的核心 Webkit 形成了鲜明对比。这意味着,我们比较难于对 Firefox 进行深层次的裁剪,无法轻易地免除一些比较大的功能部件,也很难将其中的某一个大部件剥出来单独使用(当然了,SpiderMonkey 是少数几个例外之一)。\n\n
章亦春 (agentzh) <agentzh@yahoo.cn>
\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
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.
passwd = md5(passwd)\n
for 1..2 do
passwd = md5(passwd + salt)
done