Recently in Code Category
July 4, 2010
Emacs 24 的 magit commit 问题
Magit 是 Emacs 的 git 前端,想对于在 Emacs 当中写完代码再切换到终端去 commit 代码,或者去做一些 diff 之类的操作,把一切都放在 Emacs 当中比较方面一些。而且想对于命令行来说,这种方式也更加直观。
想对于集中式的代码管理外,我感觉对于个人来说,分布式的代码管理更加灵活一些。我目前用 git 的功能也不多,很多高级功能我也还没有掌握。我主要是把 git 用来记录 log 更多一些,有时候建几个分支罢了。我目前主要的编码活动是用 Java 来写面向对象课程的作业,作业本身不算难,但弄出来的代码很多。几部分不能一下子就完成,所以我会完成了一部分之后就 commit 一下。我这学期的面向对象作业都是这么做的,从第一次就开始,感觉一直很好。
有一天我发现 Magit 突然不能 commit 了。每当我写完 commit log 之后,按下 C-c C-c 之后,就没有任何反应了。后台可以看到 git 进程,但 CPU 使用率是 0.0%,也只能手动杀死。杀死之后运行一下 git status 看看,根本没有任何提交,这就让人非常苦恼了。我目前使用 Magit 的感觉来说,其中最爽的一步就是提交了。写好了 log 之后看到之前的工作都进入了 repo 的那一刻,成就感是无与伦比的。这下子不能 commit 了,就让这种快感打了折扣了。
这个问题发生在我写第一次和第二次作业之间,当中我也没注意到发生了什么,突然就发生了这种问题。结果做第二次作业的时候感觉就不如第一次作业时那么顺了。不过那段时间比较紧张,我也没有去找到底是哪里出了问题。我印象里好像是把 Magit 从 0.7 升级到了 0.8 才有了这个问题。于是就尝试重装了几遍,但问题是依旧。我觉得这应该是一个 bug,于是就耐心等待看看下一个版本。
今天看到了 Magit 0.8.1 发布的消息,正好看到 Homebrew 里面也有了 Magit 的 formula,就安装了。安装好后我发现还是有这个问题,就去 issues 去看了一下,发现已经有人报告了同样的 bug report。底下有人回复说是 Emacs trunk 的问题,不过我印象里没有记得那阵子编译安装过最新版 Emacs。
第二条回复里说:“Setting 'magit-process-connection-type' to nil resolves this for me.”,我于是就试了一下,在 .emacs 文件里面加了这么一行:
(set 'magit-process-connection-type nil)
再在 Magit 里面运行了一下 commit,发现久违的 commit 又回来了。
February 3, 2010
越来越喜欢 Java 了
周日晚上开始,大概是 11 点多以后了,我开始写这学期的《数据结构与算法分析》课程的第一次作业的倒数第二道题。题目要求是用 C 语言或者 Java 语言实现 Binary Heap、Ternary Heap、Quaternary Heap、LB-Tree、Skew Tree、 Binomial Queue 这几个数据结构,在程序开始的时候随机生成一个包含 10000 个正整数元素的数组,把这些数据存到这些数据结构中,然后把这写数从小到达取出来,统计进行内存操作的次数,来得到这几个数据结构的性能对比。
我之前和同学讨论过这个题目,对方说他花了不少时间,不过他是用 C 来实现的。我由于这次作业第二天早上就要交了,所以也就没有跟自己较劲,非要用 C 写。基于之前用 Java 的经历,我如果要从 C 和 Java 当中选一个语言来写这个程序,我毫不由于的选择了 Java。
我曾经一度非常讨厌用 Java,因为觉得语法太繁琐,要读取文件都很麻烦。在 C 之类的语言中几行就 OK 了。另外的原因大概是有些审美疲劳,虽然本事不怎么样,但那时却好高骛远,想接触一下 C++ 之类的语言以及 Ruby 之类的新型语言。Java 写多了,那时后的课程又没有什么难度,就有些小看了 Java。后来我的一下比较大的“项目”都是用 Java 完成的,我学了面向对象课程之后,对 Java 也算是有了新的尊敬。
我最近的几次大项目有点不大在状态。每次在截止日期之前都提不起兴致来,非要等到第二天就要交了,前一天晚上才用咖啡顶着,熬夜把项目不紧不慢的写完。每次大概花上夜里 8 个小时,也算是一鼓作气了。上学期《专家系统》课的学期项目是如此,这学期的面向对象的第一次作业飞机座位模拟也是这样,这次的数据结构也是一样的情况。每个程序的规模基本上在 2000 行代码左右。后来我总结了一下,发现 Java 实在是功不可没。要是让我用 C 语言或者 C++ 来在 8 个小时内写这么多代码,我中间的空指针就够我受的了。
我另外用 Java 写的项目是去年暑假上《软件工程》课的时候和另外四个人组成的小组做的学期作业,是一个自动生成歌曲列表的软件。我所在的小组完成的是底层的逻辑部分,似乎和对象的交互没什么关系。我在上学期也和另外一个人用 C 语言写过《计算机网络》课的学期项目,我之前也写过文章讲过相关的故事。那和 Java 比就完全不是一个级别的了,开始时我写 concurrency 的时候简直是一筹莫展。后来我是用的 C 写的游戏的逻辑部分,对方写了服务器和客户端的界面与交互,总算是完成了。不过在演示的时候还是出现了字符串的乱码,估计是一个某个地方有了一个“野指针”。不过打分的助教说这不是重点,于是我们也没有找具体是哪里有问题。
之所以把 C++ 排除在外,是因为我目前的 C++ 水平很弱。我曾经在 STL 流行之前觉得我对 C++ 掌握的差不多了,那时候我还在中学时期,现在想起来也是狂妄的可以。过去只知道有个 class 关键字,底层是怎么回事我是一点都不了解。现在学了面向对象课程,学到了 C++ 中的类不仅可以放在堆里面,也可以放在栈里面。这让我困惑了许久,两着之间的区别是怎么样我也考虑过很久。还有,过去光记得用 class 关键字来定义类,使用的时候也没记得要用指针。现在基本上在定义的时候前面加星号成了标准写法,也让我着实愣了一阵。我还没有用 C++ 写上几个 2000 行左右的程序,因此对于语言本身的掌控没有什么感觉。我用 Java 写这种东西,只要把题目搞清除了,从纸上设计好,就可以开始写了。类之间的组合什么的基本上不会有什么问题,顶多在检查空指针的时候查一些粗心错误。C++ 我就还没有这个底气。
我考虑了一下我为什么感觉喜欢 Java,我喜欢的到底是 Java 的什么东西?最后得到的结论大概还是自动垃圾回收以及隐藏指针吧。C++ 和 C 里面的指针分配,不管是 new/delete 还是 malloc/free 都要小心意义的,这些东西又不能自动递归执行,稍微有点嵌套的数据结构在释放内存的时候就要自己做许多事。Java 的自动垃圾回收虽然从效率上不如 C/C++,但以目前的机能来说,差距也不大,而节省下来的人力时间则不是机器执行时间可以比的。而指针隐藏和垃圾回收也有一定的关系,不用手动维护指针总是好的。虽然指针给了更灵活的操作,但也容易让人写出有隐患的代码。
总结出了这两点,我又检查了一遍,似乎还真没有别的我喜欢的地方了。相反倒是有我不喜欢的地方,就是 Java 没有一个好的调试器,或者说我还没有掌握一个 Java 调试器。我在上学期用 C 写项目的时候,终于对 GDB 有些开窍了,突然觉得它真是一个好工具。尽管我只会用它的很小一部分功能,但已经基本上可以满足我的需要了。我用 GDB 主要是程序有了 Seg Fault 的时候,进 GDB 运行一下看看空指针在哪里。或者就是程序有了奇怪的行为,去设个断点,分布执行一下,跟踪一下变量的变化。虽然不像我过去用的那种 FreePascal IDE 之类的调试器一样可以即时的显式监控变量的列表,但我也习惯了用 p 来查看变量的值。Java 的 SDK 里面有 JDB 这个 GDB 的模拟,我用过几次总是一头雾水。说是 GDB 的模拟,但指令基本上全都变了模样。也没有缩写了,指令本身也变了好多。我反正是一次也没有成功的用起来 JDB 过,所以到目前位置我还是在代码里面插入“人肉”断言来输出变量的值的。
基于上面说的那两点,我觉得应该有不少语言都满足这些要求,但我基本上都没有熟练到像 Java 那样子。而且 Java 也算是最流行的一个,我们老师课不让我们随便用 Ruby 写作业。或者我听说 Objective C 也不错,在 C 的语法基础上加上了自动垃圾回收什么的。不过对于他我还是一点没有入门,语法上也觉得颇为奇怪。就算是之前最熟悉的 Python,拿来让我写这种大项目我也是要愣一阵子的。
想到了这一点,我觉得应该可以找到一种适合自己的编程模式,来发挥我需要语言的特性。通晓了这一点之后,应该写千百个项目都不成问题了吧。
December 7, 2009
调整页面 CSS
日子忙啊,调整页面的 CSS 竟然成了暂时的休闲活动,真是让人苦笑不已。
今天在写完前面那篇文章之后,有把讲 CSS 中文字体设定相关的几篇文章以及一些衍生的文章又看了一下,似乎若有所悟,于是就又打起了修改页面的 CSS 的主意。
之前我对页面不满意的地方主要是页面标题粗细不均匀,看上去粗一片细一片的;还有就是某些字(比如“关”),显式明显比其它字窄一些。之前试着修改过这些问题,后来一直没试成功,最后不了了之。
现在 Firebug 越用越熟练后,也越来越感觉到它的强大。用它的可视化工具来定位哪个部分归 CSS 当中的哪几行管十分方便。然后我有简单复习了一下 id 和 class 的区别,改了改字体,就好了。之前我一直用的是英文字体设定,结果因为没有设定默认的中文字体,所以导致一些中文字显式很难看。结果显式的把黑体、雅黑、宋体等一些中文字体加入到 font-family 当中去,就比较好看了。
定位文章的标题时花了一点功夫。在尝试了几组不同的组合之后,发觉设定了 .asset-name, .archive-title 之后就起作用了。同样修改的还有 widget 的字体,这样左下角“关于我”这三个字就显式正常了。
现在多数网页的链接已经不加下划线了,找了一组比较通用的设置,把默认下划线也给去掉了。
借着打开了 Firebug,我本来想顺便修修后台写文章时标题的字体太难看的问题。地方也找到了,从 Firebug 里面测试也 OK 了,但就是加在文件里面后就不起作用。之前我傻乎乎的以为后台的 CSS 设定和页面的放在一块,所以就一直改页面的 CSS 文件。最后看了看 header 才发觉后台的 CSS 是单独设定的。不过,到了最后我也没找到调整后台 CSS 的方法,反正觉得文章区域已经显示正常了,标题就暂时不管了。
MT4 的 CSS 设定还是很方便的,我这一切做的都是在后台 Design -> Templates 下面修改了 Stylesheet 而已。修改后的内容如下:styles.css。
October 2, 2009
September 30, 2009
晕
从回来之前就在家里看《Programming Ruby》,想尽快把这门语言入门。我以前也说过,对我来说,过去的知识常常会阻碍我接受新知识。过去学Python的时候是这样,现在学Ruby的时候也是一样。其实这类语法类似的脚本语言,它们的语法我早就基本掌握了,欠缺的就是解决某类问题的经验,以及对相应库的了解程度。这些就与实际编程的经验有关了。
为此,我最近写一些程序都是用的Ruby。就算用其它语言可以很快解决的,我也尽量用Ruby完成。我们密码学的第一次作业中的一道题,很简单,给一串密文:
TQLEQ TCDEJ ZFOZY EDFNN PPOEC JECJL RLTYX
而且告诉了它是用shift cipher(就是每个字母都换成了字母表中牌子后面的字母,如abc被加密成了def,就是字母被换成字母表中排在后面3位的字母了)来加密的。让我们从1到26,用穷举来列出每种情况,然后再判断原文是什么。
本来计划是用Ruby来写的。像这种不算复杂的算法类程序,又是与字符串相关的,用这种脚本语言最合适了──不用写与问题本身无关的冗余代码。题目的要求是用C、C++、Java或Pascal这些语言来写,其它语言需要教授批准。为了这个,我还专门找了教授,问他能不能用Perl、Python、Ruby这种script languages来做。后来他同意后,我就开始用Ruby来写。
结果花了我几乎半天的时间,我的结果简直可以用“惨不忍睹”来形容了。我把字符串放在数组里面,每次调用.next!来改变当前的字母。但由于Ruby的引用策略的关系,导致我的修改无法返回原数组去。因此总是出一些奇奇怪怪的错误。
本来打算再找时间研究一下的,但昨天上午的《计算机网络》这门课的实验课,要我们用C语言写socket程序。服务器端读取公交车的到站时间,客户端发送目前时间和公交车的车次,服务器端返回下一个到站的时间。自从学了脚本语言后,我越来越少用C语言认真的写程序了。主要是字符串那些东西,经常出错,远不如脚本语言方便,就连Java也比C语言方便不少。因此看到实验要求,我虽然有点怕,但还是硬写下去。结果竟然被我写出来了。
有了实验作业给我的底气,我觉得用C来完成密码学作业也不是太难了,就试着用C来写。结果让我意外的是,不到半小时这个程序就像模像样了。总共也不过30多行,比我之前用Ruby写的半成品多不了几行。
经过这件事,我开始反思我在这几年是不是对写程序不那么严肃了。如果让我评价对几种语言的喜好程度,我一定觉得脚本语言胜过C之类的语言。我花在Python上的时间比较多,而除了Java外,C语言和C++语言我几乎没有怎么“涉猎”。是不是有点避重就轻?是不是应该在平时多花一点时间在低级语言上呢?希望我在这个学期内可以有所改善。
September 26, 2009
解密辅助工具
我们的密码学课程的作业之一就是老师给你一段字母拼成的文字,单词已经划分好了,每个字母都代表另外一个字母,让你翻译成原文。翻译的方法是通过找出一些特殊的部分,不如两个相同字母结尾的单词、单字母单词之类的,来找出更多的字母。对于这种方法的难处,我在之前的文章里有过描述。其中也说了我要写个工具来帮我干这个事情。今天用Ruby简单的写了这么一个。放在了这里。
经过测试,程序能按照我的想法来做事。比如那篇文章里说的SKYQD一词,我有了arge结尾后,怎么也想不到large这个词。有了这个工具,运行match.rb SKYQD | grep arge就可以了返回large了,应该会给我的工作有很大帮助。程序的原理也很简单:对于SKYQD,先把它处理成一个标准的模式──ABCDE(更好的例子是HYTOOW,处理成标准模式后是ABCDDE)。然后再从保存了处理成标准模式的英文单词的Hash中查找就可以了。我是Ruby初学者,因此写的代码也没有什么优化,应该也挺罗唆。
目前这个程序有几个问题。
一是程序中上来先把我之前获得的英文单词都处理成我要的模式,这样每次运行都来一遍,应该挺废时间。我在想说不定把处理完毕的Hash保存起来可能会更有效率。
二是我目前的单词列表非常不够。我目前的单词列表是在这篇文章里说的,通过一个小程序在一个网站上抓取的所谓“常用单词3000字”。有很多单词都却是,因此我得到的常常就是Not Found。我无法在网上找到非常全面的单词列表,因此可能要写个程序从网络上解析网页抓单词。因为我们的这些句子经常是老师从Winnipeg Free Press上得到的,如果能把这个网站上用到的单词都作为程序的基础,那么破解起来应该会更方便。
第三点就有点提高了。目前这个程序只是按照我的要求来寻找合适的单词,并不能更进一步帮助我。如果能把我的单词列表中的单词都配上一些属性,通过人工智能上的一些技术来做进一步的筛选的话,应该会更方便。我在一年前学《人工智能》的时候,有一项作业是用Prolog来写一个检验一句话是否符合日本俳句的标准。如果能结合这两点,让程序帮忙整句的筛选,那就更理想了。
September 21, 2009
英文单词列表
《密码学》课上的一个内容就是“破译”密码。其实我们也不算真正的破译,只是老师选一段话,把每个字母用另外一个字母代替,让我们找出原文。比如这个:
GKVVEHDRR ER GKOEHQ K SKXQD
STOEHQ, ZKXEHQ, ZSTRD-PHEJ AKYESU --
EH KHTJGDX ZEJU. QDTXQD CBXHR.
其实破译这种密码并不困难,单词已经分开了,你只要找规律试就可以了。比如第一行的K,一个单独的字母单词,很容易猜到可能是a或I;还有几个EHQ结尾的单词,也很容易的会想到ing。就这样把已知的几个单词替换回去,并猜出更多的单词。最后,我们能得到这样的原文:
Happiness is having a large
loving, caring, close-knit family --
in another city. George Burns.
经过几次这样的尝试,我发现这种破译对于英文为第一语言的人来说是很简单的,可对于像我这种后来才学英语的人,对于英文单词就没有这么的敏感。比如那天我破译这一段的时候,第一行的SKYQD中,后四个我都猜出来了,于是就想了半天:什么单词是一个字母加上arge结尾的?结果想到最后,直到通过其它途径破解了密码后,才发现原来这个单词就是large啊。可当时我是怎么也想不出来。相信对于英文为母语的人来说,几乎是条件反射般的迅速反应吧。
我从上这门课的第一天,就想写个程序来协助破译。程序也不需要很复杂,用户告诉程序需要的单词的pattern,比如“GKVVEHDRR”,而程序通过搜索单词列表,把符合条件的单词都找出来,这样不用乱枪打鸟,比原先就方便多了。
但程序的基础,就是要有一份常用单词的列表。本来以为这样的东西网上一找一大片,没想到找了半天,得到的都是一些特殊的单词列表,什么简化英语单词列表之类的。很少有我想要的。而这种需求通过词典更不能解决了。
找了半天,发现了这样的一个网页,上面有3000个英文常用单词,看了之后,我觉得不错,但需要把单词整理成一个文件,每行放一个单词,然后再排序之类的。因此把这些单词都抓下来就是首要任务了。
我对Perl的正则比较熟悉,对Python的字符串处理也还行,但因为想练习Ruby,就选择用它来做。觉得Ruby这么大的“家业”,相关的模块应该不少,从网上搜索一番后,找到了Nokogiri这个库,据说是最快的一个HTML/XML Parser。它的用法很简单,看了例子后,我很快就上手了。相比起从网页中用正则挨个判断,用Nokogiri实在是太爽了。
但写程序的时候出现了一个小问题。我不知道怎么获得链接的地址。因为那个单词列表的页面上,有15个列表,点进去才是一个真正的单词表。因此我要通过Nokogiri来获得那些页面的链接。但找遍了Nokogiri的文档,却只看到返回标签内容的方法,丝毫找不到返回链接地址的方法。我不知道是因为我还没有习惯rdoc还是rdoc本来就没有这些详细的报告。最后我从一个中文blog上看到了答案,原来链接的地址被保存在对象的[:href]这里。
其它的基本上就是顺其自然的写下来了,一共不到20行。我把程序上传到了这里。程序运行后就在终端输出单词列表,稍加整理就应该能用了。不过,我用wc测试了一下,发现这个列表里面只有2000多个单词,根本没有达到页面上说的3000的数目。而且作者还把像tree这样的基础单词给删掉了。看来还要再增加啊。
September 18, 2009
Twitter备份的代码
我前天写过文章,说写了一个保存Twitter记录的工具。今天把代码整理了一下,上传到了网上。
目前我只完成了数据获取的部分,至于报表生成的部分我还没有写。写个cgi来输出HTML表格,我上学期学过,应该不难。
程序中用到了sqlite3-ruby和twitter4r这两个库,它们都可以通过RubyGems来安装。
对数据库的操作,我用了最直接的方法,没有进行任何优化。一是考虑到这个程序对速度的要求不高,二是我这学期才开始学数据库,对于SQL语句的优化还没有什么概念。
最后,说一下Ruby中的YAML配置。考虑到不管是数据库的初始化还是更新数据库,都需要Twitter的用户名和密码,而且我也想把一次抓取多少条tweet这个变量也提取出来。本来想的是在程序的开头设置变量,但这样会让程序的使用变得麻烦──修改Twitter的用户名和密码后,需要在两个程序里做出改动。因此写个配置文件就是比较必要的了。过去我一直觉得写一个带配置文件的程序是比较困难的,因为需要自己解析。但Ruby中的YAML让一切变得非常简单。正好借这个机会,学习一些YAML的解析。
中文网页很少,我没有搜到什么结果。最后从一个外国blog上看到了例子,才知道Ruby中用YAML原来是这样的简单。想看的同学自己去看看就会用了。
September 16, 2009
Twitter备份
自从上次开始,我就想写一个工具,可以像Google搜索历史那样,把Twitter的历史记录下来。思考了几天后,今天开始动手写。
我简单的找了一下,没看到有很合适的工具,也不知道有什么好办法,就用最简单粗暴的方式,写个定时运行的程序,保存tweets到sqlite数据库中,然后从数据库中获取数据,得到列表。
前几天看了Ruby的书,就用Ruby来练一下。并找到了Twitter4r库,能比较方便的获取一定数量的tweet记录。然后结合sqlite3 api接口,在解决了下述几个问题后,程序运行成功。代码我还没有整理好,等以后再上传吧。以下是当中遇到的几个问题。
一是Ruby正则表达式替换的处理,以及sqlite对于转义字符的处理问题。Tweets上经常会有引号,这样在写SQL语句的时候就有了转义的问题。我在程序中是用单引号来包含字符串的,中间一度怎么也搞不定单引号的转义问题──要么把引号弄没了,要么生成不了正确的的结果。看了一下Ruby书,似乎在Ruby正则表达式中,\'和\有特殊的含义,不能直接转义。经过几次尝试,最后用gsub(/'/, '\'\'')解决了问题。具体是什么原理,我没研究过Ruby书,因此没有深究。
二是写好程序后上传到Dreamhost服务器上,sqlite总提示出错。似乎是用了IF EXISTS和IF NOT EXISTS就不行。后来经过搜索才知道,sqlite从3.3.4之后才支持EXISTS关键字。而Dreamhost上的版本不够,于是造成了这个问题。在检查了代码后,觉得虽然不如加了EXISTS保险一些(如果有人工干预操作数据库就可能出错),但也不是非要不可,把EXISTS删除就好了。
第三是当终于能运行了后,却又发现在Dreamhost上生成的数据库在合并的时候会出现每条tweet都存了两遍的情况。为了这个我检查了将近半下午,最后才发现是时区问题。我的表中有个DATETIME字段,存了tweet发布的时间。在我这里时区是GMT-5,而在Dreamhost服务器所在的地方,时区是GMT-7。把建立数据库的程序在服务器上运行一遍后就算解决了问题。
以上是写程序中遇到的三个问题,已经解决了。但在最后我又遇到了一个最大的问题。我准备在Dreamhost上用crontab来每天运行更新程序,但Dreamhost默认没有安装twitter4r,我是通过gem安装的。而似乎crontab运行程序的用户组不是普通用户,导致找不到twitter4r库,结果程序无法运行。当然这些只是我的推测,希望可以尽快解决吧。还有就是生成报告的程序,应该不难,但要在这个的基础上写。
June 25, 2009
想写一个类似co.mments的东西
co.mments关闭了好长时间了,我的Safari书签栏上还留着它的添加书签。我一直讶异目前市场上没有这类工具,相反,印象里coComment似乎挺火的。我在最早的时候分不清co.mments和coComment,后来发现coComment提供的是插件,非常麻烦,而且似乎还无法达到我的要求。同时我一直觉得co.mments这个工具应该是人人都喜欢的,因此当开发团队说要关闭这个服务时,我着实的吃惊了一把。
在没有了co.mments之后,对我来说影响没有特别巨大,唯一的一点可能就是我更少的在别人的blog上留言了。很多blog并没有安装回复留言时的邮件通知功能,因此我在留言之后,如果不再去那个网站不断刷新,一旦对方对我的留言有回复,我就很难得知。我这个用MT搭建的blog,每次有人留言的时候,我都能收到邮件,但我回复别人留言后别人能否收到邮件通知,我就不知道了。而我在用WP的时候更没有安装邮件通知插件。
没有这个工具,我一直觉得特别不方便,因此最近有想自己实现一个山寨版的想法。方法也没有自习设计,只要用最简单能用的Quick and Dirty实现就好。先在本地保存一个网页的备份,然后定期去抓取网页回来比较,如果有不同则发送邮件提醒,这些用Perl都很好实现。
只在前天写了几行草稿,最近忙作业,一直也没有动手,真希望能找点时间完成它。另外,如果可能的话,我希望能把它弄到Google App Engine上,这样一来用着就更方便了,而且说不定还可以帮助别人。不过这样似乎就要用Python了。