Методы запоминания членов в Groovy
У меня есть метод, который является чистой функцией и требует времени для запуска. Я хотел бы запомнить этот метод, чтобы последующие вызовы были намного быстрее. Я вижу в документации Groovy, что вы можете запоминать замыкания через:
foo = {…}.memoize()
2 ответа:
Правка:
В Groovy 2.2.X появится новое преобразование AST под названием
@Memoized
, которое сделает это за вас.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
и сделать мемуаризацию за вас.Я могу найти пару примеров, один здесь для добавления Redis в качестве кэша мемоизация в файл Grails, а другой Здесь, которые, кажется, позволяют мемоизация методы с одним аргументом , в основном манипулируя АСТ, чтобы выглядеть как вторая часть ответа эпидемиана.
Поскольку вы, вероятно, хотите несколько параметров, я бы выбрал второй метод epidemian. Однако написание преобразования AST может быть интересным экспериментом / сайд-проектом?
Это то, что, если сделать все правильно, я мог бы увидеть возвращение в исходный код Groovy core (для славы и славы): -)
Я не знаю никакого прямого способа запоминания методов, точно так же, как вы можете запомнить закрытие.
Если метод не получает никаких параметров (и, следовательно, возвращаемое значение всегда одно и то же, поскольку оно чисто), вы можете сделать memoization, просто сохранив возвращаемое значение в атрибуте члена. Эта техника очень распространена в 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 closure из merhod, который вы хотите запомнить: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