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 вместо него для стековых безопасных рекурсивных запоминаемых вычислений таким же образом.

Другие вопросы по тегам