2015-01-12 1 views
1

Я написал несколько неудобный реализации Фибоначчи просто чтобы проверить потокПочему ошибка переполнения стека с помощью этого кода Scala?

def fibonacci(a : Int, b : Int) : Stream[Int] = Stream(a, b) ++ fibonacci(a + b, a + b * 2) 

Я знаю, что это не лучшая реализация, но не мог понять, почему это было бы к переполнению стека на любой вызов к нему, скажем fibonacci(0, 1) take(1)?

Спасибо.

ответ

2

Потому что вы немедленно вынуждаете оценку рекурсивному вызову fibonacci.

Другими словами, вам нужно создать ленивый генератор, либо используя метод, например continually, либо путем сопоставления на хвосте. У Scaladoc на самом деле есть хороший пример того, как создать поток фибоначчи здесь: http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream

+0

Как заставить оценку «фибоначчи» немедленно? Вместо этого, почему 'def fibonacci (first: Int, second: Int): работает Stream [Int] = first # :: fibonacci (second, first + second)'? – ekinrf

+0

Всякий раз, когда вы вызываете функцию, ее сразу оценивают. Таким образом, в вашем примере вы вызываете метод '' fibonacci'', который немедленно вызовет метод '' fibonacci'', который будет немедленно ... И так далее. Если вы использовали метод '' постоянно ''для создания потока, вам понадобятся только рекурсивные методы. Итак, когда вызывается '' take'' в вашем примере, ваш поток будет вычислять необходимые значения (1). –

+0

Как и в другом примере, '' # :: '' подобен оператору '::' (cons) для списков, но использует ленивую оценку ([см. '' => '' В аргументе конструктора] (http : //www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream$$ConsWrapper) - так же, как в методе '' постоянно''. Это означает, что следующий вызов fibonacci будет оцениваться только тогда, когда это необходимо, так же, как это происходит с '' постоянно''. –

Смежные вопросы