??xml version="1.0" encoding="utf-8" standalone="yes"?>国产三级久久久,99久久精品99国产精品,久久久久99精品久久久久http://www.aygfsteel.com/ajoo/zh-cnThu, 05 Jun 2025 22:53:08 GMTThu, 05 Jun 2025 22:53:08 GMT60用Neptune来交互执行antdhttp://www.aygfsteel.com/ajoo/archive/2006/02/10/30123.htmlajooajooFri, 10 Feb 2006 05:06:00 GMThttp://www.aygfsteel.com/ajoo/archive/2006/02/10/30123.htmlhttp://www.aygfsteel.com/ajoo/comments/30123.htmlhttp://www.aygfsteel.com/ajoo/archive/2006/02/10/30123.html#Feedback0http://www.aygfsteel.com/ajoo/comments/commentRss/30123.htmlhttp://www.aygfsteel.com/ajoo/services/trackbacks/30123.html
在Neptuneq个工具里面Q附带了一个shell。这个shell允许交互执行Neptune的Command和Ant的Task。可以在q里下蝲Q?br>http://docs.codehaus.org/display/JASKELL/Downloads

下面要介l一下怎么用:

启动Neptune shell很简单。按照要求安装完了之后(是讄一个NEPTUNE_HOME和PATH环境变量Q,q行Q?br>
np -i

shell启动后,你可以看见:
Neptune Interactive
>
q个">"是命令提C符。现在你可以输入命o了?br>
先看看最单的ant echod。xml语法是这LQ?br>
<echo message="hello world"/>
对应的neptune语法?br>
> ant.echo{message="hello world"}->exec
>
starting command Echo ...
task Echo: hello world
command Echo executed.

E微解释一下:
1。所有ant命o都在antq个namespace里面?br>2。xml的尖括号换成大括受大括号在jaskell语言里面表示一个tuple?br>3。exec函数用来执行一个命令。如果没有execQant.echo只是生成一个命令对象,但不执行。这样做得好处是Q你可以用变量时存储这些命令对象,可以把他们存在Q意的对象或者数l中Q等到真正需要执行的时候再q行?br>4?->"q个函数用来以先参数后函数的循序调用函数Q相当于exec(ant.echo{...})Q语法上有的时候显得更漂亮些?br>


再来看个复杂点的。前两天我发现需要把某个目录下所有反~译出来的jad文g改名成java文g。dos的rename命o居然不支持。于是我qh宝:
> rename {dir,from,to} = ant.move{todir=dir}.with [
>   ant.types.fileset{dir}.with [
>     ant.types.include{name="**/$from"}
>   ],
>   ant.types.mapper{type="glob",from,to}
> ] ->exec
>
=> rename()

q个东西定义了一个函敎ͼ接下来,我就可以拿rename当作一个简z的命o了:
> rename{dir="decompiled",from="*.jad",to="*.java"}
> 
starting command Move
command Move executed.
>


后来Q我把这个rename函数E微完善了一下,增加了一个recursive参数来控制是否处理子目录Q缺省值是falseQ给dir讄当前目录为缺省倹{代码放在一个可以重用的脚本文g里面。现在可以这样做了。先把函数加载进来:

> helper = import {resource="jfun/neptune/ant/anthelper.jsl"}
>


然后调用Q?br>
> helper.rename{from="*.jad",to="*.java",recursive=true}->exec
>

呵呵?br>
q个工具可以调用L的antd。还有很多好用的函数。具体请见:
http://docs.codehaus.org/display/JASKELL/Neptune


ajoo 2006-02-10 13:06 发表评论
]]>
一个方便的java shellhttp://www.aygfsteel.com/ajoo/archive/2006/01/22/28913.htmlajooajooSat, 21 Jan 2006 18:13:00 GMThttp://www.aygfsteel.com/ajoo/archive/2006/01/22/28913.htmlhttp://www.aygfsteel.com/ajoo/comments/28913.htmlhttp://www.aygfsteel.com/ajoo/archive/2006/01/22/28913.html#Feedback0http://www.aygfsteel.com/ajoo/comments/commentRss/28913.htmlhttp://www.aygfsteel.com/ajoo/services/trackbacks/28913.html
q个shell虽然是jaskell的,但是也可以作Z个交互式执行java代码的解释器。对于想快速地试试某个api比较有用?br>
相比于eclipse scrapebookQ它的好处是更方便,而且Qjaskell的一些函数式的特性让你可以写出更加简z的代码?br>
下面丑և个例子:

L玩Swing

打开shellQ它昄q样Q?br>

Jaskell Shell version 
0.5
>
然后假设你要q行一下javax.swing.JOptionPane.showInputDialog()函数的话Q你可以q样写:
> javax.swing.JOptionPane.showInputDialog["your age?"]
>
回R两下Q第一下,是单折行,因ؓ你可以接着写下一行代码,只有q箋两下折行Qshell才认Z是要执行Q?br> l果׃出现一个简单的swing对话框。在对话框里面输入年龄?3"Q回车,
shell里面׃昄Q?3?br>

q里面,一炚w要注意的QjavaҎ调用不用圆括P而是Ҏ受你可以把这个理解ؓ一个reflection调用Q传递的永远都是一个数l?br>
下面Q假设你想重复地使用JOptionPaneq个c,使用showInputDialog, showConfirmDialogq类的方法,总这么写javax.swing.JOptionPane也够ȝ的。我们可以简化它Q?br>
> dialog = javax.swing.JOptionPane
>
=> class javax.swing.JOptionPane
当你回R两次后,shell?=>"提示W后面自动显C个表辑ּ的|"class javax.swing.JOptionPane"?br>
下面我们可以重复使用dialog变量了。在q之前,我们可能想看看JOptionPane到底都支持什么静态方法,我们可以??"来让shell告诉我们
> ? dialog
q个"?"不是jaskell语言的一部分Q而是shell的命令,所以不需要回车两ơ。回车,shell׃把JOptionPane的所有方法都列出来?br>
然后假设我们选择showMessageDialogQ可以这样写Q?br>
> dialog.showMessageDialog[null"hello world"]
>
然后Q一?hello world"的对话框弹了出来(看不见?找一找。它可能被藏在你的当前窗口后面了。)

更简化一点,假设我要重复showMessageDialog若干遍,我可以这样写Q?br>
> say msg = dialog.showMessageDialog[null, msg]
>
=> say()
q个表达式的值是一个接受一个参数的Q叫做say的函数?br>
下面你可以say很多东西啦:
> say "how are you?"
>

> say "java sucks!"
>
{等{等?br>


ȝ多线E?/b>

好,看过了JOptionPaneQ我们来看看多线E。下面是用这个语a怎么启动一个线E:
> Thread.new[(\_->System.out.println["hello world"]) `implements Runnable].start[]
>
hello world
q里面Thread.new大概不需要解释。这里对构造函数的调用是Ruby风格的ClassName.newQ而不是java的new ClassName?br>
构造函C需要用一个list来传递参数。我们这里传递的是一个Runnable对象?br> 用来实现Runnable接口的是一个匿名函敎ͼq个函数不管参数是什么,一旦调用,println一下?br>
implements 是一个函敎ͼ它负责用一个函数来动态生成一个实现某接口的proxy出来。它前面的那个反向单引号表示把一个函C中缀语法调用Q所? (somefunction `implements Runnable){h于implements(somefunction, Runnable)?br>
"\"W号是lamda函数表示法?->"W号前面的是函数参数Q后面的是函C。这里因为我们不使用q个参数Q所以用"_"q个通配W?br>
最后,我们调用start[]Ҏ来执行这个线E?br>

我们q可以用标准?const"函数来让代码更简短一炏V?const x"语义上完全等价于"\_->x"。另外,我们也可以用java风格的new操作W函数来写,jaskell对两者都支持的:
> new Thread[const(System.out.println["hello world"]) `implements Runnable].start[]
>
hello world


然后Q考虑到重用,我们可以q样Q先把System.out.println搞短一点,每次敲这么长太麻烦:
> println msg = System.out.println[msg]
>
=> println()

Q实际上Qprintln函数是系l已l缺省就定义好的了。你完全没有必要自己定义println可以直接用了。这里只是演CZ下怎么自己定义函数Q?br>

然后Q把那段启动U程的代码写成函敎ͼ
> run task = Thread.new[const task `implements Runnable].start[]
>
=> run()

好了Q下面我们可以Q意启动线E做事情了:
> run(println "hello world")
>
hello world

> run(println "pei!")
>
pei
!

> run (say "nice!")
>

最后一个say "nice!"Q如果不用单独线E的话,q行后这个对话框阻塞当前线E。现在用run来运行它Q就不会d了?br>

今天你fp了吗Q?/b>

最后再随便看看jaskell作ؓ函数式语a的本分所能做的一些事?br>
foreach函数Q?/b>

> foreach [1,2,"hello"] println
>
q个函数?,2,"hello"三个都打C遍?br>
> foreach(list 1 100, println)
>
q个函数把数??00按顺序打C遍?br>
map函数Q?/b>
> map (\x->Integer.parseInt[x]) ["1","2","3"]
>
=> [
1,2,3]
q个函数把一个字W串列表转换成一个整数列表?br>

filter函数Q?/b>


> filter(\x->x<10, list 1 100)
>
=> [
1,2,3,4,5,6,7,8,9]
q个代码??00中所有小?0的整数都取出来?br>
filter函数的第一个参数是一个函敎ͼq个函数对列表中的每一个元素都q行判断Q返回true或者false?br>
find函数Q?/b>

> find(3, list 1 100)
>
=> 2
q个代码在列表中L整数2Q如果找刎ͼq回扑ֈ的位|(0为第一个)


lookup函数Q?/b>

> lookup(\x->x*x>x+50, list 1 100)
>
=> 7
q个代码在列表中LW一个符合x*x>x+50的元素,扑ֈp回位|?br>
@函数Q?/b>

上面我们知道扑ֈ的数字是在位|?Q可以用@来得C|?的|

> list 1 100 @ 7
>
=> 8
好,q个数是8?br>

sum函数Q?/b>

> sum(list 1 100)
>
=> 5050


注意Q最隄来了Q?br> fold函数Q?/b>

> fold (*1 [1,2,3,4,5]
>
=> 120
q个fold函数?为初始|然后Ҏ个列表元素,把它和当前值做乘法Q用l果更新当前|最后把计算l果q回。所以这D代码实际上做的是把从1?乘v来?br> (*)是一个乘法函数?br>
你也可以用自己写的:
>  fold (\x y->x*y) 1 [1,2,3,4,5]
一L?br>

行了Q差不多了。下载在Q?br>
http://dist.codehaus.org/yan/distributions/jaskell.zip

把jar文g都放C的classpath里面Q然后运行jfun.jaskell.shell.Shellcd行了?br>


ajoo 2006-01-22 02:13 发表评论
]]>
一个用Spring transaction template的小工具http://www.aygfsteel.com/ajoo/archive/2006/01/13/27847.htmlajooajooThu, 12 Jan 2006 23:49:00 GMThttp://www.aygfsteel.com/ajoo/archive/2006/01/13/27847.htmlhttp://www.aygfsteel.com/ajoo/comments/27847.htmlhttp://www.aygfsteel.com/ajoo/archive/2006/01/13/27847.html#Feedback0http://www.aygfsteel.com/ajoo/comments/commentRss/27847.htmlhttp://www.aygfsteel.com/ajoo/services/trackbacks/27847.html 1。直接用hibernate事务?br> 2。用spring的TransactionTemplate?br>
直接用hibernate事务有以下问题:
1。代码完全绑定在Hibernate上?br> 2。自己控制事务难度比较大Q不Ҏ处理得好?br>
对第二点Q很多h可能都不以ؓӞ不就是一个beginTransaction和一个commit(), rollback()么?太门~里看h了吧Q?br>
我就举个sparkle同学的小弟写的代码吧Q?br>
try{
   PetBean pet 
= ;
   
   beginTransaction();
    ssn.delete();
    
    commit();
    petLog();
  }
  
catch(Exception e){
     rollback();
     
throw e;
  }

一个大的try-catch块,在出CQ何异常的时候都rollback?br>
我想会这么写的h应该不在数。同志们Q革命不是请客吃饭那么简单地?br>
问题在哪Q?br>
1。最严重的。try里面一旦有Error抛出Qrollback()׃会被执行。sparkle同学_ZError我们׃了。可以,反正出Error的几率大概很。所以你的Y件可以说“大多数情况是可以工作地”?br>
2。这块代码最l抛出ExceptionQ如果外面直接套一个函数的话,{֐上就得写"throws Exception"。这U函数就一个字Q“害之马”。你让调用者根本不知道会出什么异常,W统地告诉h家“什么情况都可能发生”可不是负责ȝ态度?br>
3。这个代码依赖于rollback()的特定实现。因Z旦exception是在beginTransaction()之前或者beginTransaction()时候抛出的Q那么本来不应该调用rollback()的。调? rollback()会出什么结果呢Q如果rollback()不检查当前是否在事务中,坏菜了。而且Q就rollback()做这个检查,嵌套事务 也会把一切搞乱。因为很有可能整块代码是处在另外一个大的事务中的。调用我们的代码在我们抛出异常的时候,也许会选择redoQ或者修复一些东西,不见得L选择? 滚它那一层的事务的,不分青红皂白地就rollback上层事务Q这个代码的健壮性真的很差?br>
看,小一D代码,bug和潜在问题如此之多。你q说自己写事务控制简单吗Q?br>
真正健壮的,不对外界和调用者有多余的假设依赖的代码Q可以这样写Q?br>
 PetBean pet = ;
  
 beginTransaction();
 ok 
= false;
 
try{
    ssn.delete();
    
    ok 
= true;
    commit();
   
    petLog();
  }
  
finally{
     
if(!ok)
        rollback();
  }

攑ּtry-catchQ改用try-finally。这样就不需要捕获异常再抛出那么ȝ。然后用一个bool变量来告诉finally块是否需要回滚?br>
q个代码不难理解Q但是如果处处都用这个代码,也够丑陋的?br>
既然已经用了springQؓ什么不用spring的TransactionTemplate呢?用Spring TransactionTemplateQ下面简UttQ的好处如下Q?br> 1。事务代码不依赖hibernateQ便于移植?br> 2。自动得到异常安全,健壮的事务处理。写代码的时候几乎可以完全忘C务的存在?br>
当然Qsparkle同学有他的道理。用spring tt需要实现TransactionCallback接口。而java的匿名类语法非常J琐。更可恨的是Q匿名类只能引用定义成final的局部变量,q? 样在从tt里面往外传递返回值的时候就非常不方ѝ我们可能需要这么写Q?br>
//xxx
  Object[] result = (Object[])tt.execute(new TransactionCallback() {
      
public Object doInTransaction(TransactionStatus status) {
          Object obj1 
= new Integer(resultOfUpdateOperation1());
          Object obj2 
= resultOfUpdateOperation2();
          
return new Objetct[]{obj1,obj2};
      }
  });
  System.out.println(((Integer)result[
0]).intValue()+1);
  System.out.println(result[
1]);

多么丑陋的result[0], result[1]呀。其它还有一些变体,比如每个l果用一个Object[]Q或者定义一个通用的RefcL支持"get()"?set()"?br>
可是Q这么多的方案,sparkle同学都不满意。也是,q些Ҏ都免不了cd不安全的down cast。而处理原始类型的l果q需要装!


因ؓq些原因Q我构思了一个简单的spring tt的wrapper。一个TxcR这个Txcd以这么用Q?br>
//xxx
new Tx(){
  
private result0;
  
private String result1;
  
protected void run(){
      result0 
= resultOfUpdateOperation1();
      result1 
= resultOfUpdateOperation2();
  }
  
protected Object after(){
    System.out.println(result0
+1);
    System.out.println(result1);
    
return null;
  }
}.exec(tt);

通过把局部变量定义成Txcȝ成员变量Q我们绕q了downcast和原始类型装拆qȝ。通过把事务之后要执行的动作封装在after()q个成员函数里面Q我们可以方便地引用run()里面产生的结果?br>

下面看看Tx, TxBlock, TransactionBlockExceptionq三个类的设计:

public abstract class TxBlock implements TransactionCallback{
  
protected void before()
  
throws Throwable{}

  
protected abstract void run(TransactionStatus status);
  
protected Object after()
  
throws Throwable{
    
return null;
  }
  
protected void lastly(){}
  
public final Object exec(TransactionTemplate tt){
    
try{
      before();
      tt.execute(
this);
      
return after();
    }
    
catch(RuntimeException e){
      
throw e;
    }
    
catch(Error e){
      
throw e;
    }
    
catch(Throwable e){
      
throw new TransactionBlockException(e);
    }
    
finally{
      lastly();
    }
  }
  
public Object doInTransaction(TransactionStatus status){
    run(status);
    
return null;
  }
}



public abstract class Tx extends TxBlock{
  
protected abstract void run();
  
protected void run(TransactionStatus status) {
    run();
  }
}

public class TransactionBlockException extends NestedRuntimeException {

  
public TransactionBlockException(String arg0, Throwable arg1) {
    
super(arg0, arg1);
  }

  
public TransactionBlockException(String arg0) {
    
super(arg0);
  }
  
public TransactionBlockException(Throwable e){
    
this("error in transaction block", e);
  }
}

所有的代码都在q了Q除了importQ?br> q个工具除了after()Q还支持before(), lastly()。before()在事务开始前q行。after()在事务结束后q行。lastly()保证不管是否出现异常都会被执行?br>
如此Q一个薄薄的装Qspring tt用v来庶几不会让sparkle再以头撞墙了?br>


ajoo 2006-01-13 07:49 发表评论
]]>
վ֩ģ壺 | Ƥ| ԭ| ں| | | ̨| º| | ī| »Ȱ| ϲ| | | | ɽ| | | | º| | | | ¡| | ̨| ͩ®| Ԫ| ͭ| ʡ| Ȩ| | ˳| | | | ½| | | ʼ| «ɽ|