Call by Need: in this evaluation strategy, a parameter is evaluated only if it is used. However, once the first evaluation happens, its result is cached, so that further uses of the parameter do not require a re-evaluation. This mechanism provides the following three guarantees:
- The expression is only evaluated if the result is required by the calling function;
- The expression is only evaluated to the extent that is required by the calling function;
- The expression is never evaluated more than once, called applicative-order evaluation.
Haskell is a language notorious for using call by need. This evaluation strategy is a key feature that the language designers have used to keep Haskell a purely functional language. For instance, call by need lets the language to simulate the input channel as an infinite list, which must be evaluated only as much as data has been read. An an example, the program below computes the n-th term of the Fibonacci Sequence. Yet, the function fib, that generates this sequence, has no termination condition!
Further information: WikipediaEn:Clojure
Clojure generates infinite lazy sequences (similar to Haskell's lazy lists or Python's generators). Use take to get the first N results from the infinite sequence.(take 20 (for [x (range) :when (> (* x x) 3)] (* 2 x))) ;; ⇒ (4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42)
Further information: WikipediaEn:Common Lisp
List comprehensions can be expressed with the loop macro's collect keyword. Conditionals are expressed with if, as follows:(loop for x from 0 to 100 if (> (* x x) 3) collect (* 2 x))
An infinite lazy sequence can be created in a variety of ways, such as the CLOS object system or a yield macro.
From version 2.2 forward, Python manifests lazy evaluation by implementing iterators (lazy sequences) unlike tuple or list sequences. For instance (Python 2):
>>> list = range(10) >>> iterator = iter(list) >>> print list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> print iterator <listiterator object at 0xf7e8dd4c> >>> print iterator.next() 0
The above example shows that lists are evaluated when called, but in case of iterator, the first element '0' is printed when need arises.
Tags: 遅延シーケンス, lseq, gauche.lazy