Monix Coeval.memoize дует в стек
Определять
def memoizeCoeval(n: Int): Coeval[Int] = {
if (n <= 1)
Coeval.now(1)
else
Coeval.defer(memoizeCoeval(n - 1)).map(_ + 1).memoize
}
Сейчас
memoizeCoeval(10000).value
взрывает стек Если мы удалим .memoize
от рекурсивного вызова, это работает (как и ожидалось). Зачем?
2 ответа
Без , вы получите ровесника, который представляет собой композицию s. Каждый из них содержит преобразователь, который представляет собой функцию, возвращающую следующее: цикл выполнения разворачивает это, вызывая преобразователь, устанавливая результат как текущий, а затем продолжая цикл.
Когда используешьmemoize
,Suspend
содержит a, который расширяет() -> Coveal
. Он переопределяет таким образом, что вызывает непосредственно свой собственный базовый преобразователь, который, в свою очередь, вызывает цикл выполнения. Так когдаLazyVal
хapply
вызывается в цикле выполнения, он рекурсивно вызывает цикл выполнения, что вызывает переполнение стека.
Я не знаю, если это ошибка, какCoeval
предназначен для защиты стека, но обратите внимание, что нет смысла запоминать каждый шаг вашего рекурсивного метода, поскольку соответствующий Coveal никогда не будет использоваться повторно. Возможно, вы захотите запомнить только конечный результат.
Недостатком Coeval является то, что вы можете использовать Eval вместо него для стековых безопасных рекурсивных запоминаемых вычислений таким же образом.