我有一个pure function的方法,需要一段时间才能运行。我想记住这个方法,以便后续调用更快。我可以在Groovy的文档中看到你可以通过以下方式记住闭包:
foo = {…}.memoize()
但是,我找不到记忆成员方法的方法。有没有办法做到这一点?
答案 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