Groovy MOP
Groovy ã«ã¯ã¡ã¿ããã°ã©ãã³ã°ããã® API ãç¨æããã¦ããã*1
関数の自動メモ化 ã®ä¸ã§å½ã¦ã¯ãã㨠Spring AOP ã®ãããªãã¨ãè¨èªå
ã§è¡ããã
class MemoizeInterceptor implements Interceptor { def cache = [:] def hasResult @Override Object beforeInvoke(Object object, String methodName, Object[] arguments) { this.hasResult = cache.containsKey([methodName, *arguments]) } @Override Object afterInvoke(Object object, String methodName, Object[] arguments, Object result) { def key = [methodName, *arguments] if (!cache.containsKey(key)) cache[key] = result cache[key] } @Override boolean doInvoke() { !this.hasResult } } def memoize(obj, Closure blk) { def proxy = ProxyMetaClass.getInstance(obj.class) proxy.interceptor = new MemoizeInterceptor() proxy.use(obj, blk) } def fib = { n -> println n; n <= 1 ? n : call(n - 1) + call(n - 2) } memoize(fib) { assert fib(40) == 102334155 }
å帰å¼ã³åºããä¸æ¸ãã§ãã¦ãã¾ãã
Groovy 1.8 ã«ãªã£ã¦åä½ãå¤ãã£ã¦ããé¨å
Groovy v1.8の新機能をサクっと紹介するよ - No Programming, No Life ãè¦ã¦æ°æ©è½ã«ç®ããã£ã¦æ°ã¥ããªãã£ããããã©ã¼ãã³ã¹ã®åä¸ã®é¨åã ã
"this"ã§ã®ã¡ã½ããå¼ã³åºãæã®å¼æ°ãã´ã£ããä¸è´ããå ´åãã¡ã½ããã¯ãã¤ã¬ã¯ãã«å¼ã³åºãããããã«ãªãã¾ãããªã®ã§ãããã¯å®è¡æã®ã¡ã½ããåçå¼åºãã®éã«ã¯è¡ããã¾ããã
Groovy ã¤ã³ã»ã¢ã¯ã·ã§ã³ã® GroovyInterceptable ä¾ãã¨ã©ã¼ã«ãªã£ãã
import org.codehaus.groovy.runtime.StringBufferWriter import org.codehaus.groovy.runtime.InvokerHelper class Traceable implements GroovyInterceptable { Writer writer = new PrintWriter(System.out) private int indent = 0 Object invokeMethod(String name, Object args){ writer.write("\n" + ' '*indent + "before method '$name'") writer.flush() indent++ def metaClass = InvokerHelper.getMetaClass(this) def result = metaClass.invokeMethod(this, name, args) indent-- writer.write("\n" + ' '*indent + "after method '$name'") writer.flush() return result } } class Whatever extends Traceable { int outer(){ return inner() } int inner(){ return 1 } } def log = new StringBuffer() def traceMe = new Whatever(writer: new StringBufferWriter(log)) assert 1 == traceMe.outer() println log assert log.toString() == """ before method 'outer' before method 'inner' after method 'inner' after method 'outer'"""
inner ã®å¼ã³åºãã invokeMethod ãçµç±ããªãã§ç´æ¥å¼ã³åºãããããã«ãªã£ãã®ã§ trace ã§ãã¦ããªãã
disableopt ãªãã·ã§ã³ã§æé©åã off ã«ãããåä½ããã
ããä¸ã¤ã® Interceptor ã®ä¾ã¯è¨³æ³¨ã« 1.1 ã®æç¹ã§ã¨ã©ã¼ã«ãªã£ãã¨æ¸ãã¦ããã 1.8 ã§ãåä½ãã*2ã
MOP2
Groovy ã¤ã³ã»ã¢ã¯ã·ã§ã³ã®æç¹ã§ MOP ã®è¨è¨ã®è¦ç´ããããã¨æ¸ãã¦ãããå¤ãã£ã¦ããªãæ°ãããã
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Lafor…
å»å¹´ã®è³æã ã MOP ã®é¨åã¯æ½è±¡çã«æ¸ããã¦ããã®ã§ Groovy 2.0 以éã«ãªãã®ããªã
æ¤ç´¢ãã¦ããã¾ã使ç¨ä¾ãè¦ã¤ãããªãã®ã ãã©ç¾å¨ã® MOP ã§ãããªãã®ãã¯ã¼ãç§ãã¦ããã¨æãã
2011-05-08 追è¨
ãããã¯ã«å¼æ°ã§æ¸¡ãã¦ã¿ãã
def memoize(obj, Closure blk) { def proxy = ProxyMetaClass.getInstance(obj.class) proxy.interceptor = new MemoizeInterceptor() proxy.use(obj) { blk(obj) } } memoize({ n -> println n; n <= 1 ? n : call(n - 1) + call(n - 2) }) { assert it(40) == 102334155 }
*1:Groovy ã¤ã³ã»ã¢ã¯ã·ã§ã³ 7.6ã Google ããã¯ã¹ã§å ¬éããã¦ãã
*2:ã¹ãã¼ã¹ã®æ°ã¯èª¿ç¯ãã