赵翔鹏的Blog Xiangpeng's Thinkpad

30十二/060

用自我约束的最后期限战胜拖延的陋习(转载)

"很多人常常面临这样的情况:本来手头有一大堆工作要做却故意拖延,上网去看看新浪的娱乐或者浏览热门贴的评论,要么干脆写日志。我们拖延重要的事情,像吸毒那样同时带有的负罪感和快感。这种拖延的吸引力在心理学上称之为hyperbolic time discounting(连续时间折扣),拖延的奖励相比浪费的是不对称的。换句话说拖延本身就是一种奖励。一位MIT的教授发现他如果让学生自己制定作业的最终期限(deadlines),学生自己会抵制拖延。当然一个问题是学生设置的最终期限是宽裕的,有弹性而非最佳。多数有拖拉习惯的人的经验是提早开始工作。"

30十二/060

Java相关技术学习资料收集

* AOP
What is AspectJ
AOP学习资源和AspectJ
AOP的确是个很强的idea,可以在一定程度上改变思维方式,同时也非常容易理解。

* EMF
OOPSLA 2006 - Introduction to EMF(附带一个很好的cheet sheet)
EMF真的是个好东西,比JAXB什么的强多了;加上GMF后就更强了。做个图形化的编辑器,可能只要15分钟!这个introduction是我见过的最好的了。

* xDoclet
ANT忠诚伴侣XDoclet基本任务手册
文档化注释可以做很多很多事。

* Spring, Hibernate
用spring、Hibernate、Struts组建轻量级架构

看了基于Spring的J2EE开发以后,越来越觉得企业应用开发很无聊……有了这些框架,程序员要做的无非是把用户的需求翻译成代码罢了,毫无创造性。

* MDA
AndroMDA
两篇openMDX的文章
看过一些MDA的工具后,我发现MDA并不是个空洞的概念,这里真的有点东西。PIM到PSM的自动转换的确是很有意义的。

14十二/060

Java6的一些新特征和例子代码

  • Web service更容易写了

看下面的代码,感觉跟C#很像。

1 package hello; 2 import javax.jws.WebService; 3 4 @WebService 5 public class CircleFunctions { 6 public double getArea(double r) { 7 return java.lang.Math.PI * (r * r); 8 }
除了@WebService,Java 6也支持@WebMethod。
调用web service是这样的:
public static void main(String[] args) {
    try { // Call Web Service Operation
        ws.CircleFunctionsService service =
        new ws.CircleFunctionsService();
        ws.CircleFunctions port = service.getCircleFunctionsPort();
        // TODO initialize WS operation arguments here
        double arg0 = 3.0;
        // TODO process result here
        double result = port.getArea(arg0);
        System.out.println("Result = "+result);
    } catch (Exception ex) {
    }
}

其中ws这个package可以由IDE从给定的wsdl文件自动生成。

  • 运行期编译Java源代码

以前要编译Java源码必需用javac.exe,如果想在运行时动态生成两个类,只能先System.exec调用javac,然后用 ClassLoader从硬盘上读取生成的.class文件载入类。这个过程因为要读写硬盘所以非常慢。现在可以直接用API调用javac了。

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable compilationUnits = manager.getJavaFileObjects(new File("MyClass.java"));
compiler.getTask(null, manager, null, null, null, compilationUnits).call();
manager.close();
  • 内置脚本支持

以前觉得djava是个好东西,现在java6内置了脚本支持,也允许脚本跟java之间的交互。看起来djava快要完全退休了。借用sun公司的一句广告:Perhaps You ThougHt yOu couldN't program with a scripting language and Java togetheR. Which will yoU Be trYing ?

jsEngine.put("namesListKey", namesList);
System.out.println("Executing in script environment...");
try {
    jsEngine.eval("var x;" +
    "var names = namesListKey.toArray();" +
    "for(x in names) {" +
    " println(names[x]);" +
    "}" +
    "namesListKey.add(\"Dana\");");
} catch (ScriptException ex) {
    ex.printStackTrace();
}
System.out.println("Executing in Java environment...");
for (String name: namesList) {
    System.out.println(name);
} 
  • 其它

还有很多新特性,比如更好的桌面效果,可以对内存做分析如memory dump,等等,可以参考
http://java.sun.com/javase/6/
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/beta2.html

14十二/060

Java6发布了!

内置脚本支持
以前觉得djava是个好东西,现在java6内置了脚本支持,也允许脚本跟java之间的交互。看起来djava快要完全退休了。

jsEngine.put("namesListKey", namesList);  System.out.println("Executing in script environment...");  try {    jsEngine.eval("var x;" +                  "var names = namesListKey.toArray();" +                  "for(x in names) {" +                  "  println(names[x]);" +                  "}" +                  "namesListKey.add(\"Dana\");");  } catch (ScriptException ex) {      ex.printStackTrace();  }  System.out.println("Executing in Java environment...");  for (String name: namesList) {    System.out.println(name);  }  

9十二/060

招聘会和温泉:一个周末的堕落

上午先陪yj去人大的招聘会,就当长长见识。集贸市场一样的体育馆里排满了展台,而这市场竟然要5块钱买一张票才能进去。哦,对了,招聘会跟集贸市场的另一个区别是,要卖的人站着,要买的人坐着。

来买人的企业中有些还算著名,也有些只看看展板就觉得很烂。好点的企业的柜台前都挤满了人,走了两圈之后我就觉得很累。我注意看了看计算机相关的招聘,大多都是招windows程序员,Java程序员,unix程序员,等等,总之就是招有项目经验能干脏活累活的人。偶尔有些是招比较专门的技术人员比如图像处理,或是gis什么的。

看着一群群手攥简历心情忐忑不知道该怎么把自己卖出去的毕业生们,想到明年的我或许也会成为其中的一员,逐渐我的心情就比较黯淡了,找工作真是不容易啊。得出一个小结论:软件学院的学生真是符合招聘会市场的需要,而我们做理论研究的的确不适合这种,嗯,小公司。

赶完集之后是12:00。出发,去九华山庄吧。心情不是很好,车坐的也不是很顺,下车后徒步走了好久。走在路上看着马路边的荒郊野地,还看见两只狗……心想这九华山庄的地方选得可真不错。

进山庄大门之后,感觉就完全变了,真tmd是个豪华的地方:白玉台阶,红木亭榭,雕龙喷水,假山奇崛。中央大泳池和四周一个个小巧玲珑的汤池上散布着缥缈的蒸汽,耳边又传来阵阵的古典音乐,仿古建筑的确给人一点点皇家的错觉……嗯,心情开始变好了。

周围的一切都很好,只是我忘了说一件事:在北京的冬天,只穿着泳裤(再披一件浴袍)露天欣赏美景显然不是一个很好的选择。赶快跳下水,没什么好形容的了,舒服~

尝试了游泳、温泉、药浴、桑拿、泡泡、红外照射等n种玩意儿之后,头开始发晕,天开始变黑,泡了快三个小时了。打道回府!

总结:温泉就是要冬天泡,40元比较值。

26十一/060

《大师的智慧》:15位计算机科学家的故事

大师的八卦故事总是很受人欢迎的。这本书描述了15位计算机科学家的生平,有点像《Heroes in my heart》。摘录若干经典句子如下:

  • Dijkstra

“科学就像时装设计一样,有自己的潮流。”
他花了好几年才发表他关于最短路径算法的论文,因为这种文章在当时的数学家看来是没有价值的。
“他后来的研究涉及到证明程序正确运行的技术,这是甚至在今天也不受欢迎的一种方法。”

  • Alan Kay

在IBM1401机器流行的时代,“程序设计是一种地位很低的工作,大部分程序员都是女的。”
面向对象的idea原来是来自生物学。想像一个对象就是一个细胞。

  • Knuth

对TAOCP的评价:“Dijkstra教我们分辨正确和错误;Knuth则教我们分辨不过如此和极其优秀。”

  • 结束语

“人们常常认为数学家年轻时总是有着丰富的想像力,而到中年时便有些迟钝。但看起来计算机科学家却并不是这样。拉宾在40多岁时发明了随机化算法;麦卡锡在 50岁时发明了非单调逻辑。巴库斯在60岁时才研究函数式语言,Dijkstra也是在这时候发展了数学证明的新方法。”

22十一/060

论文管理工具JabRef

JabRef是个很好的bibTex管理工具。跟Endnote相比,JabRef以bib作为默认的标准格式,界面更漂亮,比Endnote更小、更简单,而且是免费的。

JabRef支持把bib文件导出为很多其它的格式,比如html,Endnote,Docbook,等等。支持自动生成bibkey。

可以实现bib文件的合并。如果有两个bib文件,大多数条目相同,但只有少量的不同,可以先打开其中一个,然后File-Append database,选择另一个文件,然后Tools-Scan database - Find and remove exact duplicates即可。

注意2.2版非常不稳定,一定要下载2.1版

ctex上有一些相关的讨论。

14十一/060

除掉anonymouse.org的弹出广告

anonymouse.org是我平时用于浏览wikipedia等被过滤网站的工具之一。这个网站就是一个匿名代理,速度还挺快。唯一讨厌的是,每打开一个页面,都会弹出一个广告窗口。今天用greasemonkey插件,写了一行代码,搞定了这个问题。

greasemonkey是个著名的firefox插件,允许在网页载入后自动运行一段用户给定的代码来动态修改网页内容,比如删除页面中的广告,或者增加个按钮之类。关于它的介绍很多,还有一本简短的电子书“dive into greasemonkey“可以看看。有一个经典的greasemonkey脚本可以允许我们访问一直以来都被屏蔽的google网页快照。

安装greasemonkey插件后,用户只要写一个后缀为.user.js的文件,然后用firefox打开这个文件并选择“Install script"就可以了。

下面是我写的script文件(需要把它先另存为anonymouse.user.js,然后再用firefox打开就可以安装了):
// ==UserScript==
// @name Anonymouse popup remover
// @namespace http://xiang.blog.edu.cn
// @description Remove anonymouse.org popup ad. by zxp
// @include http://anonymouse.org/*
// ==/UserScript==
document.getElementById("mouselayer").style.display='none';

13十一/061

jjTree和javaCC学习笔记

javacc是类似lex/yacc的parser生成器,可以把一段文本转换为抽象语法树(AST)。
一般来说,用户首先要写一个jjtree文件(如eg2.jjt),然后执行jjtree eg2.jjt编译得到eg2.jj,再执行javacc eg2.jj就可以生成所有的.java文件。单独使用javacc也可以,不过基本上不能实用。
 
javacc的教程比较多,官方网站上的教程也很不错。相比之下,jjtree的参考手册里讲了很多细节,比如jjtree里面的堆栈,以及一些条件规则,但其实大部分都用不到。第一次看这个reference的时候感觉比较晕,比javacc的几个教程差多了。如果已经看完了javacc的教程,那接下来看一下这篇introduction,然后结合自带例子和eclipse的调试器来学习jjtree比较好。

我们通过一个例子来研究jjtree。下面的例子是javacc自带的eg2.jjt例子的改进版本。
--------------------eg2.jjt------------------------------
options {
 MULTI=true;  

 // 这句是让jjtree给每个非终结符生成一个对象,比如Expression就生成ASTExpression对象,这样才能通过jjtGetChild取得孩子!!!
  NODE_SCOPE_HOOK = true;  
 // 这个跟下面的jjtreeOpenNodeScope、jjtreeCloseNodeScope函数一起,用于从ASTExpression对象得到相应token。 默认情况下,javacc生成的对象里不保存什么信息,所以这里一定要设置一下。这个技巧参考了前面说的那个很好的introduction
}

PARSER_BEGIN(eg2)
package test;
class eg2 {
  public static void main(String args[]) {
    System.out.println("Reading from standard input...");
    eg2 t = new eg2(System.in);
    try {
      ASTStart n = t.Start();    // parse结果保存到n里面,这里Start是我们定义的一个非终结符
      for (int i = 0; i < n.jjtGetNumChildren(); i++) {
                Node node = n.jjtGetChild(i); //取得一个child,应该对应一个Expression
                Token t;
                for (t = node.first_token; t != node.last_token; t = t.next) {
                    System.out.print(t.image);    // 输出这个token对应的文本
                }
                System.out.println(t.image); //输出node的最后一个token,并换行
      }
      n.dump("");    // 输出语法树的层次结构。
      System.out.println("Thank you.");
    } catch (Exception e) {
      System.out.println("Oops.");
      System.out.println(e.getMessage());
      e.printStackTrace();
    }
  }
 
  static void jjtreeOpenNodeScope( Node node )
  {
    ((SimpleNode)node).first_token = getToken(1);    //这里的first_token,last_token都要手工加到SimpleNode.java中
  }

  static void jjtreeCloseNodeScope( Node node )
  {
    ((SimpleNode)node).last_token = getToken(0);
  }
}

// token部分略去,没什么意思

ASTStart Start() : {}
{
  Expression() ";"
 { return jjtThis; } //注意这里要写一句return,还有Start的返回值不能是void。
}

void Expression()  : {}
{
  AdditiveExpression()
}

void AdditiveExpression() #void : {}
// 这里可以设置#void,说明不必为此非终结符生成对象,也不会生成ASTAdditiveExpression类。
// 因此,Expression的child会包含MultiplicativeExpression
{                                
  (
    MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )*
  )
}

...
// 后面的很多细节都略去了,请参考自带例子,总之只要会BNF就可以了。

// 其中的LOOKAHEAD细节我没有花太多时间研究。大部分时候,我们只要先找来一个别人写的jjt文件,然后改改就可以了。
--------------------eg2.jjt------------------------------
    
30十/060

澳门,我又来了~

来澳门开会一周。

小岛还是老样子,朋友们也还是老样子~虽然我也带了相机,不过迄今一次都没拿出来过。天气闷热无比,中午穿着T恤也猛出汗,幸好早晚还算凉快。晚上挤公交回zl家,那车堵得简直跟中关村一样。等到吃过晚饭就已经8:00了,然后跟zl一起玩ps2,呵呵,这时就有一点度假的感觉了。

说到开会,这两天是一个workshop叫做AWCVS,感觉好多人都是做code analysis/verification的,跟我们做的方向不尽相同。接下来的ICFEM应该更有趣一些。虽然也不是第一次做报告,不过这次开会我一共要做3个报告,真够我准备的了~

   下一页