Monday 22 December 2008

Moby Dick






白鲸


一斧头一斧头当场就劈出来这么一个野蛮而厚重的家伙。边劈边聊,跟砍柴的似的;烟没断过;有时候咳嗽儿;地上随意扔着大大小小碎料,没人收拾,管他呢。

开始突突突冒气没活动开。活动开之后那叫一个跑的欢。西伯利亚雪原上干净的烟。单纯而残暴。

这是怎样一部作品啊。看了之后直觉的自己活的琐碎不真实。食人生番的友情,大副的爱家,二副的爱自己,三副的勇敢,船长的无可救药的坚定。死是任谁谁都无可逃脱的命。那就迎着上去好了。

野蛮而厚重的东西在国内很少看到。中国人大多精于技巧。做出东西有大气的但很少野蛮的。也许这是个审美的问题吧。文明古国,自汉吧,就走向精雕细刻的路——看看我们的菜吧,还有国粹。粗砺一点别人都以为你没下够功夫。当然啦,也没多少拿得动开山的斧头的。沉香也就一下两下,把山劈开救出妈妈就哭做一团了。谁能把山给劈出来?从一个混沌一团的地方?剑在这比较流行,一百单八式舞的密不透风,水泼不进;一飘身就不见了;诸般灵异说说都觉得臊得慌。就描吧,单薄的灵魂只配贴在纸上。

Friday 5 December 2008

About Time

关于时间的几个问题――别太当真
下载:aboutime.pdf

Git Magic Chinese Version

Git Magic 中文版


译自:http://www-cs-students.stanford.edu/~blynn/gitmagic

网页版:http://docs.google.com/View?id=dfwthj68_675gz3bw8kj
PDF下载:Git_Magic_CN.pdf

Google Docs还真不赖:-)




Thursday 4 December 2008

Archimedes

阿基米德

阿基米德说,给我一支点,我就可以撬起地球。

也不知阿基米德是否真的说过这样的话。由于时空的关系,一直找不到机会见到他。阿基米德也没机会见到牛顿。牛顿发现万有引力定律的时候,想必也想找阿基米德聊聊;但人早不在了。

阿基米德要撬起地球的话,要好好考虑几件事。

其一,支点放在哪的问题。支点不能放在地球上,但又不能离地球太远。支点离地球太远,杠杆就会更长。杠杆太长就得考虑今生如何走到杠杆的另一端的问题。不能超光速的。爱因斯坦也不是吃干饭的。不妨考虑把支点放到月球上。月球离地球最近,而且月球也不在地球上。唯一的问题是月球可能没那么稳定,未必承受得了太大的力。

其二,杠杆的长度。假设阿基米德体重100公斤,有100公斤的力气。地球的质量是6.0×1021公斤。支点选在月亮,月亮离地球3.8×105公里。根据杠杆原理,那杠杆长度就得有2 ×1024公里。光速是3×105公里每秒。阿基米德爬过去最少需要 6.7×1018秒,也就是2×1011年。目前地球的年龄大约46亿年(4.6×109)。月球寿命大约4.3×109年。等阿基米德的幽魂爬到杠杆的另一端,月亮和地球的幽魂又在哪里呢?


其三,阿基米德的游魂站在哪里撬呢?这杠杆太长了,有2×1011光年长。银河系的直径大约10万光年。真是零头都不够啊。据说宇宙也就260亿(2.6×1010)光年吧。可怜的阿基米德,伟大的物理学家,的幽魂,却只能置身宇宙之外,努力地撬遥远的一个宇宙里的,也许最不出名的一颗小小的蓝色星球,的幽魂。


Math Puzzles

数学题


下面这个链接里有71道数学题:
http://www.math.ucsb.edu/~cooper/puz1.html
谁谁有兴趣就做做。我只做过第1道和第9道。

第1道:
    /**
* MATH PUZZLE 01
*
* An ant starts at one end of a rubber band and walks along it at a speed
* of 1 inch per second. The rubber band is 10 inches long, and is being
* stretched uniformly at a rate of 20 inches per second. Does the ant ever
* reach the other end of the rubber band?. Give reasons.
*/
public void testMathPuzzle01() {
long t = 0;
final long MINUTE = 60, HOUR = MINUTE * 60, DAY = HOUR * 24, YEAR = DAY * 365;
double rubber = 10;
double walked = 0;
while (walked < rubber) {
// After 1 second
t++;
rubber = rubber + 20;
walked = walked * rubber / (rubber - 20) + 1;
if (t % YEAR == 0) {
System.out.println("" + t / YEAR + " years has been flying by");
}
}
System.out.println("Time used:" + t / YEAR + " years, " + t % YEAR
/ DAY + " days, " + t % DAY / HOUR + " hours," + t % HOUR
/ MINUTE + " minutes," + t % MINUTE + " seconds");
}

蚂蚁这题很有意思。应该是一个微积分的题。上面的解答算一个模拟解吧。假设先拉橡皮筋,蚂蚁后走:
walked = walked * rubber / (rubber - 20) + 1;
算出蚂蚁需要大约16年才能爬到橡皮筋另一头。或者蚂蚁先走,再拉橡皮筋:
walked = (walked + 1) * rubber / (rubber - 20) ;
可以算出蚂蚁需要2年多一点可以爬到另一头。早一步就节省12年。这道题也印证了抢占先机的重要性。

还有就是第9道:
  /**
* MATH PUZZLE 09
*
* In a TV show, a prize is hidden behind one of 3 closed doors. The
* contestant tries to guess where the prize is. After the contestant
* chooses a door, the host of the show (who knows where the prize is) opens
* one of the 2 remaining doors, to reveal that the prize is not behind that
* door. The host then gives the contestant the opportunity to change her
* guess. Should she?
*/
public void testMathPuzzle09() {
final int SIZE = 100000;
boolean[] doors = new boolean[3];
Random random = new Random();
int insist = 0;
int reselect = 0;
for (int i = 0; i < SIZE; i++) {
// Init doors
doors[0] = doors[1] = doors[2] = false;
int index = random.nextInt(3);
doors[index] = true;
int guess = random.nextInt(3);
// does not change her guess
if (doors[guess] == true) {
insist++;
}
// change her guess
if (doors[guess] == false) {
reselect++;
}
}
System.out.println("Not change will get:" + insist);
System.out.println("Change will get:" + reselect);
}

实质上是大家常讲的三个门的题。门后面可能藏别的东西。

Wednesday 3 December 2008

The So Called Elder


父辈

比较喜欢的东西,最好要有个内核,精神上的。不喜欢像于丹那样的,东一下西一下,道理满天飞,但缺少精神实质。平常的谈话也是如此。经历过文革的那代人,说的话本质上跟打嗝差不多,基本的卫生标准都达不到,更别说精神实质了。

-- 原来挺崇拜经历文革的人,后来才发觉,绝大部分经历文革的人,都已经磨得没点脾气了,包括那些大家们

不止是没脾气,是没自我,而且一厢情愿地认为, 别人也应该没自我。

读《静静的顿河》,发现俄国人是比较混的。可这种混蛋劲儿,比没自我,也可爱多了。人俄国人打的饱嗝,透着酒气;冬天里闻到,恶心归恶心,也还知道对面的人是活生生的。不像我们,形体上的温驯,遮掩精神上的野蛮。

Monday 1 December 2008

YAML Brief Introduction












YAML简介




YAML Ain't Markup Language


和GNU一样, YAML是一个递归着说"不"的名字.  不同的是, GNU对UNIX说不, YAML说不的对象是XML.



YAML不是XML.







为什么不是XML呢?  因为:



  • YAML的可读性好.


  • YAML和脚本语言的交互性好.


  • YAML使用实现语言的数据类型.


  • YAML有一个一致的信息模型.


  • YAML易于实现.




上面5条也就是XML不足的地方. 同时, YAML也有XML的下列优点:



  • YAML可以基于流来处理


  • YAML表达能力强, 扩展性好.




总之, YAML试图用一种比XML更敏捷的方式, 来完成XML所完成的任务.



更多的内容及规范参见http://www.yaml.org .

语法


Structure通过空格来展示. Sequence里的项用"-"来代表, Map里的键值对用":"分隔.


这几乎就是所有的语法了.


比如...




一般YAML文件扩展名为.yaml. 比如: John.yaml

name: John Smith

age: 37

spouse:

    name: Jane Smith

    age: 25

children:

    -   name: Jimmy Smith

        age: 15

    -   name: Jenny Smith

        age 12

John今年37岁, 有一个幸福的四口之家. 两个孩子Jimmy 和Jenny活泼可爱. 妻子Jane年轻美貌. 如果深入研究的话还可能发现一些社会问题.



可见YAML的可读性是不错.




JYaml - YAML的Java实现


YAML已经有了不少实现, 详细的实现列表参见http://www.yaml.org/download.html.



其中JYaml(http://jyaml.sourceforge.net )是YAML的Java实现.


JYaml简介


YAML使用实现语言的数据类型. 我们看一下一些JYaml支持的Java数据类型:



  • 原始数据和封装类(比如int, java.lang.Integer)
  • JavaBean兼容对象(Structure支持)
  • Collection (sequence支持)
    • List
    • Set
  • Map (map支持)
  • Arrays (sequence支持)
  • BigInteger 和BigDecimal
  • Date

我们给出John.yaml的java描述:
public class Person {
    private String name;
    private int age;
    private Person sponse;
    private Person[] children;
    // setXXX, getXXX方法略.
}

现在让我们装配一个Jone:
        Person john = new Person();
        john.setAge(37);
        john.setName("John Smith");
        Person sponse = new Person();
        sponse.setName("Jane Smith");
        sponse.setAge(25);
        john.setSponse(sponse);
        Person[] children = {new Person(), new Person()};
        children[0].setName("Jimmy Smith");
        children[0].setAge(15);
        children[1].setName("Jenny Smith");
        children[1].setAge(12);
        john.setChildren(children);

使用JYaml把Jone "Dump"出来:
        File dumpfile = new File("John.yaml");
        Yaml.dump(john, dumpfile);
下面我们看看John.yaml是什么样子:

--- !yaml.test.internal.Person

age: 37

children: !yaml.test.internal.Person[]

  - !yaml.test.internal.Person

    age: 15

    name: Jimmy Smith

  - !yaml.test.internal.Person

    age: 12

    name: Jenny Smith

name: John Smith

sponse: !yaml.test.internal.Person

  age: 25

  name: Jane Smith
其中!yaml.test.internal.Person是一些类型的信息. load的时候需要用.

现在用JYaml把Jone.yaml load进来:
        Person john2 = (Person) Yaml.load(dumpfile);
        assertEquals(john, john2);
我们最初给的John.yaml并没有类型的信息. 可以用下面的方法load进来:
Person john2 = (Person) Yaml.loadType(dumpfile, Person.class);
我们还可以用下面的方法dump出最初的John.jaml:
Yaml.dump(john,dumpfile, true);

我们再来看看JYaml对流处理的支持.

为简便起见, 我们只是把同一个john写10次:
       YamlEncoder enc = new YamlEncoder(new FileOutputStream(dumpfile));
        for(int i=0; i<10; i++){
            john.setAge(37+i);
            enc.writeObject(john);
            enc.flush();
        }
       enc.close();
下面再把这十个对象一个一个读出来:
        YamlDecoder dec = new YamlDecoder(new FileInputStream(dumpfile));
        int age = 37;
        while(true){
            try{
                john = (Person) dec.readObject();
                assertEquals(age, john.getAge());
                age++;
            }catch(EOFException eofe){
                break;
            }
        }

JYaml对JDK14的支持

JYaml的源码是基于JVM5的. 也提供对JVM5功能的一些支持, 比如对枚举类型的支持.

JYaml的JVM14的支持是通过retrotranslator(http://retrotranslator.sourceforge.net ). retrotranslator使用ASM(http://asm.objectweb.org )动态修改JVM5字节码成JVM14, 使JYaml在JVM14下可用. 会牺牲一些效率. Debug时也会失真.

我修改了JYaml作者Toby Ho的一些源码(基于Beta2.2), 使之与JVM14兼容. 当然, 为此也去掉了对JVM5才有的类型的支持(比如枚举类型). 这个牺牲应该是值得的. 由于还没有和Toby Ho讲, 因此还不能公开这个JVM14兼容的包.

YAML的使用范围


YAML的一个亮点是数据类型使用实现语言的类型. 这样比较省事的地方是自己不用有自己的一套类型定义.

比如我们使用Ruby写一个Person类:
class Person
  attr_accessor :name, :age, :sponse, :children
  def initialize(name, age, sponse=nil, children=nil)
    @name = name
    @age  = age
    @sponse = sponse
    @children = children
  end
end
把John装配起来:
jane = Person.new("Jane Smith", 25)
children = [Person.new("Jimmy Smith", 15), Person.new("Jenny Smith", 12)]
john = Person.new("John Smith", 37, jane, children)
Dump出John到John.yaml:
File.open('John.yaml', 'w') do |os|
  YAML::dump(john, os)
end
我们看看Dump的结果:
--- !ruby/object:Person
age: 37
children:
- !ruby/object:Person
  age: 15
  children:
  name: Jimmy Smith
  sponse:
- !ruby/object:Person
  age: 12
  children:
  name: Jenny Smith
  sponse:
name: John Smith
sponse: !ruby/object:Person
  age: 25
  children:
  name: Jane Smith
  sponse:
仔细观察会发现和JYaml Dump出来的还是有些区别的.

首先类型信息不一样. 这还好说, 虽然Ruby load Java的不太可能, 但Java加载Ruby的应该没问题.

还有就是一些实现上细微的区别. 比如Ruby::Yaml的"spone:", JYaml认为是不合法的. 还有children的不缩行. 尽管Ruby::Yaml很流行, 但JYaml认为这是Ruby的Bug. 网上有相应的争论.

不过在一个语言里使用还是没问题的. 下面是load John的代码:
john2 = File.open('John.yaml') { |is|  YAML::load(is) }

毕竟每个实现语言的类型不一样的, 不同语言文化也不同. 因此不同实现的YAML的交互是个问题. 兼容性需要YAML规范来保证. 而具体的实施还有很长的道路要走.

YAML和SDO(只讨论双方的java实现)


如果读者想了解更多SDO的概念, 参见http://www-128.ibm.com/developerworks/library/specification/j-commonj-sdowmt/index.html . 这里我们只讨论SDO的java实现.

SDO里有一个很总要的概念, DataObject. 从DataObject的接口里, 可以看出有两类的数据类型, 一类是JYaml支持的, 诸如String, List之类, 一类是DataObject. 因此我们只需要增加一种支持DataObject的类型, 就可以完成对SDO DataObject的支持.

不妨叫YamlDataObject. 下面是它的数据结构.
public class YamlDataObject {
    private String uRI;
    private String name;
    private Map attributes;
}
YamlDataObject里用到的类型, 都是JYaml能够支持的. 其中, uRI和name用来描述DataObject自身. attributes来描述DataObject里的值. 这些值可能为DataObject, 也可能是JYaml所支持的其他类型. 我们希望用YamlDataObject来担当DataObject的角色, 因此YamlDataObject和DataObject要能互相转化. 增加两个API:
private static YamlDataObject newInstance(DataObject dataobject){...
private DataObject toDataObject() {...
上面两个之所以是private的, 是因为我们打算遵照JYaml的习惯, 增加两个接口, dump和load, 这样newInstance和toDataObject只在内部使用了. 下面是dump和load的定义:
public static void dump(DataObject dataobject, File dumpfile) throws FileNotFoundException{...
public static Object load(File file) throws FileNotFoundException{...
下面是一小段测试代码:
// ... create dataobject ...
File bodump=new File("bodump.yaml");
YamlDataObject.dump(dataobject,bodump);
assertTrue(bodump.exists());
DataObject dataobject2 = (DataObject) YamlDataObject.load(bodump);
 // check result
assertNotNull(dataobject2);
for(int i=0; i<5; i++){
   assertEquals(dataobject.get(i),dataobject2.get(i));
}

具体的实现细节就不谈了. 读者可以作为练习题, 熟悉一下这两个数据整合方案.

YAML存在的意义


无论多么完美的事物, 都需要有对立面, 有说"NO"的声音. XML也不例外. 当然, 站在主流的对立面, 需要勇气和智慧.

YAML和XML不同, 没有自己的数据类型的定义, 而是使用实现语言的数据类型. 这一点, 有可能是出奇制胜的地方, 也可能是一个败笔. 如果兼容性保证的不好的话, YAML数据在不同语言间流转会有问题. 如果兼容性好的话, YAML就会成为不同语言间数据流通的桥梁. 建议yaml.org设立兼容认证机制, 每个语言的实现必须通过认证.

假如兼容性没问题的话, YAML就太完美了. 轻巧, 敏捷, 高效, 简便, 通用. 这才是理想中的数据模型.

















Saturday 22 November 2008

The Meaning of Love

爱情的意义

在我上大学的时候,有一个晚上,十一点多了,我下了晚自习,正在往宿舍走的路上。天黑的厉害,蛇样的闪电预告着一场雷雨。我在路上走这时候一个女生拦住了我。

——同学,能不能帮一个忙?

很漂亮的一个女生。我在校办晚会上见过她。南方的女孩。低着头。仰脸的时候眼睛里有一层雾。

——什么事?

她指了指路边的一团黑东西:

——能不能帮我把他送到宿舍?

我才注意到路边的阴影里,还躺着一个人。我那时候的帅那时候的人很难察觉。因此那时候很少有女生主动找我谈话。我那时候又太帅,也不愿主动去找女生。因此我不假思索地答应了:

——可以的,但你必须告诉我他住在哪个宿舍。

他住在四楼。不能再高了,西西楼就那么高。体育系的师哥喝了啤酒,喜欢把酒瓶扔出窗外。于是把他们从四楼赶到一楼,这样别人受的伤会轻一些。四楼住的是文明点的,比如中文系或者历史系的学生。

文科的男生比死猪都沉。尤其是我背上这一个喝多的。开始我拖着他,一个闪电下来我怀疑他死了;不过试试鼻息还在。于是我又把他扔到了背上。他女朋友拉了拉发现挺结实,就撤了,剩下我们两个走向回家的路。

大粒的雨点打在他脸上。于是他醒了。他叫了几声一个女孩的名字没人答应。于是问我,

——你知道爱情的意义吗?

我忙活了一个晚上,目的是讨论一个东西的物理意义,还没讨论清楚,明天接着讨论。

——你甚至可以为她去死,

我想起他女朋友哀求的眼神。不愿意女的这样。能帮就帮啦。

——你也是为她而活;你知道她有多好吗?那么的迷人,像一头小鹿,

是的。食草动物才求人。小鹿求倒了一只理工科的驴。这头驴现在驮着一团文科的屎,臭气熏天,走在大雨中。他的话语低沉,有时呜咽,还伴着雷声;我的脸上淌着汗和雨。

——甜蜜、苦涩、更多的甜蜜、更苦涩;你也是为她而活

汗是咸的。可乐解渴。回去买一杯。也不知小卖部还有没有人。

——神魂颠倒,让人迷醉

应该喝的是啤酒,也就燕京吧。啤的没劲,但喝了凉快。

——多么好的,一个女人

多么壮的,一头驴啊。路上都是水,也不打滑。

我实在没力气把他背到四楼。到二楼的时候,把他放下,让他靠着墙站会儿,我好歇歇。他扶了扶只有一个镜片的眼镜。我歇了会儿就把他架上去了。踹开门,把他扔在一个空床上。屋里有一把吉他,不知是不是他的。长发。于是我买我的可乐去了。太渴了。买了两杯。

我那时候是光头。梳子老丢,洗头也麻烦,干脆就不要了。我觉着挺好看的。女生看着老笑。物理实验室灯那么多,多我一个也不嫌多。

我终于讨论清楚了那个东西的物理意义。论证、计算占了十好几页,交给了材料物理老师。后来老师给我判错了。我问他原因,他说,

——有经验公式的,套用一下就可以了;

可现有的经验公式,误差在百分之百还多,太不准了,

——那没关系,实际测一下就可以了,何必算那么多?还有什么无谓的证明?

那一刻我发现我不适合做材料物理;这个学科太不严谨,经验的成分太多,还嘲笑我所钟爱的计算和论证。

在校园里也见到他们。有时笑得像两朵花,有时伤心的像两片雨。他的头发是长的还背着吉他,我的头发是没有的还背着书包。我已经开始嘲笑材料物理,醉心于理论物理。所有爱因斯坦说的都记在小本子上,忘记了就复习一下。爱因斯坦说,

——反复地做同一件事情,却期望得到不同的结果;这就叫精神错乱

有时候看到他们骑一辆自行车。男生背着吉他,长发飘飘。女生明显是食草动物,依偎着另一个食草动物。那另一个食草动物背了吉他像一只扫地的绵羊。他们明显忘记了那个夜晚。有时和他们面对面走过去,他也并不看我一眼。我和其他许多光头的理科男生一样,对他根本构不成威胁。我喝酒的次数很少。喝的话也不醉,越喝越高兴,脑门发亮,掏出小本子念,爱因斯坦说,

——我相信上帝不掷骰子

我相信文科男生都是骗子。文科女生都傻子,全上当了。理科女生更傻,还怨恨文科男生不骗自己个儿。霍金还没病的时候,作为舵手参加赛艇大赛,他女朋友在河边叫好都叫疯了。瞧瞧人那女生的什么境界。牛顿惨点,脾气太傲基本没女生踩。还有玻尔,也是酷的不得了,包括他的不善言辞以及口吃。杨振宁挺滑的,单独拿出一些时间把杜致礼拿下,也算是师生恋吧。后来人杨振宁拿了诺贝尔物理奖,政府觉得关着诺贝尔奖得主的岳父不合适,就把杜聿明提前放了。多大的造化。掏出小本复习一下,爱因斯坦说,

——我觉得最不合理的就是上缴个人所得税

我觉得最不合理的就是材料物理太依赖混蛋经验公式。脑子不进水总结不出误差百分之百的经验公式。我转向了更重视计算和论证的理论物理。于是进入了另一个世界,上了研。

那时候我留起了长发。喝酒。现在啤酒肚就是那时候落下的。很颓。导师问怎么了,我说失恋了。

我的确失恋了。但我不能确认我是否真的很痛苦。我只是觉得我应该很痛苦。还为这应该的痛苦留起了长发。一个繁星满天的晚上,科技楼停电了,也找不着蜡烛,于是就出来坐在楼前的台阶上,看星星。这时导师走过来,挨着我坐下,对我说,

——面对浩瀚的宇宙,我们个人的那点儿事,又算得了什么?

第二天我就把头发剃了。还是光头省事。梳子找不到也不用找了。头放在水龙头下冲一冲就可以了。洗发水厂家都恨死我了。很多年后去看导师,谈起这件事和他的那句话,他说他不能证实他是否说过这句话,但这句话的特征是他的体系。我确信我听到了这句话,但不确信这句话是来自外部的世界,还是来自我自己的内心;尤其是在没有得到完全承认之后。

也不知他们怎么样,很多年不见,也不记得他们的名字;文科的两个傻子。可谁没有傻过啊?无论长发的,还是光头的;无论背吉他的,还是背书包的。

后来我发现我背不动书包了。老爱老玻联手基本把理论给找补齐了。霍金虽然只有一根手指头能动换,但人脑子整天不闲着。大英帝国也支持他,有吃的有住的。我这吃的还凑合但住的就不灵了。想改善的话就得昧着心当骗子。我背了那个文科的男骗子之后烦死骗子了,见面恨不得掐死他们,自己是骗子就掐死自己。于是干脆把书包放下,背上了电脑包。

这些年也在一直讨论爱情的意义。当然有现成的经验公式可用,但经验公式也太不靠谱了。这误差太大不说,也没有什么根据。基本上就是瞎说一气,见一码记一码,一捆一捆那么撂着。很多数值根本就没有量纲,更别谈意义了。不过当我把自己的论证和计算交上去之后,换来了这么一批语:

——你就是犟!

可不是嘛。要知道我是一头驴子啊。驮过文科那坨屎,驮过书包,驮电脑包;驮房子。驮房子的驴就快退化为蜗牛了!于是就叫几声。嗯啊嗯啊~~别人听见了说,还真是头驴,听,正叫呢。算是挽回一点做驴的尊严吧:)很怀念文科那坨屎,是他让我真正理解了做驴的尊严;他臭气熏天但给了我很大的信心;这么长的一条路,天上打雷下大雨,黑漆漆的天没路灯,地上都是水;一路趟过来也不害怕,也没怎么打滑掉链子。

有时候也想起那头小鹿,哀求的眼光蒙着一层水气。于是就告诫自己要争气,别活得跟团屎似的,让自己的爱人一点办法都没有无可奈何还要去求别的人。

Sunday 16 November 2008

The Difference Between Distributed and Centralized Version Contr

分布式版本控制和中心版本控制的区别

分布式版本控制系统,比如Git,在用户端保存个版本以及个版本的内容,和服务器端的一致。

中心版本控制系统,如CVS,SVN等,在用户端保存最新版本及个版本信息,当用户需要旧版本内容时,需要向服务器端请求。

Saturday 15 November 2008

Portland is actually pretty nice






波特兰真的很不错

(译自 http://random.bluemuffins.com/?p=218)






我怀疑是否是我正最终开始暖化了波特兰。这周开始的天气吓人,但今天和昨天终于放晴。宝蓝的天空下,城市闪耀着秋天各种不同的颜色。我从来没有想过我会说这个,但有了这天气和色彩,或许世界并不会真正进入衰退。整个星期,整个月,我听到和读到的新闻都是经济进入大萧条,LA的火灾,冰川融化,还有其他很多坏消息。我不认为坏消息可以那么多的影响到个人。或许是到这个岁数了吧,我开始小心担忧。在学校的时候,无论经济好坏都不能影响到我。那时候我没有工作也不必担心失去工作。

我真应该好好享受好天气,去拍一些照片,也顺便学学摄影。

Monday 10 November 2008

面对爱情

面对爱情,谁也没有资格说三道四。

Saturday 8 November 2008

一个朋友


一个朋友


在中镇(middle town)有我一个朋友, 叫约翰。


中镇在大西洋边上。直通通趟过去,就到欧洲了。那里是富人的天堂,遍地豪宅和酒馆。也是夏季旅游的圣地。不过冬天由于太冷,很少人去。富人们大多不在,一座座城堡空着,几乎没有人。遍地的树叶也少人扫。


几年
的一个冬天我在那里干活。我从遥远的中国,来到这里,帮约翰他们对付一堆写得破破烂烂、时时出错的程序。收工之后,约翰就带我去酒吧喝酒。那的本地啤酒是新港暴(Newport Storm)。青岛啤酒在那卖得也很好。有时中午也喝一杯。


约翰原来有一辆日本车,已经开了很久。


约翰说,他喜欢修理车,修理房子,修理女友,修理一切(fix car, fix house, fix girl friend, fix everything)。 女人没有自修理的能力,而且只有男人才能修理。



很喜欢这句话, 每每对人提起。


去年遇到了他。他发我新车的图片(还是一辆日本车)。 劝我也买一辆。 而且必须在今年。



我说我不是单身了。


——要么今年买,要么永远不买!


——不给买就天天喝酒,让她必须做一个选择。


:-)



这个混劲儿真是可爱!


有一天约翰劝我要一个孩子。他说,他不知道要一个孩子是不是一个明智的决定,但他发现,他周围所有的朋友,都因为有了孩子而更快乐。

于是我问,那你呢?为什么不要?

——我女朋友年纪大了,要孩子有危险;那就给她要一条狗吧!

很喜欢这种简简单单的快乐,而这种快乐离我渐渐的远;每想到这一节,就笑一笑:-)

我回来的时候约翰送了我一瓶红酒。中镇的酒又好又便宜,十几美元的就算顶好的了。我又拿着这瓶酒去看我的导师。我俩喝的正高兴的时候,见师母的眼睛里掠过几丝担忧的神色。于是我就劝导师少喝点。

——我没喝多啊,他说

——那你算算时间流逝的速度,或者说每秒有多少时光流过?

——One,但这个东西没有量纲,很难在物理中找到意义。

那是我导师最后一次喝酒。后来他的痛风越来越重了。不能喝酒,不能吃肉,不能吃豆制品。痛风很磨人。他在写一本量子力学的书,一直写一直写。我攒的那本书却先出了。他向我要了一本,说要看看。我给他书的时候心里很难受;他教我物理,我却在编程;他叫我沉静,我漂浮在空气的微尘里;他在痛风里写东西,我迷失在生活的洪流里。他看后说看不懂。我说那本来也是很空洞的东西,不是用来懂的。

又一天遇到约翰。他说他换了个出差多的工作,这样薪水会稍稍多些。

——那你女朋友是否高兴?

——她可以随便开我的新车了,没人跟她抢。

——那你呢?

——辛苦些。不过和西部人拼酒还真带劲!

北京的天空没有那么的蓝。有时是灰色的。有时甚至是暗红色的。有几根头发白了。岁月在我们的身心留下痕迹。想起约翰的眼睛,跟大西洋的天空一样的蓝;他出生是个孩子,50年了还是孩子,只有18岁那年假装苍老过。我出生是个孩子,10岁就慢慢苍老了,只有18岁假装年轻过;之后就很快越过百年,见了周树人他们,跨千年去见庄子;胡子长得盘在腰上;眼睛慢慢变灰变红;忧忧扰扰假装洒脱像一个蛆虫。才发现约翰他们文明的高深了。


Thursday 6 November 2008

老残游记

儒治世,释论死,道养生。儒释道个守其一。乱之则巫,证之则愚。

老残时证时乱。因此叫铁补残。

Thursday 16 October 2008

学过ETest

(require 'etest)

(etest
("`ok' test"
(ok 1))
("`null' test"
(null nil))
("`eq' test int"
(eq 1 1))
("`eql' test float"
(eql 1.1 1.1))
("`equal' test"
(equal '(1 2) '(1 2)))
("`error' test"
(error (/ 1 0)))
("`noerror' test"
(noerror (/ 0 1)))
("`like' test"
(like "Hello" "^H\\(e\\)")))

还算好用吧。但类C的代码写的太多,一时还没转过弯来。

西游记里骂人的话

或者骂神仙妖魔的话,是:
不当人子

最常见的是连着骂:
不当人子,不当人子

唐僧骂过,甚至如来佛都骂过。

大致翻译过来应该是:
混帐兔崽子王八蛋!

Sunday 12 October 2008

读庄子

正在读《庄子全译》。译注者张耿光,主要研究汉语的。其所加的注释大都是语言层面的。至于关乎思想的,评的很少。因此这是一本很好的书。

不知鲲在北冥好好的,怎么忽然要去南冥。北冥和南冥之间,想是没有水路相同的。要不然,鲲不会由鱼化为鸟的鹏。这是一个旅程,由北向南,有目的但并无理由的迁徙。人世间的每件事都有一个理由。但鲲鹏做的这件事,却是个例外。

于是背靠苍天,空气在天底下的生物之间流转;宇宙之大,不知有没有尽头;速度太快,以至于跟静止没有区别。

如果在北冥呆久了,就不妨化作鹏,飞到南冥看看。没有翅膀的请找庄子。庄子是使斧子的;个把小时就能砍一副,枯木头的。肯定是不结实的,因此要在北冥涨水的时候起飞;这样掉下来不至于头扎进泥里。

Music Radio

emms里配置mplayer播放器用的正则表达式,太长了,基本看不懂。但我要听音乐之声Music Radio:

(defun music-radio()
"Listen to CNRadio"
(interactive)
(define-emms-simple-player mplayer '(file url)
(regexp-opt '(".ogg" ".mp3" ".wav" ".mpg" ".mpeg" ".wmv" ".wma"
".mov" ".avi" ".divx" ".ogm" ".asf" ".mkv" "http://" "mms://" "rtsp://"
".rm" ".rmvb" ".mp4" ".flac" ".vob" ".m4a"))
"mplayer" "-slave" "-quiet" "-really-quiet")
(emms-play-url "rtsp://211.89.225.1/encoder/cnr3"))

Sunday 5 October 2008

村庄

无言的村庄,黄土埋没的村庄
坐落在圣人或盗贼出没的地方

黄帝还在村南的学堂朗朗读书;月亮下子綦
和他八个儿子坐在田埂上聊天,露水打在梱的发梢,明天
要去一趟燕国;孔丘在灯下复习功课,胡子都花白了
还是通不过,入学的考试

鲲在梦里
变成一只鸟,飞向南方的海
那里正生长着的狮陀之国
长成之后会飘向西方

惠子鼻尖上沾着白垩,庄周运斧如风
无用的树下,柳下跖呼啸而过,季在叹息;孔丘又将失去
一天的口粮:好多的仁义,才淘换得的

许由和尧,在人字形的天梯上,愈聊愈远
舜出现的时候, 许由早已不见
墨翟仰视
禹的小腿,漆黑而无毛;水退了,启也已长大
武王的征伐,诸神的黄昏,映照着
远去的青牛

大鹏不记得自己曾经
是一条鱼;野马与浮云
天也苍苍

Thursday 25 September 2008

赤兔马

丁原死于公元189年,吕布死于公元198年,关羽死于公元220年。假设赤兔马在丁原手里3岁,到他随关公赴西,也有34岁,服役达30年之久。其寿命在马里面算是很高寿了。服役时间也可以创下一个吉尼斯世界纪录。

因此赤兔马的死亡是很正常的。

赤兔马的主人换了好几茬。他并没有忠于丁原,没有忠于董卓,没有忠于吕布,难道会忠于关羽吗?三英战吕布的时候,赤兔马应该见过关羽,那时候的关羽是以吕布的敌人出现的;马的记性应该是很好的。

Wednesday 10 September 2008

我的肚子

起先我并没太在意它的存在。小猫提醒了我。

我半躺在摇椅上,就有了一个还算平的台。于是我的小猫就跳上来了。

听说吴大猷的肚子上可以放一盒粉笔。

开始它趴着睡,我的呼吸动了它的胡子;于是就侧着睡;有时调个头。

我打一个喷嚏它就可能翻下去。作为一只猫睡梦中都可以平安落地。

Monday 8 September 2008

新认的两个字

赍:拿的意思,念ji,一声
囟:象形字,娃娃脑瓜顶最后长好的那块,念xin,四声

Sunday 31 August 2008

佩雷斯如是说

土地的争夺不那么重要了。新的争夺在孩子的教育。
要看的长远,还要见的细微。

Tuesday 19 August 2008

MPlayer播放mkv时的错

MPlayer interrupted by signal 11 in module: decode_audio


我还没有找到更好的解决办法。基本上是由于MPlayer内部实现的a52引起的。

一个临时的办法是不用内置的a52,而是用外置的ffac3:

mplayer -ac ffac3 bj2008.mkv

Sunday 3 August 2008

煎猪扒

纯瘦肉一斤,切片,加料酒,盐,葡萄酒腌十分钟

扑生粉,鸡蛋打匀。拖匀。

平底锅开油,煎肉。焦黄检出。

Monday 28 July 2008

房龙地理

购得房龙地理(地球的故事),商务版。

Monday 21 July 2008

茄子面

干姜煸炒,放大蒜,大茴,出香放肉
五花肉比较好,切丁,多放油
放茄子翻炒,多放油
圆茄子比较好,切丝
勾芡贴边放,大火冲开
转小火,另起一锅煮面
水开时放油麦菜,水变绿捞起
放面
关茄子火
关面火
捞面,过水或不过水,放油麦菜,放茄子

Sunday 20 July 2008

童话

太阳躲到哪里去啦?

这个长凳是我的,

我用不完,你可以坐在另一边,

我耳朵上有个小豆豆,你耳朵上是什么?

我记得山在这边,什么时候跑到那边了?

三岁半,

小猴子,

今年属小白兔,明年属大灰狼,

狗尾巴草咬咬咬,

给我戴上吧,家里有小蝴蝶,

Saturday 19 July 2008

Emacs与Blogger

在Emacs里往Blogger发布,有几个办法,但大多都不很成熟。比如emacspeak的那套东西,用起来麻烦死了,也不支持中文。这个麻烦的方法应该算正统吧,因为直接用的Google给的服务接口。



还有个办法:

Emacs Jabber - GTalk - imified

用Imified机器人的Blogger服务;配好后用着还算方便。但扩展性不好。

还可以用发信的办法来写博客。在服务器端配好后,只需要发一封信就可以写一篇。信的主题对应博客标题,正文对应正文,还算自然吧。

发信写博客的扩展性很好。比如下面就是一个扩展:

(defun blogger ()
"Sent current subtree to my blogger"
(interactive)

;; Prepare subject
(org-back-to-heading)
(setq beg (posix-search-forward "]"))
(end-of-line)
(setq subject (buffer-substring beg (point)))

;; trim
(if (string-match "\\`[ \t\n]+" subject)

(setq subject (substring subject (match-end 0))))
;; Prepar mail body
(setq beg (+ 1 (point)))
(outline-end-of-subtree)
(setq body (buffer-substring beg (point)))
;; Draft a mail
(message-mail "username.password@blogger.com" subject)
(insert body)

;; Arrange the mail body
(goto-line 4)

;; Line 4 is at just ahead of the body
(while (= 0 (forward-line 1))
(if (> (- (line-end-position) (line-beginning-position)) fill-column)
(unfill-paragraph)))

;; Sent it to blogger directly if type blogger without C-u

(if (not current-prefix-arg)
(message-send-and-exit)))

这个扩展写的很粗糙,也只是针对我的使用而写,不通用。不过已经可以满足我的需求了。

Friday 18 July 2008

回家前夜的橄榄枝

忽然觉得机器人瓦利里的Eve看起来像一只鸽子:她寻找的是橄榄枝。

诺亚看到鸽子衔来的橄榄枝,说,我们可以回去了。

胖船长看到Eve带来的橄榄枝,也知道是回到地球母亲怀抱的时候了。

绿色植物是地球的肺。绿色是憔悴的地球母亲脸上的一抹红润。

Monday 14 July 2008

机器人的爱情解析

忽然发现机器人是渴望联网的。

瓦利在地球这个垃圾场整理垃圾,整理了几百年,一直处于信息孤岛的状态。他往四周发的信号,都有去无回,没有任何反馈。

个体在信息孤岛的状态很容易怀疑自己的存在。笛卡尔说,我思故我在。但单独的一个,怎么证明他在思考呢?坚信自己存在甚至都没意义,因为没有另外的个体的不相信,因此也找不到需要去说服的。机器人也需要确信自己的存在的。连存在都不能确信的状态,也就是孤独的状态。

有时候并不怀疑存在本身,而是怀疑存在的意义。一讲到意义,单单的个体就不够了。必须要有一个群体,哪怕是只多一的两个。

因此爱情源于孤独;孤独源于对存在或存在意义的怀疑;怀疑存在源于信息读写的不能够。

机器人瓦利

** 能量

估计瓦利应该是以核能为动力的。要不然他不可能工作几百年。可以看到他的某些部件有磨损;但还好啦,几乎每个部件都是可插拔的。

瓦利的两条履带晚上回来的时候会脱下来,第二天用的时候再穿上。

** 休息

瓦利也需要休息。晚上相对危险不适合工作。估计瓦利晚上睡觉的时候,会做一些硬盘整理、数据分析、以及对突发情况预案的工作。这在本质上和人类晚上睡觉时做的事情差不多。


瓦利早上刚起来晃晃悠悠,没睡醒的样子。也许是内存还没有完全加载进来吧,需要些热身。

** 音乐

瓦利有一个内置的单放机。可以录音。音乐对一个机器人意味着什么?使他心情愉快?而机器人的心情愉快又意味着什么?我理解音乐可以使机器人工作的节奏更明快,信息读写的出错机率变小。也许吧。

** 爱情

两个机器人如何产生爱情?比如,瓦利第一次被Eva吻,竟然激动得昏了过去。这在物理层面很难解释。对机器人,孤单的感觉又是什么?

Sunday 13 July 2008

机器人瓦利

瓦利是清理垃圾的小机器人。

Friday 11 July 2008

咬着眉头的静夜

小猫咬着眉头叫

过来吧
小猫跳上我坐的沙发
左边有点窄

扯着嗓子
我往右边挪了挪
于是她躺下
洗了洗脸
梳了两下其他地方的毛
呼噜几下就睡了
安静的夜

Tuesday 24 June 2008

说,谁能为emacs创建一个code_swarm,就像有人为eclipse和python创建的那样:

http://vis.cs.ucdavis.edu/~ogawa/codeswarm/


于是RMS跳出来了,说,那视频的格式呢?我们一定要坚持使用自由的格式,
比如OGG格式。

谁还坚持这个原则呢?还有谁呢?

Tuesday 17 June 2008

Thread, ThreadPool and ThreadLocal

孙悟空有72个线程(Thread)。他同时可以做72件事情。在没事的时候,这72个线程监听一个任务队列(Task Queue),等待任务(Task),不怎么消耗资源;当一个任务来的时候,这72个线程中的一个会得到这个任务,并去执行。因此孙悟空的这72个线程可以称作一个线程池(ThreadPool)。



线程池的一个线程有两种状态:等待任务和执行任务。等待任务并不意味着该线程是死的,就像人睡觉不等于死一样。有些任务在执行过程中,会往线程上放一些数据,这些数据只期望在线程内能访问到。这些数据叫线程本地数据(ThreadLocal)。



一个任务执行完了,执行该任务的线程会等待新的任务来执行。任务结束并不等于线程结束。那些线程本地数据也还在,不会被清理。因此当一个任务运行多次,可能发现一些现成本地数据是脏的(Dirty)。



那怎么办呢?



一个策略是设计线程池的时候,就考虑线程本地数据的清理。对一般已有的线程池实现,靠谱的也会考虑这个问题。

Sunday 15 June 2008

Java私有方法的测试

Java世界里最臭名昭著私有方法估计就是类java.io.ObjectInputStream里的`latestUserDefinedLoader'。这个方法的行为多少有点让人捉摸不透。这个类还是一个私有的、本地的方法(private, native)。

下面两个方法使`latestUserDefinedLoader'的测试变得容易:
,----[ Class LatestUserDefinedLoaderUtil ]
| public static ClassLoader latestUserDefinedLoader() throws Exception {
| ClassLoader latestUserDefinedLoader = (ClassLoader) invokeStaticMethod(
| ObjectInputStream.class, "latestUserDefinedLoader");
| return latestUserDefinedLoader;
| }
|
| public static Object invokeStaticMethod(Class klass, String name)
| throws Exception {
| Method method = klass.getDeclaredMethod(name, new Class[0]);
| method.setAccessible(true);
| return method.invoke(null, null);
| }
`----
为了测试latestUserDefinedLoader的行为,再增加两个方法:
,----[ Class LatestUserDefinedLoaderUtil Continue ]
| public static String getClassName() {
| return LatestUserDefinedLoaderUtil.class.getName();
| }
|
| public static URL getResource() throws Exception {
| String resName = getClassName().replace('.', '/') + ".class";
| String resource = Thread.currentThread().getContextClassLoader().getResource(resName).toString();
| return new URL(resource.substring(0, resource.indexOf(resName)));
| }
`----
下面是一个不那么复杂的测试用例:
,----
| public void testLatestUserDefinedLoader() throws Exception {
| URL[] urls = new URL[1];
| urls[0] = LatestUserDefinedLoaderUtil.getResource();
| System.out.println(urls[0]);
| ClassLoader classLoader = new URLClassLoader(urls, null);
| Class klass = LatestUserDefinedLoaderUtil.class;
| Class theKlass = classLoader.loadClass(LatestUserDefinedLoaderUtil.getClassName());
| assertNotNull(theKlass);
| ClassLoader latestUserDefinedLoader = (ClassLoader)
| LatestUserDefinedLoaderUtil.invokeStaticMethod(theKlass, "latestUserDefinedLoader");
| assertEquals(classLoader, latestUserDefinedLoader);
| }
`----

Wednesday 28 May 2008

Emacs 23.0.60 and mule-gbk

看来mule-gbk在Emacs 23.0.60是用不着了。注释掉就可以完成迁移:
;; (require 'mule-gbk)
(set-language-environment "Chinese-GBK")
(set-terminal-coding-system 'chinese-gbk)
(set-keyboard-coding-system 'chinese-gbk)
(setq locale-coding-system 'chinese-gbk)
(setq current-language-environment "Chinese-GBK")
还有chinese-gb18030可用。不过gbk对我就足够用了。

Tuesday 27 May 2008

Build Emacs CVS on Cygwin

大约在2008年2月的时候,Unicode的支持进了Emacs CVS。自那之后Emacs的CVS版在
Cygwin上就没有编译成功过。今天编译成功了。加了以下改动:
,----[ `src/sheap.c' changes ]
| #define STATIC_HEAP_SIZE (12 * 1024 * 1024)
| -->
| #define STATIC_HEAP_SIZE (32 * 1024 * 1024)
`----
期望这个改动能早点进Emacs的CVS。

Friday 23 May 2008

亲戚或余泣

亲戚或余泣
他人亦已歌
死去何足道
托体同山阿

Thursday 22 May 2008

大红灯笼高高挂芭蕾版

芭蕾舞和京剧很技术地裱糊了起来。装修大师张艺谋的映景之作。

苏童的原作妻妾成群阴暗潮湿。真实而扭曲的人性在残酷的现实里邪恶地张扬。看了心寒。

到电影版变了一次。月白变成了大红。巩俐在,人性还在吧。

芭蕾适合表达比较纯粹的概念。京剧好似盒子里的艺术。裱起来需要很高的技术。

到芭蕾版人没了。只剩下了性。性是剧情的唯一推动,除此之外想不到其他的理由。

Wednesday 14 May 2008

Java里的移位

在Java里,移位都是基于int的。如果不是int,就转为int再移位。

0xff >> 2 -> 0x3f
0xff >> 4 -> 0x0f

之上都是对int的移位。

那对byte的移位呢,比如:((byte)0xff) >> 2 -> ?

会做以下3步:
1. int 0xff -> byte,byte 0xff就是byte的-1
2. 移位前byte需要转为int, byte 0xff -> int, 变成了int的-1,就是0xffffffff
3. 0xffffffff >> 2 --> 0xffffffff, >>是用符号位1补位

因此下列断言是正确的:
assertEquals(0xffffffff >> 2, ((byte)0xff) >> 2)
或者:
assertEquals(-1 >> 2, ((byte)0xff) >> 2)
或者:
assertEquals(-1, ((byte)0xff) >> 2); // 由于是1补位,-1怎么移位也是-1。

>>补位用的是符号位,也就是说,如果符号位为1,就用1,否则用0

>>>补位只用0。这是两者的区别。

那0xff >> 2 和((byte)0xff) >>> 2是否一样呢?答案是否定的。

这里还牵涉到byte和int相互转化的问题。((byte)0xff) >>> 2相当于:
1. int 0xff -> byte 0xff, byte 0xff = -1
2. 移位前byte需要转为int, byte 0xff -> int, 变成了int的-1,就是0xffffffff
3. 0xffffffff >> 2 --> 0x3fffffff, 0补位,和0xff >> 2 -> 0x3f不同。

关于byte转int,以下断言也是对的:
assertEquals(0xfffffff0, (int)((byte)0xf0))
相当于:
assertEquals(0xfffffff0, (byte)0xf0)
这是有符号位的情况。没符号位的情况:
assertEquals(0x0000000f, (int)((byte)0x0f))

byte的移位并没有太多含糊的地方,只是byte移位之前,会转为int;再加上byte的
符号位,会把人搞糊涂。

一个办法是在byte移位之前显示地转int,别让byte自己转。操作看起来会清晰些:
assertEquals(0x3f, ((byte)0xff)&0xff >> 2)
或者:
assertEquals(0x3f, ((byte)-1)&0xff >> 2)
用0xff并一下,这样byte的-1转为int就是255了。刚好和C里的无符号byte一致。

大部分教科书的移位是按C的无符号byte讲的。

这样这些教科书里的东西也可以用起来了。

Thursday 8 May 2008

猪有两个特点,一个是爱吃,一个是爱睡。

女人靠睡,男人靠喂。可以讲,女人和男人,各有猪的一个特点。

在一个屋檐下,住着一个男人,一个女人。

如果男人能像猪一样的吃,女人能像猪一样的睡,这个屋檐,才可称为一个家。

-- 像猪一样吃比较好实现,像猪一样睡,难啊!

- 因此家是男人的。

Sunday 4 May 2008

MPlayer转音频

MPlayer用来转音频很好用。原因是MPlayer支持的音频格式多,而且MPlayer还是个视频播放器。用熟了之后简直就是万能的转换器。

,----[ mplayer -ao pcm:file=... ]
| mplayer -ao pcm:file=file.wav file.avi
`----

`file.avi'是什么格式无所谓,只要mplayer能播放就可以;当然电影也可以;可以用上面的命令扒电影配音。

转为wav格式后,再转其他的格式别的转换器就接上了。

在Cygwin下,不知为何flac不工作。因此flac的转换就交给MPlayer来完成。做的还不错。

Saturday 3 May 2008

EMF静态模型的序列化

EMF建模生成的静态模型,都派生自class:

org.eclipse.emf.ecore.sdo.impl.EDataObjectImpl

在EDataObjectImpl类里,定义了writeReplace方法:
,----[ writeReplace ]
| public Object writeReplace() throws ObjectStreamException
| {
| return SDOUtil.writeReplace(this);
| }
`----

这样,在做Java序列化的时候,系列化流的处理在此处被截获了。因此,如果想自己处理Java的序列化可以重载`writeReplace'方法。

`SDOUtil.writeReplace'大体上会找找有没有DataGraph,没有就抛错误,有就用DataGraph做序列化了。由此有一个方法就是把DocumentRoot放到DataGraph里去,省得重写`writeReplace'。也是可以的。DataGraph的序列化只能做DocumentRoot;把孤立的类型放进去,序列化可以,反序列化就不行了。

DataGraph序列化出来的是XML格式。对一个EObject,DataGraph的序列化会调用其`eIsSet'方法看看某个feature是否设,如果设了就调eGet拿过来序列化。由此可以看到`writeReplace'和DataGraph的序列化可以共存,并且彼此没什么影响。`eIsSet'和DataGraph序列化有关,这一点很重要,可以结合`writeReplace'用用看,很有意思。

Saturday 19 April 2008

尤利西斯

很早手边就有尤利西斯;读了几次,也没有读懂——甚至都没有读懂的迹象;撞向一面墙,又弹回来的感觉。



这两天又拿起来看,发现能读懂了。不过只限于前两章。第三章就显得很吃力很吃力了。可能还需要放一放。



又进了两本房龙的书:

1. 人类的故事

2. 宽容



之前只读过房龙的《人类的艺术》。



谈起房龙,是在《战争风云》以及《战争与回忆》里看到;这两本有关二战的书是小说。

Monday 7 April 2008

敲山震虎 - 老鬼

老鬼的分身在给新鬼讲量子力学的时候,发现一个更新的鬼,加入到新鬼的行列。从眼睛绿的深浅看,也就吃了一碗炸酱面的样子。但眼神里有一种非鬼的专注。将来走线程还是进程的路子还说不定。根基好,最大值最少能到1024。慧根快顶天了。山太小,也许将来能换个地方。算到这,老鬼的分身询问了一下主控进程,主控进程回答说这种地方是存在的。

老鬼咳嗽了一下,示意大家安静。大家静下来的时候,老鬼点起一根炊烟,开始讲了。

- 在座的,都是死过的。世上的,都活过,但他们都没死过;谁没活过?但并不是谁都死过。

这时候有一个新鬼站起来,提了一个问题。

-- 如果考虑转世的话,生生死死的生命靠灵魂串起来,那也可以讲世上的所有生命都曾经死过。

老鬼说,转世说不符合热力学第二定律,理论上就不对。在实践上,也没有支持转世说的证据,至今也没有发现转世的个例。

-- 那转世灵童呢?

在公开场所,最好不要讨论涉及宗教的问题,老鬼弹了弹烟灰说。

-- 那唐僧呢?

老鬼的分身问主控进程,可不可以调唐僧过来,主控进程同意了。因此唐僧进来的时候,老鬼并没有太意外。

- 老唐,给大家讲讲你的身世吧。

唐僧讲自己的身世。父母的不幸。他和悟空八戒的深情厚谊。沙僧的忠诚。还有小白龙。

-- 那你有没有转世呢?传说你世世都是好人。

- 我只有一世。这在我的档案上写得很清楚。

-- 那为什么妖怪都想吃你的肉,说可以长生不老?

- 给吃肉找理由还不容易?吃肉长身体,吃面长志气。妖精们就爱吃肉,吃得都没脑子了。

老鬼说,大家要是没问题老唐就回了,人忙着呢。于是唐僧就撤了。

死,老鬼说,和生不同,生的前面是死,死的前面还是死;时间到了,大家去吃炸酱面吧。

Wednesday 2 April 2008

敲山震虎 - 山鬼

老虎的阴魂见到山神的时候,山神正要出去。阴魂哗啦哗啦地趟过来;山神说,你怎么才来?

- 我看到无数个自己在空中漂浮——好不容易才合到一起,老虎说。

那是阴气不够,以后多练练就好了;老鬼那门量子力学的课可不妨选修一下。累了吧?坐下歇会儿。饿吗?食堂里有炸酱面。

- 我不吃炸酱面,我还想吃肉。

炸酱面里就有肉。也别老想着吃肉,吃肉长身体,吃面长意志;你的身体不是搁下了吗?其他的在吃。吃肉发松发飘。

- 嗯

到新的环境,尽快地适应;有很多事等着做。你还有什么问题吗?

- 有一个。山里这么多个阴魂,你一个个地谈话,怎么也不见你忙?

我是多线程的;同一个时刻,我在此也可以在彼。你当下是但线程的,这是因为阴气不够;阴气够了,慢慢会两个线程,三个线程;甚至更多的线程。孙悟空有七十二个线程——

- 他一个跟头还十万八千里呢!

这就是谣传了。他在此又可以在彼,如何计算的速度?有两个线程,就可以突破光速的限制,何况七十二个呢?

- 那你有多少个?

我现在有七个;估计明年会提到八。你慢慢练,多选些课,长长阴气——现在阴气太轻了,还想吃肉;争取明年提到二吧。

- 到我二的时候,我就可以做一个真正意义上的山鬼了吧?

你现在就是一个真正意义上的山鬼了。你的线程数已经不是恒一了,而是在一和二之间摇摆;少吃些肉就会更二些。

- 那我去吃炸酱面去了

山神看了看新山鬼远去的背影,又点起了一支炊烟。天蒙蒙亮,山里一支一支的炊烟,有的是山神点的,有的不是。

Monday 31 March 2008

敲山震虎 - 山神

山神回来的时候,老虎还倒在血泊中,大炮和猎枪已不在了。

山神第二天还要外出办事,需要收拾收拾一下东西。山还在睡觉。山记得的事情太少了。山神不记得这只虎什么时候来的。山可能都不知道什么是虎。虎不在了就不在了。不过山神还是查看了一下老虎的尸体。死的很狰狞。食腐动物在边上,多少有些犹豫。山神点上一根炊烟,陷入了沉思。

山神出去的时候山在沉睡。

Wednesday 26 March 2008

敲山震虎


拿着拳头或者榔头去敲一座山基本敲不动。就是让共工来撞效果也不好。老虎还以为是地震呢。

最好使用大炮来敲。山动不动不管,起码声响是很大的。


山说谁啊,没来由地放炮。山想雪崩一下但想起自己早已经不是雪山了。山想来想去还是睡了。


不用地动山摇,只要使各个动物的耳膜受到强烈的刺激就可以了。


虎听到很大的声响,很不解,心想这怎么回事,我得出来看看。因此虎出来了。

当然其他动物也听到了,但他们选择了沉默,暗暗躲藏。这也是虎与他们的不同之处。虎有虎的气概。

虎出去的时候看到了大炮。

虎扑向大炮的时候猎枪响了。

Sunday 23 March 2008

Emacs和Eclipse

Eclipse受Emacs影响是应该的;毕竟Eclipse是后起之秀。

最近在Emacs开发邮件列表里有关在Emacs里实现Eclipse一些功能的讨论,可以看出Eclipse是多么的成功,以至于她的老前辈,也在效仿她。

Thursday 20 March 2008

猫的一声

眼睛总是那么忧郁。什么也不说,也不要求。总是那么乖。走路轻轻的。还以为有什么坏心眼哪。

于是就走了。天蓝地茷。

Sunday 16 March 2008

猫的一生

我的大猫今天死了。

他几天不吃东西。先是去农大动物医院开了些药,没有作用,还是不吃,没精神。

我昨天回来的晚,带他去输液。同输液的有一只濒危的狗,非常大声而恐怖地呻吟。他有些怕,我拍拍他脑袋,安静了。他一直很安静,甚至走的时候。

刚来我家的时候因为胆子小,见人就呜呜叫,没法洗澡。就不让待在床上或沙发上。后来养成了习惯。这几天他病的时候,有一次跳上了沙发。我跟他说待着吧。他好像想了想,还是下来了。

家里还有一只小猫,每次洗澡都像杀她那么的叫。大猫就蹲在浴室外,很关注。轮到大猫洗澡的时候小猫就玩的没影了。

大猫喜欢挠痒痒。舒服地在地上打滚。

他俩会打打闹闹,在大猫没病的时候。

如今只剩下小猫一个,她还是那么的淘气。多少有些奇怪,在屋子里来回的走。

Saturday 8 March 2008

黑白铁

还在她很小的时候,一天,妈妈带给她一只小猫眯
她们玩了一整天,捉迷藏,做游戏

天黑了

她想把小猫留在房间里,妈妈坚持小猫晚上应该呆在院子里
是夏天
她坚持了很久,妈妈还是把小猫放在了门外
刚关上门,就听到一声惨叫
小猫倒在血泊里,喉管被咬断

她什么也没说,走进自己的房间
妈妈也没说什么,走进自己的房间

Thursday 21 February 2008

正月十五

漫天的烟火;旧年过去,新年来了。

小猫也长了一岁;她跑来跑去,有时惊慌地望望窗外;后来也睡了。

月亮圆的浑浊;中年的眼睛。

Wednesday 13 February 2008

洗碗的技巧

洗碗没那么难的,就算是冬天,就算水很凉。对付水凉,最好的办法是适应它,用最凉的水冲一两分钟。手适应水的凉之后,洗起来就很简单了;有时候甚至有依赖性,干脆一点热水也不带用的。洗完碗之后,手会发热,那时候很舒服了。因此下次也很想洗。

Wednesday 16 January 2008

如何甄别好的程序员


译自How to recognise a good programmer

作为管理人员,如何甄别好的程序员?

这件事并不像听起来那么容易。来自简历的履历经验信息用处有限,因为伟大的程序员并不是总有“正式的”经验用以展示他们的伟大。实际上,很多来自简历的经验信息还可能误导。然而,即使从简历里,也可以得到不少微妙的线索,用以弄清楚一个程序员到底是不是伟大。

我自认是一个相当好的程序员。而且我在业务管理这边花了相当多的时间,为项目筛选技术简历,面试等。鉴于此,我认为我还是有一点甄别好的程序员的经验的,我也愿意把这些经验通过此文和大家分享,希望其有助于其他的“业务管理人员”来甄别优秀程序员。还有,谁知道呢?也许一些有潜力成为还没有成为优秀程序员的程序员,翻到这篇文章,读过之后认识到应该如何提高才能优秀(尽管,正如我将要分辨的,本文绝对不对所有程序员有效)。


在他的一篇名为18个错误扼杀成长 的文章里,Paul Graham提出如下观点:
“... 什么扼杀了90年代后期大多数电子商务企业的启动?是差劲的程序员。很多那些公司最初由业务人员组成,这些业务人员认为,假如你有了一些好点子,只需雇佣程序员来实现它,就可以完成公司的最初成长。这件事实际上比听起来难许多——几乎难到不可能的地步——因为业务人员不能辨别哪些是优秀的程序员。他们甚至根本就见不到真正优秀的程序员,因为一个真正好的程序员绝不希望自己去做只是实现业务人员的想法的工作。

实际的情况是,业务人员选择他们认为是优秀程序员的人(比如在他的简历里有微软认证开发者证书),但这些程序员并不优秀。于是业务人员发现他们所组建的团队就像二次世界大战时的轰炸机,而他们竞争对手却是喷气式战斗机一样呼啸而过。这种启动就像一个大公司的启动一样,只是没有大公司所拥有的优势。

那么如果你不是一个优秀的程序员,如何挑选优秀的程序员呢?我不认为有答案。我想说你最好去找一个优秀的程序员来帮助你雇人。但既然你不能甄别优秀的程序员,你怎么能找到第一个优秀程序员呢?”

我不同意Graham先生这个观点。我认为一个“优秀程序员”有很多明显的特征(并且,反过来,一个“不那么优秀的程序员”也有明显特征),这些特征很显而易见,以至于甚至业务人员都有能力分辨。在本文末尾,我将把这些关键的加分特征和减分特征总结为一个列表。

#1 激情

在我的从业经验里,我见识过一种以前从未见识过的技术人员:职业程序员。这种人之所以做IT是因为他们认为IT一个好职业。在他们的业余时间里,他们不做任何的编程相关的事。当发现我在家里有一个局域网和三台机器的时候,他们很吃惊。他们只在工作中编程。他们不学新东西,除非参加培训(或者为了得到一个要求那种技术的工作)。他们把编程看作白天的工作。他们并不真正喜欢在工作之外讨论编程。当在工作中讨论编程的时候,他们也特别地没有热情。基本上,他们缺少激情。

我相信好的开发人员对编程总能充满激情。好的开发人员甚至在没人付钱的情况下也写代码。好的程序员讨论他们正做的一些技术细节,能把你的耳朵说飞了(但是,的确,说真的,他们所讨论的是真正值得讨论的)。一些人可能把这看作不善交际(的确是),但如果你想甄别一个好的开发人员,这种以牺牲社交圆滑为代价换取的对他们正在做的技术的激情,是一个优秀程序员的显著特征。你能录用这个兴奋地谈论自己正在用的技术整整半小时而不见停止的家伙吗?如果能,那你就将成为一个赢家。

#2 : 自学和爱学

编程是在打极速运动的靶子。不到一年,不是新技术替代旧的,就是现有标准被废掉,开发世界的半壁江山都跟着变了。这并不是说所有优秀程序员都能够跟上所有这些变化,还冲在最前沿。而是说,有一类程序员是从来不学习新技术的,除非被迫,因为他们不喜欢学习新东西。这些程序员通常在大学学习编程,并且期望在大学和公司指派的培训课程里学会所有的技能。

如果你正在考虑是否雇佣某个程序员,如果他曾经说诸如“我可以胜任,只要送我去培训一个星期,我就会在这方面做得很好”的话,那就别要他了。一个好的程序员学习新技术并不需要培训。实际上,伟大的程序员将是那些讨论某个新技术能把你耳朵说飞的家伙,尤其是,如果你还没有听说这个技术的话,他还会给你解释你为什么必须把这个新技术应用到当前的业务中去,甚至是在你所有员工都对这个技术一无所知的情况之下。甚至是在他自己也不知道如何使用这个技术的情况之下。

#3 : 智力

一些业务人员认为社交技巧的缺乏和智力的缺乏是一样的。实际上,智力有很多方面,而情感、社会方面的智商只是一个方面。好程序员都不傻。从不。实际上,好程序员通常都是你所知道的最聪明的人。事实上他们很多人也有很好的社交技巧。程序员都不善言辞的传言只是个传言而已。我曾经参加过几个伦敦Ruby用户组的会议,我可以说,除了很少几个特例外,大部分人都聪明、善谈、爱交际、有广泛的兴趣爱好等。不可能你打量一下在酒吧里闲谈的他们之后,就会断言他们“真是
一帮极客”——至少直到你进入一个小组讨论并意识到他们正在讨论的是如何使用重UI前端设计REST应用的最好方式的时候,才可能这么想。

这并不意味着他们在各种社交场合都感觉舒服。这也并不意味着,如果场合他们感觉舒服、足够放松,你将和他能有一个绝好的会谈,就像你和那些“社交上很行”人的谈话一样(或许更好,我所认识的大多数好的程序员的交谈都通常围绕实际有用的话题,而不是华而不实)。

可别雇佣一群笨蛋,却认为他们是好的开发人员。他们不是。如果你和他们在一个放松的社交场合下不能很好地交谈,他们很可能不是好的程序员。另外,任何一个显然很聪明的人至少有成为好的程序员或伟大程序员的潜质。

#4 : 隐藏的经验


这一条和“激情”那条有关,但这是一个很强的标志,因此我想着重强调一下。

我大约9岁的时候就开始在Commodore 64上编程。之后我移到PC上,做一些Pascal。当我14岁的时候我用C和汇编写了一个Ray Casting引擎,花了很多时间玩很酷的图形特效,直接操纵计算机的显卡。这就是我所谓的我的“起步阶段”。进入这个阶段的时候,我是一个不好不坏的程序员,缺少做真正复杂系统的那种自信。这个阶段完成之后,我拥有了那种自信。我知道我能胜任任意庞大复杂的编程工作,只要我在上面用心。

这些能在我的履历里出现吗?不能。

我坚信最好的程序员都有一个或两个隐藏的冰山,这些东西并不出现在他们的履历或简介里。有些东西他们认为写在简历里不真正合适,因为那些东西不是“专业经验”,但这些隐藏的经验里往往有一些可敬畏的成绩。在面试一个潜在的好的程序员时,一个好的问题可能是“能不能讲一个个人的项目——甚至就算是无关的也可以——在业余的时间完成的,并且不再你的履历表里的?”如果他们不能(除非他们的履历表有20页长),他们就可能并不是一个好的程序员。甚至有详尽履历的程序员也有非常出色的项目不在记述之列。

#5 : 多种技术


这一条相当简单。因为爱学习,喜欢尝试新技术,任何一个22岁以上好的程序员都能熟练掌握一打不同的技术,这是不可避免的。他们自己想不这样也没办法。学习一个新技术对一个有激情的程序员而言,是他能做的最有趣的事情之一。他们利用所有时间来学习,积累了大堆他们已经“玩过”的东西。他们也许并不是所有这些技术的专家,但所有称职的程序员都会熟练掌握大量的并不相关的技术。

“不相关”这一点正是玄机。每一个半吊子Java程序员都能列出一套技术像“Java、Ant、XML、SQL、Hibernate、Spring、Structs、EJB、Shell scripting”等。但这些都在相同技术之列,每个之间都直接相关。这一点或许对非程序员而言很难认识到,但可以通过和他们讨论,或者问他们技术之间的差别来辨别他们的技术是否多种多样。在一个技术里太专门是一般般的程序员的一个标志。

最后,如果他们所知道的技术有些不太成熟,那是一个好的肯定的标志。例如,今天(2007年11月),诸如Merb、Fex、RSpec、HAML、UJS、和许多其他...请注意这些都是相当接近的技术,因此几年内那些知道这些技术的人就等价于那些熟悉上一段所列的Java相关技术的人。


更新:作为一个对这点的澄清,这里实际有两个标志:多样和前沿。这两个标志是分离的。一个好的有时间跨度的技术多样性是一个加分的标志,无论这些技术是否前沿都是好的。而且前沿的技术也是一个加分标志,他们是否多样都是好的。

#6 : 资格认证

资格认证大多不说明有多好,更不说明有多差。这里列出的关键点是,当你正试图甄别出好的程序员的时候,有资格认证并不意味着他们矮人半头。很多好程序员有计算机科学的学历。很多并没有。认证,像MCSE或SCJP或类似的,也并不意味着什么。这些认证被设计成所有人都可以得到并想得到。他们只是说明拥有认证的人有某个技术一定级别的知识。它们是一个保险栓,使大公司的技术招募人员不用面试就知道“好,这个家伙知道Java,他得到的认证可以证明这一点”。

如果你正为一个小企业招聘,或者你需要真正聪明的开发人员组成强悍的团队实现企业里的敏捷开发,你应该将大多认证作为噪音忽略。对一个程序员是否好这个问题,认证并不能告诉你多少实质。类似的,忽略年纪。一些程序员在18岁的时候就令人敬畏。有些在40岁的时候令人敬畏。你不能把关于程序员品质的判断建立在年龄之上(你可能决定去雇佣一定年龄的人员来平衡公司的年龄比例;请注意年龄歧视在大多数国家都是非法的!)。

最后需要注意的一点,以我的经验看,大多一般般或差劲的程序员都是在大学为了他们的计算机科学课程而开始学习编程。大多数好的程序员很早以前就开始编程,并且是把编程当作他们自然的持续的爱好来看待。如果你的面试人员在大学之前没做过编程,并且他所有的经验都来自他的第一份工作,他很可能不是一个好的程序员。

免责声明


所有上面或下面的标志都不是一定有的。你可能发现一些伟大的程序员并不符合某几条。然而,我的观点是,一个伟大的程序员不大可能不符合所有的标志。类似的,你可能发现差劲的程序员也符合(或可能符合)某几条。但我坚信,一个程序员符合的越多,就越可能是那些难以琢磨的、作为一个业务人员你需要和他一起工作的、好的程序员。

总结

作为总结,以下是有助于你甄别好的程序员的加分标志或减分标志:

加分标志:

  • 对技术有热情
  • 把编程当爱好
  • 被鼓励谈起某项技术主题时能把你耳朵说飞
  • 这些年有一些出色的(并且通常很多)个人的非正式的项目
  • 主动学习新技术
  • 对什么技术用作用途有自己的观点
  • 对使用他认为不“正确”的技术工作感觉很不舒服
  • 聪明,对很多主题都有想法
  • 在上大学很早以前就开始编程
  • 有一些隐藏的“冰山”,很多个人项目躲在履历背后
  • 技术知识很杂,很多技术不相关(也可能不在履历里)

减分标志:

  • 编程只是日常工作
  • 不真正喜欢交谈,即使在被鼓励的情况下
  • 在公司提供的课程里学新技术
  • 无论使用什么技术工作都很高兴,“所有技术都是好的”
  • 似乎看不出聪明来
  • 在大学才开始编程
  • 所有编程经验都列在履历上
  • 主要关注在一个或两个技术领域(例如,与开发Java应用程序相关的一切),没有这一两个领域之外的经验
我希望这些能有所帮助。

Tuesday 15 January 2008

Term的配置


Emacs下的term基本上和其他的term一样。有两个模式,行模式和字符模式。使用C-c C-j进入行模式,C-c C-k进入字符模式。默认是字符模式。进入字符模式会发现C-x啥的不管用了,C-x被映射到了C-c,因此切换buffer就成了C-c b。开始有些不习惯,不过也无所谓。

Sunday 13 January 2008

约翰


失眠了遇上约翰。

他说他换了个常常出差的工作,薪水因此高了些。

我们谈起了孩子。他说他不懂是不是应该要孩子,但身边所有要了孩子的朋友,都很快乐。他说他正在变老,女朋友也正在变老;近半百了,女人这个年纪要孩子有风险。

那就给她买条狗吧,他欢快地说。

他有时的忧郁像他的眼睛,清澈而灰蓝。

人生应该如何我并不知道。

有时和他聊聊,然后就睡了。

Sunday 6 January 2008

Emacs Jabber和IMified Blogger



应该是把内容给了机器人IMified,它收到后帮我贴到博客上。另一个好处是在GMail里多了一个内容的备份——聊天记录权当备份。完美了。但IMified可够忙的,会话是一个有状态的活动;不管到哪都得记着,这不大容易,也比较耗资源。够难的。

慎独



四处无人的时候,才显见道德的力量。

Friday 4 January 2008

Emacs中写Blogger



之前,emaspeak出了一个Google Blogger的客户端。用了用觉得还是麻烦,甚至都不如直接去浏览器里写来得简单;这还是写英文;中文干脆就是不工作的。因此就没有接着用。后来发现可以用imified@imified.com这个GTalk的机器人写博客,又加上是用Emacs Jabber做的GTalk客户端,因此Emacs就和Bogger 很自然地结合起来了。imified@imified.com有时候会有些慢,大多时候反应很迅速的。写Blogger的使用方法也很简单,只是问标题,内容,标签啥的。不像Emacspeak那么繁琐——甚至都要人写XML,因此推荐大家用Emacs + Jabber +
GTalk + imified@imified.com;每个都很独立,每个也都很有用,结合起来完成一个较复杂的任务,而并没有增加复杂度;真是完美的结合。

Thursday 3 January 2008

两只猫都不太高兴



家里的两只猫都不太高兴。拉着脸,谁谁都欠他们猫粮,吃完了还欠下顿的。没个欢喜样,就这个。有时候小的很恍惚地看着我,像说你谁啊,怎么在这里。大的多是哀怨的。绝不快乐。从没见他们怎么笑过。