Reputation: 4081
If we've defined the following:
lazyFib x y = x:(lazyFib y (x + y))
fib = lazyFib 1 1
(from the 7 languages in 7 weeks book). Why does
fibNth x = head (drop (x-1) fib)
evaluate slower than
fibNth2 x = head (drop (x-1) (take (x) fib)
? Clearly the second one terminates the infinite list as soon as required - but intuitively I expected the (head) call to terminate the evaluation the moment one item comes through the "drop", regardless of whether there was a take limit on fib? Can anyone explain?
(updated with timings for reference):
> :set +s
> fibNth 100000
259740693472217241661550340212759154148804853865176...
(1.16 secs, 458202824 bytes)
> fibNth2 100000
259740693472217241661550340212759154148804853865176....
(0.09 secs, 12516292 bytes)
Upvotes: 2
Views: 131
Reputation: 30103
If you flip the order of the two functions in your source file or the interpreter, you would see that the second function is a lot faster.
The reason? fib
is a top level value that gets evaluated only once. On the first call you evaluate it as far as needed, on the second call you just breeze through the list.
You can look at this SO question for notes on when such evaluation behaviour is to be expected. In a nutshell, values with non-polymorphic types are memoized, while polymorphic values and function applications are not.
Upvotes: 7