2016-11-16 5 views
0

別のクラスのいくつかのクロージャのためにメモ処理を実装しようとしています。しかし、私はそれを機能させることができません。パラメータを指定しないで閉じますmemoizationはcall()でのみ機能します

.call()を使用してクロージャを呼び出すと、メモの設定が正しく機能します。しかし、私は通常の方法のようにそれを呼び出すときに動作しません。

コード:

public class Tester { 

    static main (String[] args){ 

     Sample sample = new Sample(); 

     println sample.printer.call(); \\works 
     println sample.printer.call(); \\works 

     sample = new Sample(); 

     println sample.printer(); \\does not work 
     println sample.printer(); \\does not work 
    } 
} 

class Sample{ 

    def printer= { 
     println "inside" 
     true; 
    }.memoize(); 
} 

コンソールログ:

inside 
true 
true 
Caught: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.doCall() is applicable for argument types:() values: [] 
Possible solutions: call(), call([Ljava.lang.Object;), call(java.lang.Object), call([Ljava.lang.Object;), equals(java.lang.Object), isCase(java.lang.Object) 
groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.doCall() is applicable for argument types:() values: [] 
Possible solutions: call(), call([Ljava.lang.Object;), call(java.lang.Object), call([Ljava.lang.Object;), equals(java.lang.Object), isCase(java.lang.Object) 
    at Tester.main(Tester.groovy:12) 

このため、私は今call()を使用して、すべての私の閉鎖呼び出しを変更する必要があります。同じことが私の通常のメソッド呼び出しを達成できるかどうか私に教えてください。私は解決策、私ができる最善を与えることができるのが大好きです

答えて

1

は、しかし、あなたは何を簡単に見て(とgroovyコンソールで試行を)教えている私を得た:

直接呼び出す閉鎖のための短い構文を使用してローカルメモ化閉鎖が魔法のように動作上:なしメソッド「プリンタがないよう

def memclosure = { println "foo" }.memoize() 
memclosure() 
memclosure() 

ので、それが道とは何かを持って、Groovyは、実際には

sample.printer() 

を解決します"このクラスでは、オブジェクトmetaClass(またはデフォルトの場合は" invokeMethod ")の" methodMissing "がトリガされ、メソッド名を持つプロパティがあるかどうかを調べ、その値に対して" doCall "アクションを実行しますは私にGroovyのバグになります。例えばComposedClosure、IteratorClosureAdapterとMethodClosure:Groovyのは、それがすべてではない閉鎖実装がこのdoCall方法を提供することを、ライン1249)。ここで

問題でMetaClassImpl中です2.4.4にdoCallを提供しますが、Memoizeのオブジェクトはそうしません。

は、おそらく誰かが、私は、実行時にメモ化閉鎖のメタクラスに「doCall」方法を取り付けて作業それを得た(別にバグチケット上げから)

をよりよく説明および/またはソリューションを持っています

def dummy = { println "never called" }.memoize() 
dummy.class.metaClass.doCall = { -> delegate.call() } 
dummy.class.metaClass.doCall = { a -> delegate.call(a) } 
dummy.class.metaClass.doCall = { a, b -> delegate.call(a, b) } 
dummy.class.metaClass.doCall = { a, b, c -> delegate.call(a, b, c) } 
// can you attach new methods to a metaClass with dynamic parameter count? 

おそらく実現可能な回避策

+0

おかげで男のthats場合は、開始時刻に何とかそれを実行しようと見ています。メタクラスメソッドを試してみます。直接呼び出しはもっとうまくいくでしょうが、これはうまくいかないのでどこでも 'call() 'を使うことに決まります。 – v1shnu

+0

もちろん、あなたのグルーヴィーバージョンをパッチしてコンパイルして、doCallをmemoizeクロージャーバリアントに導入することができます。グルーヴィーバグのチケットを発行することは良い考えです。 – norganos

+0

metaClassを持つバリアントは、プログラムの開始時にのみ必要です。その後、あなたはメモの付いたクロージャを直接呼び出すことができます – norganos

関連する問題