fbpx
Wikipedia

Lazy evaluation

In programming language theory, lazy evaluation, or call-by-need,[1] is an evaluation strategy which delays the evaluation of an expression until its value is needed (non-strict evaluation) and which also avoids repeated evaluations (by the use of sharing).[2][3]

The benefits of lazy evaluation include:

  • The ability to define control flow (structures) as abstractions instead of primitives.
  • The ability to define potentially infinite data structures. This allows for more straightforward implementation of some algorithms.
  • The ability to define partly-defined data structures where some elements are errors. This allows for rapid prototyping.

Lazy evaluation is often combined with memoization, as described in Jon Bentley's Writing Efficient Programs.[4] After a function's value is computed for that parameter or set of parameters, the result is stored in a lookup table that is indexed by the values of those parameters; the next time the function is called, the table is consulted to determine whether the result for that combination of parameter values is already available. If so, the stored result is simply returned. If not, the function is evaluated, and another entry is added to the lookup table for reuse.

Lazy evaluation is difficult to combine with imperative features such as exception handling and input/output, because the order of operations becomes indeterminate.

The opposite of lazy evaluation is eager evaluation, sometimes known as strict evaluation. Eager evaluation is the evaluation strategy employed in most[quantify] programming languages.

History edit

Lazy evaluation was introduced for lambda calculus by Christopher Wadsworth[5] and employed by the Plessey System 250 as a critical part of a Lambda-Calculus Meta-Machine, reducing the resolution overhead for access to objects in a capability-limited address space.[6] For programming languages, it was independently introduced by Peter Henderson and James H. Morris[7] and by Daniel P. Friedman and David S. Wise.[8][9]

Applications edit

Delayed evaluation is used particularly in functional programming languages. When using delayed evaluation, an expression is not evaluated as soon as it gets bound to a variable, but when the evaluator is forced to produce the expression's value. That is, a statement such as x = expression; (i.e. the assignment of the result of an expression to a variable) clearly calls for the expression to be evaluated and the result placed in x, but what actually is in x is irrelevant until there is a need for its value via a reference to x in some later expression whose evaluation could itself be deferred, though eventually the rapidly growing tree of dependencies would be pruned to produce some symbol rather than another for the outside world to see.[10]

Control structures edit

Lazy evaluation allows control structures to be defined normally, and not as primitives or compile-time techniques. For example one can define if-then-else and short-circuit evaluation operators:[11][12]

ifThenElse True b c = b ifThenElse False b c = c -- or True || b = True False || b = b -- and True && b = b False && b = False 

These have the usual semantics, i.e., ifThenElse a b c evaluates (a), then if and only if (a) evaluates to true does it evaluate (b), otherwise it evaluates (c). That is, exactly one of (b) or (c) will be evaluated. Similarly, for EasilyComputed || LotsOfWork, if the easy part gives True the lots of work expression could be avoided. Finally, when evaluating SafeToTry && Expression, if SafeToTry is false there will be no attempt at evaluating the Expression.

Conversely, in an eager language the above definition for ifThenElse a b c would evaluate (a), (b), and (c) regardless of the value of (a). This is not the desired behavior, as (b) or (c) may have side effects, take a long time to compute, or throw errors. It is usually possible to introduce user-defined lazy control structures in eager languages as functions, though they may depart from the language's syntax for eager evaluation: Often the involved code bodies need to be wrapped in a function value, so that they are executed only when called.

Working with infinite data structures edit

Delayed evaluation has the advantage of being able to create calculable infinite lists without infinite loops or size matters interfering in computation. The actual values are only computed when needed. For example, one could create a function that creates an infinite list (often called a stream) of Fibonacci numbers. The calculation of the n-th Fibonacci number would be merely the extraction of that element from the infinite list, forcing the evaluation of only the first n members of the list.[13][14]

Take for example this trivial program in Haskell:

numberFromInfiniteList :: Int -> Int numberFromInfiniteList n = infinity !! n - 1  where infinity = [1..] main = print $ numberFromInfiniteList 4 

In the function numberFromInfiniteList, the value of infinity is an infinite range, but until an actual value (or more specifically, a specific value at a certain index) is needed, the list is not evaluated, and even then, it is only evaluated as needed (that is, until the desired index.) Provided the programmer is careful, the program completes normally. However, certain calculations may result in the program attempting to evaluate an infinite number of elements; for example, requesting the length of the list or trying to sum the elements of the list with a fold operation would result in the program either failing to terminate or running out of memory.

As another example, the list of all Fibonacci numbers can be written in the programming language Haskell as:[14]

 fibs = 0 : 1 : zipWith (+) fibs (tail fibs) 

In Haskell syntax, ":" prepends an element to a list, tail returns a list without its first element, and zipWith uses a specified function (in this case addition) to combine corresponding elements of two lists to produce a third.[13]

List-of-successes pattern edit

Other uses edit

In computer windowing systems, the painting of information to the screen is driven by expose events which drive the display code at the last possible moment. By doing this, windowing systems avoid computing unnecessary display content updates.[15]

Another example of laziness in modern computer systems is copy-on-write page allocation or demand paging, where memory is allocated only when a value stored in that memory is changed.[15]

Laziness can be useful for high performance scenarios. An example is the Unix mmap function, which provides demand driven loading of pages from disk, so that only those pages actually touched are loaded into memory, and unneeded memory is not allocated.

MATLAB implements copy on edit, where arrays which are copied have their actual memory storage replicated only when their content is changed, possibly leading to an out of memory error when updating an element afterwards instead of during the copy operation.[16]

Performance edit

The number of beta reductions to reduce a lambda term with call-by-need is no larger than the number needed by call-by-value or call-by-name reduction.[17][18] And with certain programs the number of steps may be much smaller, for example a specific family of lambda terms using Church numerals take an infinite amount of steps with call-by-value (i.e. never complete), an exponential number of steps with call-by-name, but only a polynomial number with call-by-need. Call-by-need embodies two optimizations - never repeat work (similar to call-by-value), and never perform unnecessary work (similar to call-by-name).[19] Lazy evaluation can also lead to reduction in memory footprint, since values are created when needed.[20]

In practice, lazy evaluation may cause significant performance issues compared to eager evaluation. For example, on modern computer architectures, delaying a computation and performing it later is slower than performing it immediately. This can be alleviated through strictness analysis.[19] Lazy evaluation can also introduce memory leaks due to unevaluated expressions.[21][22]

Implementation edit

Some programming languages delay evaluation of expressions by default, and some others provide functions or special syntax to delay evaluation. In Miranda and Haskell, evaluation of function arguments is delayed by default. In many other languages, evaluation can be delayed by explicitly suspending the computation using special syntax (as with Scheme's "delay" and "force" and OCaml's "lazy" and "Lazy.force") or, more generally, by wrapping the expression in a thunk. The object representing such an explicitly delayed evaluation is called a lazy future. Raku uses lazy evaluation of lists, so one can assign infinite lists to variables and use them as arguments to functions, but unlike Haskell and Miranda, Raku does not use lazy evaluation of arithmetic operators and functions by default.[10]

Laziness and eagerness edit

Controlling eagerness in lazy languages edit

In lazy programming languages such as Haskell, although the default is to evaluate expressions only when they are demanded, it is possible in some cases to make code more eager—or conversely, to make it more lazy again after it has been made more eager. This can be done by explicitly coding something which forces evaluation (which may make the code more eager) or avoiding such code (which may make the code more lazy). Strict evaluation usually implies eagerness, but they are technically different concepts.

However, there is an optimisation implemented in some compilers called strictness analysis, which, in some cases, allows the compiler to infer that a value will always be used. In such cases, this may render the programmer's choice of whether to force that particular value or not, irrelevant, because strictness analysis will force strict evaluation.

In Haskell, marking constructor fields strict means that their values will always be demanded immediately. The seq function can also be used to demand a value immediately and then pass it on, which is useful if a constructor field should generally be lazy. However, neither of these techniques implements recursive strictness—for that, a function called deepSeq was invented.

Also, pattern matching in Haskell 98 is strict by default, so the ~ qualifier has to be used to make it lazy.[23]

Simulating laziness in eager languages edit

Java edit

In Java, lazy evaluation can be done by using objects that have a method to evaluate them when the value is needed. The body of this method must contain the code required to perform this evaluation. Since the introduction of lambda expressions in Java SE8, Java has supported a compact notation for this. The following example generic interface provides a framework for lazy evaluation:[24][25]

interface Lazy<T> {  T eval(); } 

The Lazy interface with its eval() method is equivalent to the Supplier interface with its get() method in the java.util.function library.[26][27]: 200 

Each class that implements the Lazy interface must provide an eval method, and instances of the class may carry whatever values the method needs to accomplish lazy evaluation. For example, consider the following code to lazily compute and print 210:

Lazy<Integer> a = () -> 1; for (int i = 0; i < 10; i++) {  Lazy<Integer> b = a;  a = () -> b.eval() + b.eval(); } System.out.println("a = " + a.eval()); 

In the above, the variable a initially refers to a lazy integer object created by the lambda expression () -> 1. Evaluating this lambda expression is similar[a] to constructing a new instance of an anonymous class that implements Lazy<Integer> with an eval method returning 1.

Each iteration of the loop links a to a new object created by evaluating the lambda expression inside the loop. Each of these objects holds a reference to another lazy object, b, and has an eval method that calls b.eval() twice and returns the sum. The variable b is needed here to meet Java's requirement that variables referenced from within a lambda expression be effectively final.

This is an inefficient program because this implementation of lazy integers does not memoize the result of previous calls to eval. It also involves considerable autoboxing and unboxing. What may not be obvious is that, at the end of the loop, the program has constructed a linked list of 11 objects and that all of the actual additions involved in computing the result are done in response to the call to a.eval() on the final line of code. This call recursively traverses the list to perform the necessary additions.

We can build a Java class that memoizes a lazy object as follows:[24][25]

class Memo<T> implements Lazy<T> {  private Lazy<T> lazy; // a lazy expression, eval sets it to null  private T memo; // the memorandum of the previous value  public Memo(Lazy<T> lazy) {  this.lazy = lazy;  }  public T eval() {  if (lazy != null) {  memo = lazy.eval();  lazy = null;  }  return memo;  } } 

This allows the previous example to be rewritten to be far more efficient. Where the original ran in time exponential in the number of iterations, the memoized version runs in linear time:

Lazy<Integer> a = () -> 1; for (int i = 0; i < 10; i++) {  Lazy<Integer> b = a;  a = new Memo<Integer>(() -> b.eval() + b.eval()); } System.out.println("a = " + a.eval()); 

Java's lambda expressions are just syntactic sugar. Anything that can be written with a lambda expression can be rewritten as a call to construct an instance of an anonymous inner class implementing the interface,[a] and any use of an anonymous inner class can be rewritten using a named inner class, and any named inner class can be moved to the outermost nesting level.

JavaScript edit

In JavaScript, lazy evaluation can be simulated by using a generator. For example, the stream of all Fibonacci numbers can be written, using memoization, as:

/**  * Generator functions return generator objects, which reify lazy evaluation.  * @return {!Generator<bigint>} A non-null generator of integers.  */ function* fibonacciNumbers() {  let memo = [1n, -1n]; // create the initial state (e.g. a vector of "negafibonacci" numbers)  while (true) { // repeat indefinitely  memo = [memo[0] + memo[1], memo[0]]; // update the state on each evaluation  yield memo[0]; // yield the next value and suspend execution until resumed  } } let stream = fibonacciNumbers(); // create a lazy evaluated stream of numbers let first10 = Array.from(new Array(10), () => stream.next().value); // evaluate only the first 10 numbers console.log(first10); // the output is [0n, 1n, 1n, 2n, 3n, 5n, 8n, 13n, 21n, 34n] 

Python edit

In Python 2.x the range() function[28] computes a list of integers. The entire list is stored in memory when the first assignment statement is evaluated, so this is an example of eager or immediate evaluation:

>>> r = range(10) >>> print r [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> print r[3] 3 

In Python 3.x the range() function[29] returns a generator which computes elements of the list on demand. Elements are only generated when they are needed (e.g., when print(r[3]) is evaluated in the following example), so this is an example of lazy or deferred evaluation:

>>> r = range(10) >>> print(r) range(0, 10) >>> print(r[3]) 3 
This change to lazy evaluation saves execution time for large ranges which may never be fully referenced and memory usage for large ranges where only one or a few elements are needed at any time.

In Python 2.x is possible to use a function called xrange() which returns an object that generates the numbers in the range on demand. The advantage of xrange is that generated object will always take the same amount of memory.

>>> r = xrange(10) >>> print(r) xrange(10) >>> lst = [x for x in r] >>> print(lst) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

From version 2.2 forward, Python manifests lazy evaluation by implementing iterators (lazy sequences) unlike tuple or list sequences. For instance (Python 2):

>>> numbers = range(10) >>> iterator = iter(numbers) >>> print numbers [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.

.NET edit

In the .NET framework, it is possible to do lazy evaluation using the class System.Lazy<T>.[30] The class can be easily exploited in F# using the lazy keyword, while the force method will force the evaluation. There are also specialized collections like Microsoft.FSharp.Collections.Seq that provide built-in support for lazy evaluation.

let fibonacci = Seq.unfold (fun (x, y) -> Some(x, (y, x + y))) (0I,1I) fibonacci |> Seq.nth 1000 

In C# and VB.NET, the class System.Lazy<T> is directly used.

public int Sum() {  int a = 0;  int b = 0;   Lazy<int> x = new Lazy<int>(() => a + b);  a = 3;  b = 5;  return x.Value; // returns 8 } 

Or with a more practical example:

// recursive calculation of the n'th fibonacci number public int Fib(int n) {  return (n == 1)? 1 : (n == 2)? 1 : Fib(n-1) + Fib(n-2); } public void Main() {  Console.WriteLine("Which Fibonacci number do you want to calculate?");  int n = Int32.Parse(Console.ReadLine());   Lazy<int> fib = new Lazy<int>(() => Fib(n)); // function is prepared, but not executed  bool execute;   if (n > 100)  {  Console.WriteLine("This can take some time. Do you really want to calculate this large number? [y/n]");  execute = (Console.ReadLine() == "y");   }  else execute = true;    if (execute) Console.WriteLine(fib.Value); // number is only calculated if needed } 

Another way is to use the yield keyword:

// eager evaluation  public IEnumerable<int> Fibonacci(int x) {  IList<int> fibs = new List<int>();  int prev = -1;  int next = 1;  for (int i = 0; i < x; i++)  {  int sum = prev + next;  prev = next;  next = sum;  fibs.Add(sum);   }  return fibs; } // lazy evaluation  public IEnumerable<int> LazyFibonacci(int x) {  int prev = -1;  int next = 1;  for (int i = 0; i < x; i++)  {  int sum = prev + next;  prev = next;  next = sum;  yield return sum;  } } 

See also edit

Notes edit

  1. ^ a b Java lambda expressions are not exactly equivalent to anonymous classes, see Anonymous function#Differences to Anonymous Classes

References edit

  1. ^ Hudak 1989, p. 384
  2. ^ David Anthony Watt; William Findlay (2004). Programming language design concepts. John Wiley and Sons. pp. 367–368. ISBN 978-0-470-85320-7. Retrieved 30 December 2010.
  3. ^ Reynolds 1998, p. 307
  4. ^ Bentley, Jon Louis. Writing Efficient Programs. Prentice-Hall, 1985. ISBN 978-0139702440
  5. ^ Wadsworth 1971
  6. ^ Hamer-Hodges, Kenneth (1 Jan 2020). Civilizing Cyberspace: The Fight for Digital Democracy. BOOK WRITING Incorporated. p. 410. ISBN 978-1-95-163044-7. Retrieved 29 February 2020.
  7. ^ Henderson & Morris 1976
  8. ^ Friedman & Wise 1976
  9. ^ Reynolds 1998, p. 312
  10. ^ a b Casas, A.; Cabeza, D.; Hermenegildo, M.V. (2006). "A Syntactic Approach to Combining Functional Notation, Lazy Evaluation, and Higher-Order in LP Systems". In Hagiya, M.; Wadler, P. (eds.). Functional and logic programming, FLOPS 2006. Lecture Notes in Computer Science. Vol. 3945. Springer. p. 149. doi:10.1007/11737414_11. ISBN 978-3-540-33438-5. Retrieved 14 January 2011.
  11. ^ "utility-ht: Data.Bool.HT.Private". hackage.haskell.org. Retrieved 8 January 2022.
  12. ^ "The Haskell 98 Report: Standard Prelude". www.haskell.org. Boolean functions. Retrieved 8 January 2022.
  13. ^ a b Wells, J.B.; Haack, C. (2002). "Branching Types". In Le Métayer, Daniel (ed.). Programming languages and systems, ESOP 2002. Lecture Notes in Computer Science. Vol. 2305. Springer. pp. 129–132. doi:10.1007/3-540-45927-8_9. ISBN 978-3-540-43363-7.
  14. ^ a b Maessen, Jan-Willem (2002). "Eager Haskell: resource-bounded execution yields efficient iteration". Proceedings of the 2002 ACM SIGPLAN Haskell Workshop (Haskell '02): Pittsburgh, Pennsylvania, USA; October 3, 2002. Association for Computing Machinery. pp. 38–50 See p. 40. doi:10.1145/581690.581694. ISBN 978-1-58113-605-0.
  15. ^ a b Lazy and Speculative Execution Butler Lampson Microsoft Research OPODIS, Bordeaux, France 12 December 2006
  16. ^ "Out of memory when assigning values to existing arrays?". MATLAB Answers. MATLAB Central.
  17. ^ Niehren, Joachim (1996). "Functional computation as concurrent computation" (PDF). Proceedings of the 23rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages - POPL '96. pp. 333–343. doi:10.1145/237721.237801. ISBN 0897917693. S2CID 7332050.
  18. ^ Niehren, Joachim (September 2000). "Uniform confluence in concurrent computation". Journal of Functional Programming. 10 (5): 453–499. doi:10.1017/S0956796800003762. S2CID 66013. Retrieved 7 January 2022.
  19. ^ a b Stelle, George Widgery (July 2019). Shared-Environment Call-by-Need (PhD). University of New Mexico. pp. 11–12. Retrieved 8 January 2022.
  20. ^ Chris Smith (22 October 2009). Programming F#. O'Reilly Media, Inc. p. 79. ISBN 978-0-596-15364-9. Retrieved 31 December 2010.
  21. ^ Launchbury 1993.
  22. ^ Edward Z. Yang. "Space leak zoo".
  23. ^ "Lazy pattern match - HaskellWiki".
  24. ^ a b Grzegorz Piwowarek, Leveraging Lambda Expressions for Lazy Evaluation in Java, 4Comprehension, July 25, 2018.
  25. ^ a b Douglas W. Jones, CS:2820 Notes, Fall 2020, Lecture 25, retrieved Jan. 2021.
  26. ^ Interface Suppier<T>, retrieved Oct. 2020.
  27. ^ Bloch, Joshua (2018). "Effective Java: Programming Language Guide" (third ed.). Addison-Wesley. ISBN 978-0134685991.
  28. ^ "2. Built-in Functions — Python 2.7.11 documentation".
  29. ^ "2. Built-in Functions — Python 3.5.1 documentation".
  30. ^ "Lazy(T) Class (System)". Microsoft.

Sources edit

  • Friedman, D. P.; Wise, David S. (1976). S. Michaelson; R. Milner (eds.). "Cons should not evaluate its arguments" (PDF). Automata Languages and Programming Third International Colloquium. Edinburgh University Press.
  • Henderson, Peter; Morris, James H. (1976). "A lazy evaluator". Proceedings of the 3rd ACM SIGACT-SIGPLAN symposium on Principles on programming languages - POPL '76. pp. 95–103. doi:10.1145/800168.811543. S2CID 1228296.
  • Hudak, Paul (September 1989). "Conception, Evolution, and Application of Functional Programming Languages". ACM Computing Surveys. 21 (3): 383–385. doi:10.1145/72551.72554. S2CID 207637854.
  • Launchbury, John (1993). "A natural semantics for lazy evaluation". Proceedings of the 20th ACM SIGPLAN-SIGACT symposium on Principles of programming languages - POPL '93. pp. 144–154. doi:10.1145/158511.158618. ISBN 0897915607. S2CID 14945994.
  • Reynolds, John C. (1998). Theories of programming languages. Cambridge University Press. ISBN 9780521594141. Retrieved 2016-02-23.
  • Wadsworth, Christopher P. (1971). Semantics and Pragmatics of the Lambda Calculus (PhD thesis). University of Oxford.

External links edit

  • in Nemerle
  • Lambda calculus in Boost Libraries in C++ language
  • Lazy Evaluation in ANSI C++ by writing code in a style which uses classes to implement function closures.

lazy, evaluation, programming, language, theory, lazy, evaluation, call, need, evaluation, strategy, which, delays, evaluation, expression, until, value, needed, strict, evaluation, which, also, avoids, repeated, evaluations, sharing, benefits, lazy, evaluatio. In programming language theory lazy evaluation or call by need 1 is an evaluation strategy which delays the evaluation of an expression until its value is needed non strict evaluation and which also avoids repeated evaluations by the use of sharing 2 3 The benefits of lazy evaluation include The ability to define control flow structures as abstractions instead of primitives The ability to define potentially infinite data structures This allows for more straightforward implementation of some algorithms The ability to define partly defined data structures where some elements are errors This allows for rapid prototyping Lazy evaluation is often combined with memoization as described in Jon Bentley s Writing Efficient Programs 4 After a function s value is computed for that parameter or set of parameters the result is stored in a lookup table that is indexed by the values of those parameters the next time the function is called the table is consulted to determine whether the result for that combination of parameter values is already available If so the stored result is simply returned If not the function is evaluated and another entry is added to the lookup table for reuse Lazy evaluation is difficult to combine with imperative features such as exception handling and input output because the order of operations becomes indeterminate The opposite of lazy evaluation is eager evaluation sometimes known as strict evaluation Eager evaluation is the evaluation strategy employed in most quantify programming languages Contents 1 History 2 Applications 2 1 Control structures 2 2 Working with infinite data structures 2 3 List of successes pattern 2 4 Other uses 3 Performance 4 Implementation 5 Laziness and eagerness 5 1 Controlling eagerness in lazy languages 5 2 Simulating laziness in eager languages 5 2 1 Java 5 2 2 JavaScript 5 2 3 Python 5 2 4 NET 6 See also 7 Notes 8 References 9 Sources 10 External linksHistory editLazy evaluation was introduced for lambda calculus by Christopher Wadsworth 5 and employed by the Plessey System 250 as a critical part of a Lambda Calculus Meta Machine reducing the resolution overhead for access to objects in a capability limited address space 6 For programming languages it was independently introduced by Peter Henderson and James H Morris 7 and by Daniel P Friedman and David S Wise 8 9 Applications editDelayed evaluation is used particularly in functional programming languages When using delayed evaluation an expression is not evaluated as soon as it gets bound to a variable but when the evaluator is forced to produce the expression s value That is a statement such as x expression i e the assignment of the result of an expression to a variable clearly calls for the expression to be evaluated and the result placed in x but what actually is in x is irrelevant until there is a need for its value via a reference to x in some later expression whose evaluation could itself be deferred though eventually the rapidly growing tree of dependencies would be pruned to produce some symbol rather than another for the outside world to see 10 Control structures edit This section needs additional citations for verification Please help improve this article by adding citations to reliable sources in this section Unsourced material may be challenged and removed March 2011 Learn how and when to remove this template message Lazy evaluation allows control structures to be defined normally and not as primitives or compile time techniques For example one can define if then else and short circuit evaluation operators 11 12 ifThenElse True b c b ifThenElse False b c c or True b True False b b and True amp amp b b False amp amp b False These have the usual semantics i e span class nf ifThenElse span span class w span span class n a span span class w span span class n b span span class w span span class n c span evaluates a then if and only if a evaluates to true does it evaluate b otherwise it evaluates c That is exactly one of b or c will be evaluated Similarly for span class kt EasilyComputed span span class w span span class o span span class w span span class kt LotsOfWork span if the easy part gives True the lots of work expression could be avoided Finally when evaluating span class kt SafeToTry span span class w span span class o amp amp span span class w span span class kt Expression span if SafeToTry is false there will be no attempt at evaluating the Expression Conversely in an eager language the above definition for span class nf ifThenElse span span class w span span class n a span span class w span span class n b span span class w span span class n c span would evaluate a b and c regardless of the value of a This is not the desired behavior as b or c may have side effects take a long time to compute or throw errors It is usually possible to introduce user defined lazy control structures in eager languages as functions though they may depart from the language s syntax for eager evaluation Often the involved code bodies need to be wrapped in a function value so that they are executed only when called Working with infinite data structures edit Delayed evaluation has the advantage of being able to create calculable infinite lists without infinite loops or size matters interfering in computation The actual values are only computed when needed For example one could create a function that creates an infinite list often called a stream of Fibonacci numbers The calculation of the n th Fibonacci number would be merely the extraction of that element from the infinite list forcing the evaluation of only the first n members of the list 13 14 Take for example this trivial program in Haskell numberFromInfiniteList Int gt Int numberFromInfiniteList n infinity n 1 where infinity 1 main print numberFromInfiniteList 4 In the function numberFromInfiniteList the value of infinity is an infinite range but until an actual value or more specifically a specific value at a certain index is needed the list is not evaluated and even then it is only evaluated as needed that is until the desired index Provided the programmer is careful the program completes normally However certain calculations may result in the program attempting to evaluate an infinite number of elements for example requesting the length of the list or trying to sum the elements of the list with a fold operation would result in the program either failing to terminate or running out of memory As another example the list of all Fibonacci numbers can be written in the programming language Haskell as 14 fibs 0 1 zipWith fibs tail fibs In Haskell syntax prepends an element to a list tail returns a list without its first element and zipWith uses a specified function in this case addition to combine corresponding elements of two lists to produce a third 13 List of successes pattern edit This section needs expansion You can help by adding to it March 2011 Other uses edit In computer windowing systems the painting of information to the screen is driven by expose events which drive the display code at the last possible moment By doing this windowing systems avoid computing unnecessary display content updates 15 Another example of laziness in modern computer systems is copy on write page allocation or demand paging where memory is allocated only when a value stored in that memory is changed 15 Laziness can be useful for high performance scenarios An example is the Unix mmap function which provides demand driven loading of pages from disk so that only those pages actually touched are loaded into memory and unneeded memory is not allocated MATLAB implements copy on edit where arrays which are copied have their actual memory storage replicated only when their content is changed possibly leading to an out of memory error when updating an element afterwards instead of during the copy operation 16 Performance editThe number of beta reductions to reduce a lambda term with call by need is no larger than the number needed by call by value or call by name reduction 17 18 And with certain programs the number of steps may be much smaller for example a specific family of lambda terms using Church numerals take an infinite amount of steps with call by value i e never complete an exponential number of steps with call by name but only a polynomial number with call by need Call by need embodies two optimizations never repeat work similar to call by value and never perform unnecessary work similar to call by name 19 Lazy evaluation can also lead to reduction in memory footprint since values are created when needed 20 In practice lazy evaluation may cause significant performance issues compared to eager evaluation For example on modern computer architectures delaying a computation and performing it later is slower than performing it immediately This can be alleviated through strictness analysis 19 Lazy evaluation can also introduce memory leaks due to unevaluated expressions 21 22 Implementation editSome programming languages delay evaluation of expressions by default and some others provide functions or special syntax to delay evaluation In Miranda and Haskell evaluation of function arguments is delayed by default In many other languages evaluation can be delayed by explicitly suspending the computation using special syntax as with Scheme s delay and force and OCaml s lazy and Lazy force or more generally by wrapping the expression in a thunk The object representing such an explicitly delayed evaluation is called a lazy future Raku uses lazy evaluation of lists so one can assign infinite lists to variables and use them as arguments to functions but unlike Haskell and Miranda Raku does not use lazy evaluation of arithmetic operators and functions by default 10 Laziness and eagerness editControlling eagerness in lazy languages edit In lazy programming languages such as Haskell although the default is to evaluate expressions only when they are demanded it is possible in some cases to make code more eager or conversely to make it more lazy again after it has been made more eager This can be done by explicitly coding something which forces evaluation which may make the code more eager or avoiding such code which may make the code more lazy Strict evaluation usually implies eagerness but they are technically different concepts However there is an optimisation implemented in some compilers called strictness analysis which in some cases allows the compiler to infer that a value will always be used In such cases this may render the programmer s choice of whether to force that particular value or not irrelevant because strictness analysis will force strict evaluation In Haskell marking constructor fields strict means that their values will always be demanded immediately The seq function can also be used to demand a value immediately and then pass it on which is useful if a constructor field should generally be lazy However neither of these techniques implements recursive strictness for that a function called deepSeq was invented Also pattern matching in Haskell 98 is strict by default so the a href Tilde html Computer languages title Tilde a qualifier has to be used to make it lazy 23 Simulating laziness in eager languages edit Java edit In Java lazy evaluation can be done by using objects that have a method to evaluate them when the value is needed The body of this method must contain the code required to perform this evaluation Since the introduction of lambda expressions in Java SE8 Java has supported a compact notation for this The following example generic interface provides a framework for lazy evaluation 24 25 interface Lazy lt T gt T eval The Lazy interface with its eval method is equivalent to the Supplier interface with its get method in the java util function library 26 27 200 Each class that implements the Lazy interface must provide an eval method and instances of the class may carry whatever values the method needs to accomplish lazy evaluation For example consider the following code to lazily compute and print 210 Lazy lt Integer gt a gt 1 for int i 0 i lt 10 i Lazy lt Integer gt b a a gt b eval b eval System out println a a eval In the above the variable a initially refers to a lazy integer object created by the lambda expression gt 1 Evaluating this lambda expression is similar a to constructing a new instance of an anonymous class that implements Lazy lt Integer gt with an eval method returning 1 Each iteration of the loop links a to a new object created by evaluating the lambda expression inside the loop Each of these objects holds a reference to another lazy object b and has an eval method that calls b eval twice and returns the sum The variable b is needed here to meet Java s requirement that variables referenced from within a lambda expression be effectively final This is an inefficient program because this implementation of lazy integers does not memoize the result of previous calls to eval It also involves considerable autoboxing and unboxing What may not be obvious is that at the end of the loop the program has constructed a linked list of 11 objects and that all of the actual additions involved in computing the result are done in response to the call to a eval on the final line of code This call recursively traverses the list to perform the necessary additions We can build a Java class that memoizes a lazy object as follows 24 25 class Memo lt T gt implements Lazy lt T gt private Lazy lt T gt lazy a lazy expression eval sets it to null private T memo the memorandum of the previous value public Memo Lazy lt T gt lazy this lazy lazy public T eval if lazy null memo lazy eval lazy null return memo This allows the previous example to be rewritten to be far more efficient Where the original ran in time exponential in the number of iterations the memoized version runs in linear time Lazy lt Integer gt a gt 1 for int i 0 i lt 10 i Lazy lt Integer gt b a a new Memo lt Integer gt gt b eval b eval System out println a a eval Java s lambda expressions are just syntactic sugar Anything that can be written with a lambda expression can be rewritten as a call to construct an instance of an anonymous inner class implementing the interface a and any use of an anonymous inner class can be rewritten using a named inner class and any named inner class can be moved to the outermost nesting level JavaScript edit In JavaScript lazy evaluation can be simulated by using a generator For example the stream of all Fibonacci numbers can be written using memoization as Generator functions return generator objects which reify lazy evaluation return Generator lt bigint gt A non null generator of integers function fibonacciNumbers let memo 1n 1n create the initial state e g a vector of negafibonacci numbers while true repeat indefinitely memo memo 0 memo 1 memo 0 update the state on each evaluation yield memo 0 yield the next value and suspend execution until resumed let stream fibonacciNumbers create a lazy evaluated stream of numbers let first10 Array from new Array 10 gt stream next value evaluate only the first 10 numbers console log first10 the output is 0n 1n 1n 2n 3n 5n 8n 13n 21n 34n Python edit In Python 2 x the range function 28 computes a list of integers The entire list is stored in memory when the first assignment statement is evaluated so this is an example of eager or immediate evaluation gt gt gt r range 10 gt gt gt print r 0 1 2 3 4 5 6 7 8 9 gt gt gt print r 3 3 In Python 3 x the range function 29 returns a generator which computes elements of the list on demand Elements are only generated when they are needed e g when print r 3 is evaluated in the following example so this is an example of lazy or deferred evaluation gt gt gt r range 10 gt gt gt print r range 0 10 gt gt gt print r 3 3 This change to lazy evaluation saves execution time for large ranges which may never be fully referenced and memory usage for large ranges where only one or a few elements are needed at any time In Python 2 x is possible to use a function called xrange which returns an object that generates the numbers in the range on demand The advantage of xrange is that generated object will always take the same amount of memory gt gt gt r xrange 10 gt gt gt print r xrange 10 gt gt gt lst x for x in r gt gt gt print lst 0 1 2 3 4 5 6 7 8 9 From version 2 2 forward Python manifests lazy evaluation by implementing iterators lazy sequences unlike tuple or list sequences For instance Python 2 gt gt gt numbers range 10 gt gt gt iterator iter numbers gt gt gt print numbers 0 1 2 3 4 5 6 7 8 9 gt gt gt print iterator lt listiterator object at 0xf7e8dd4c gt gt gt gt 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 NET edit In the NET framework it is possible to do lazy evaluation using the class span class n System span span class p span span class n Lazy span span class o lt span span class n T span span class o gt span 30 The class can be easily exploited in F using the span class k lazy span keyword while the span class n force span method will force the evaluation There are also specialized collections like span class n Microsoft span span class p span span class n FSharp span span class p span span class n Collections span span class p span span class n Seq span that provide built in support for lazy evaluation let fibonacci Seq unfold fun x y gt Some x y x y 0I 1I fibonacci gt Seq nth 1000 In C and VB NET the class span class n System span span class p span span class n Lazy span span class o lt span span class n T span span class o gt span is directly used public int Sum int a 0 int b 0 Lazy lt int gt x new Lazy lt int gt gt a b a 3 b 5 return x Value returns 8 Or with a more practical example recursive calculation of the n th fibonacci number public int Fib int n return n 1 1 n 2 1 Fib n 1 Fib n 2 public void Main Console WriteLine Which Fibonacci number do you want to calculate int n Int32 Parse Console ReadLine Lazy lt int gt fib new Lazy lt int gt gt Fib n function is prepared but not executed bool execute if n gt 100 Console WriteLine This can take some time Do you really want to calculate this large number y n execute Console ReadLine y else execute true if execute Console WriteLine fib Value number is only calculated if needed Another way is to use the span class k yield span keyword eager evaluation public IEnumerable lt int gt Fibonacci int x IList lt int gt fibs new List lt int gt int prev 1 int next 1 for int i 0 i lt x i int sum prev next prev next next sum fibs Add sum return fibs lazy evaluation public IEnumerable lt int gt LazyFibonacci int x int prev 1 int next 1 for int i 0 i lt x i int sum prev next prev next next sum yield return sum Main article Thunk This section needs expansion You can help by adding to it May 2011 See also editCombinatory logic Currying Dataflow Eager evaluation Functional programming Futures and promises Generator computer programming Graph reduction Incremental computing a related concept whereby computations are only repeated if their inputs change May be combined with lazy evaluation Lambda calculus Lazy initialization Look ahead Non strict programming language Normal order evaluation Short circuit evaluation minimal Notes edit a b Java lambda expressions are not exactly equivalent to anonymous classes see Anonymous function Differences to Anonymous ClassesReferences edit Hudak 1989 p 384 David Anthony Watt William Findlay 2004 Programming language design concepts John Wiley and Sons pp 367 368 ISBN 978 0 470 85320 7 Retrieved 30 December 2010 Reynolds 1998 p 307 Bentley Jon Louis Writing Efficient Programs Prentice Hall 1985 ISBN 978 0139702440 Wadsworth 1971 Hamer Hodges Kenneth 1 Jan 2020 Civilizing Cyberspace The Fight for Digital Democracy BOOK WRITING Incorporated p 410 ISBN 978 1 95 163044 7 Retrieved 29 February 2020 Henderson amp Morris 1976 Friedman amp Wise 1976 Reynolds 1998 p 312 a b Casas A Cabeza D Hermenegildo M V 2006 A Syntactic Approach to Combining Functional Notation Lazy Evaluation and Higher Order in LP Systems In Hagiya M Wadler P eds Functional and logic programming FLOPS 2006 Lecture Notes in Computer Science Vol 3945 Springer p 149 doi 10 1007 11737414 11 ISBN 978 3 540 33438 5 Retrieved 14 January 2011 utility ht Data Bool HT Private hackage haskell org Retrieved 8 January 2022 The Haskell 98 Report Standard Prelude www haskell org Boolean functions Retrieved 8 January 2022 a b Wells J B Haack C 2002 Branching Types In Le Metayer Daniel ed Programming languages and systems ESOP 2002 Lecture Notes in Computer Science Vol 2305 Springer pp 129 132 doi 10 1007 3 540 45927 8 9 ISBN 978 3 540 43363 7 a b Maessen Jan Willem 2002 Eager Haskell resource bounded execution yields efficient iteration Proceedings of the 2002 ACM SIGPLAN Haskell Workshop Haskell 02 Pittsburgh Pennsylvania USA October 3 2002 Association for Computing Machinery pp 38 50 See p 40 doi 10 1145 581690 581694 ISBN 978 1 58113 605 0 a b Lazy and Speculative Execution Butler Lampson Microsoft Research OPODIS Bordeaux France 12 December 2006 Out of memory when assigning values to existing arrays MATLAB Answers MATLAB Central Niehren Joachim 1996 Functional computation as concurrent computation PDF Proceedings of the 23rd ACM SIGPLAN SIGACT symposium on Principles of programming languages POPL 96 pp 333 343 doi 10 1145 237721 237801 ISBN 0897917693 S2CID 7332050 Niehren Joachim September 2000 Uniform confluence in concurrent computation Journal of Functional Programming 10 5 453 499 doi 10 1017 S0956796800003762 S2CID 66013 Retrieved 7 January 2022 a b Stelle George Widgery July 2019 Shared Environment Call by Need PhD University of New Mexico pp 11 12 Retrieved 8 January 2022 Chris Smith 22 October 2009 Programming F O Reilly Media Inc p 79 ISBN 978 0 596 15364 9 Retrieved 31 December 2010 Launchbury 1993 Edward Z Yang Space leak zoo Lazy pattern match HaskellWiki a b Grzegorz Piwowarek Leveraging Lambda Expressions for Lazy Evaluation in Java 4Comprehension July 25 2018 a b Douglas W Jones CS 2820 Notes Fall 2020 Lecture 25 retrieved Jan 2021 Interface Suppier lt T gt retrieved Oct 2020 Bloch Joshua 2018 Effective Java Programming Language Guide third ed Addison Wesley ISBN 978 0134685991 2 Built in Functions Python 2 7 11 documentation 2 Built in Functions Python 3 5 1 documentation Lazy T Class System Microsoft Sources editFriedman D P Wise David S 1976 S Michaelson R Milner eds Cons should not evaluate its arguments PDF Automata Languages and Programming Third International Colloquium Edinburgh University Press Henderson Peter Morris James H 1976 A lazy evaluator Proceedings of the 3rd ACM SIGACT SIGPLAN symposium on Principles on programming languages POPL 76 pp 95 103 doi 10 1145 800168 811543 S2CID 1228296 Hudak Paul September 1989 Conception Evolution and Application of Functional Programming Languages ACM Computing Surveys 21 3 383 385 doi 10 1145 72551 72554 S2CID 207637854 Launchbury John 1993 A natural semantics for lazy evaluation Proceedings of the 20th ACM SIGPLAN SIGACT symposium on Principles of programming languages POPL 93 pp 144 154 doi 10 1145 158511 158618 ISBN 0897915607 S2CID 14945994 Reynolds John C 1998 Theories of programming languages Cambridge University Press ISBN 9780521594141 Retrieved 2016 02 23 Wadsworth Christopher P 1971 Semantics and Pragmatics of the Lambda Calculus PhD thesis University of Oxford External links editLazy evaluation macros in Nemerle Lambda calculus in Boost Libraries in C language Lazy Evaluation in ANSI C by writing code in a style which uses classes to implement function closures Retrieved from https en wikipedia org w index php title Lazy evaluation amp oldid 1197571399, wikipedia, wiki, book, books, library,

article

, read, download, free, free download, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, picture, music, song, movie, book, game, games.