Use of existing language features to emulate LazyEvaluation in an eager programming language. (Most mainstream programming languages, other than the Haskell family, are eager by default. Note that strict evaluation refers to completely evaluating a function's arguments before execution, while eager evaluation refers to evaluation of an expression as soon as it is bound).
The usual technique is to create a function/object which when called (or has a well-known method invoked on it), yields the desired result. The function/object should then save the result away, so that subsequent calls yield the same result. (Otherwise, you have NormalOrderEvaluation). Note that the state transitions required are monotonic, so that this isn't considered too offensive in a SideEffect-free context. (ConceptsTechniquesAndModelsOfComputerProgramming discusses this in great depth).
Note that the function/object must have some state, to record whether or not the result has been evaluated, and to store the result if it has. A standard CeeCeePlusPlus function won't work; a LexicalClosure will (or an "emulated closure", which consists of a function and a pointer to some state). Objects will work fine.
Some languages make this easier than others:
- In C, it's a royal pain.
- In C++, it's easily doable with FunctorObjects, though C++'s lack of GarbageCollection makes dealing with FunctorObjects a bit more difficult. (FunctorObjects are often used in ways that make explicit allocation/deallocation difficult). The BoostLibraries have lots of goodies to help with this.
- Another approach you could do in CeePlusPlus (I can't think of any examples however) is with a lazy SmartPointer. By overloading the various dereferencing forms in C++ (operator *, operator ->, operator []) one is provided with a "hook" where one can attach the test-and-evaluate step. Unlike other forms, this one is almost transparent. If you provide such a beastie with a (non-explicit) copy constructor which takes a pointer on the RHS, then you can use real pointers and these things interchangeable FTMP.
- SmalltalkLanguage does this (sort of) with blocks. However, SmalltalkLanguage blocks by default implement NormalOrderEvaluation (if you send the value message to a block twice, the block is executed twice), additional work is needed to make Smalltalk blocks implement true LazyEvaluation. (In many lazy Smalltalk idioms, such as ifTrue: ifFalse:, the block is never evaluated more than once, so this is not necessary for those forms).
- SchemeLanguage has delay and force, which essentially create and call the necessary lambda forms.
- OcamlLanguage has lazy and Lazy.force, which create and force delayed expressions. Delayed expressions have the type Lazy.t . See ExplicitLazyProgramming
See also
ImplicitLazyEvaluation
CategoryLazyPattern