Groovy 1.8 新特性: 增强的DSL和闭包特性
虽然 JDK7 千呼万唤不出来,Groovy 还是如期升级到 1.8 版本。大致读了下 Release Notes,改动不大(大了还得了),但是亮点还是有的。 加强的 DSL 特性:把 Scala 和旧版的 Groovy 进行比较,会发现 Groovy 被迫写了很多点和括号,而 Scala 则看起来更像是自然的英语。前几天我还絮叨过这个问题,但现在有所不同了 1: turn left then right
2: paint wall with red,green and yellow
印象深刻! 在新版本中,a b c d 等同于 a(b).c(d),由此,可以写出更自然的 DSL。(支持多参数、闭包和命名参数) PS: 对多数人来说,写 DSL 的情况不多,但是多半接触过 Gradle、Grails 等工具,多少会有了解。要做出好的设计,必须对 command chains 的模式(谁知道有没有现有的模式对应?我记得以前用过一种不断返回自身的连续接口,中文叫啥来着,和这个类似,但要简单很多)很熟悉。即使不写 DSL,在脚本中应用以上的特性也是很能改善可读性的。 性能提升:1.8.x 将对基础类型和方法调用做大量的优化(目前 int 的四则运算和比较已经被优化了)。Groovy 由于其动态模型必须在计算前作大量的检查,在新版本中,如果符合一定的前提条件,则这些检查将被略过,从而加快执行速度。 PS II. 如果细读文档会发现这些优化目前仅针对相当受限的条件,比如提到的整数运算,如果你计算 int + int,那么就可以得到优化的速度,可如果计算 int + int + long 则立刻回到原有的模式。但需要强调的是,代码原来怎么写,现在还怎么写,不要去迎合这些优化。否则,1.9 版本一出,难道重写所有代码? PS III. 而且我对 Groovy 的性能要求也不高,至少以前单位里的那些小白鼠也没有因为我用了 Groovy 就来投诉我的。就算万一遇到瓶颈了,还可以用 Groovy++ 来顶一下。以前没有吧 Groovy++ 作为首选,但现在 Groovy 的 Windows 安装包里已经默认包含了 Groovy++,官方的态度也算是不言自明了吧。 GPars说实在,这个我真不太关心。主要是觉得要是这玩意管用,那我的 Scala 不是白学了么,老子又不是搞科研的 增强的闭包!!这个喜欢。 首先是闭包现在可以作为注释的参数了:(例程我改过了,原来的代码能说明意思,但本身有问题) 1: import java.lang.annotation.*
2:?
3: @Retention(RetentionPolicy.RUNTIME)
4: @interface Invariant { 5: Class value() //此处value()将返回注释参数的class 6: }
7:?
8: @Invariant({ number >= 0 }) //在新版本中,闭包可以作为注释的参数 9: class Distance { 10: def number,unit
11: }
12:?
13: //以下我对Release Notes中的范例做了修改,原版的代码显然是……错的 14: def anno = Distance.getAnnotation(Invariant) //这里和Java的用法相同 15:?
16: Object[] args = [[number: 12],[unit: 'km']] //这是针对下一行的newInstance函数(Groovy的Class类方法) 17: def check = anno.value().newInstance(args) //注意这里check是Distance下的闭包,而不是Distance的实例 18: println check.class 19:?
20: assert check() 这二十行代码可能看起来没有什么用,但对于框架设计者来说则提供了很多有趣的可能。(比如“按合约设计”) 然后是闭包之间的组合(这个帅呆了) 1: triple = { it * 3 }
2: square = { it ** 2 }
3:?
4: tripleBeforeSquare = triple >> square
5: assert tripleBeforeSquare(1) == 9 // square(triple(1)) 6:?
7: tripleAfterSquare = triple << square
8: assert tripleAfterSquare(1) == 3 // triple(square(1)) Trampoline! 1: /*
2: factorial = { 3: it > 1 ? factorial(it - 1) * it : 1 4: } 5:
6: factorial 1000 7: */ 8:?
9: rec = { n,f = 1G -> // 1G的写法表示BigInteger 10: n > 1 ? rec.trampoline(n - 1,n * f) : f
13: factorial = rec.trampoline()
14:?
15: factorial 1000 toString() size() // 2560位的大数,你不会想把它打印出来的
在注释掉的部分,我们看到了一个旧式的阶乘闭包。这个闭包不太管用,因为过深的递归将造成溢出错误。通过新的 Trampoline 闭包,Groovy “不太优雅”的解决了这个问题。 PS IV: 之所以说不太优雅,是和 Scala 的尾递归相比较而言的。但毫无疑问,到目前为止,这个新特性可能是以后最为常用的特性之一。 闭包缓存 新版本中,闭包的结果可以进行缓存(假设给定相同的参数必定返回相同的结果) 1: cls = { ... do something ... }.memoize()
2: // .memoizeAtMost(max) 最多缓存max个结果 3: // .memoizeAtLeast(min) 至少缓存min个结果 4: // .memoizeBetween(min,max) 缓存min到max个结果
出人意料的新功能!以前总是用 map 来实现简单的缓存,现在直接用闭包就可以做到。当然,危险性则是这个闭包是否总是针对相同的参数返回相同的结果。(毕竟 Groovy 不是纯粹的函数风格) Currying 又一个伪装的函数风格!(注意,这一特性也被加入了 1.7 的最新版本) 1: divide = { a,b -> a / b }
3: // 反向的 currying:被替换的是b(右侧)而不是a 4: halve = divide.rcurry(2)
5: assert halve(4) == 2 7: // curry化索引为n的参数 8: halve2 = divide.ncurry(1,2)
9: assert halve2(4) == 2 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |