在Groovy中记住成员方法

时间:2012-04-02 16:49:40

标签: methods groovy memoization

我有一个pure function的方法,需要一段时间才能运行。我想记住这个方法,以便后续调用更快。我可以在Groovy的文档中看到你可以通过以下方式记住闭包:

foo = {…}.memoize()

但是,我找不到记忆成员方法的方法。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:7)

编辑:

在Groovy 2.2.X中会有一个名为@Memoized的新AST转换,它会为你做这个。

import groovy.transform.Memoized

class Woo {
  @Memoized
  def sum( int a, int b ) {
    Thread.sleep( 1000 )
    a + b
  }
}

new Woo().with {
  println new Date()
  println sum( 1, 2 )
  println new Date()
  println sum( 1, 2 )
  println new Date()
}

原始答案

另一种选择是编写某种AST转换,以允许您使用@Memoize注释方法,并为您完成备忘。

通过基本上操纵AST看起来像流行病学家的答案的第二部分,我可以找到几个例子,一个是here for adding Redis as a Memoization cache to Grails,另一个是here which seems to allow memoization of single argument methods

由于你可能想要多个参数,我会选择流行病的第二种方法。但是编写AST变换可能是一个有趣的实验/侧面项目?

如果做得对,我可以看到回到Groovy核心源代码(为了名声和荣耀): - )

答案 1 :(得分:3)

我不知道任何记忆方法的直接方式,就像你可以记住一个Closure一样。

如果方法没有接收到任何参数(因此返回值总是相同的,因为它是纯的),您可以简单地通过将返回值存储在成员属性中来进行记忆。这种技术在Ruby中很常见,它通常采用def some_method; @value ||= compute_value; end的形式。将其翻译为Groovy,您可以执行以下操作:

class Computer {
    private answer
    def getAnswer() {
        answer = answer ?: computeAnswer()
    }
    private computeAnswer() {
        println "Computing the Answer to the Ultimate Question of Life, the Universe, and Everything"
        42
    }
}

def c = new Computer()
println c.answer
println c.answer

输出结果为:

Computing the Answer to the Ultimate Question of Life, the Universe, and Everything
42
42

所以备忘录有效:)

如果您不想定义额外的方法,您还可以编写getAnswer方法,如:

def getAnswer() {
    if (answer != null) return answer
    println "Computing the Answer to the Ultimate Question of Life, the Universe, and Everything"
    answer = 42        
}

现在,如果方法 接收任何参数,以这种方式实现memoization将非常麻烦。你可以从你想要记忆的方法中调用一个memoized闭包:

class Calculator {
    def sum(a, b) {
        memoizedSum(a, b)
    }
    private memoizedSum = { a, b ->
        println "Computing the sum of $a and $b"
        a + b
    }.memoize()
}

def c = new Calculator()
println c.sum(4, 7)
println c.sum(4, 7)
println c.sum(4, 2)

输出结果为:

Computing the sum of 4 and 7
11
11
Computing the sum of 4 and 2
6