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>

]]>