Why is lazy evaluation useful?

后端 未结 22 1512
无人共我
无人共我 2020-11-29 17:04

I have long been wondering why lazy evaluation is useful. I have yet to have anyone explain to me in a way that makes sense; mostly it ends up boiling down to \"trust me\".<

相关标签:
22条回答
  • 2020-11-29 17:49

    I don't know how you currently think of things, but I find it useful to think of lazy evaluation as a library issue rather than a language feature.

    I mean that in strict languages, I can implement lazy evaluation by building a few data structures, and in lazy languages (at least Haskell), I can ask for strictness when I want it. Therefore, the language choice doesn't really make your programs lazy or non-lazy, but simply affects which you get by default.

    Once you think of it like that, then think of all the places where you write a data structure that you can later use to generate data (without looking at it too much before then), and you'll see a lot of uses for lazy evaluation.

    0 讨论(0)
  • 2020-11-29 17:50

    Lazy evaluation related to CPU the same way as garbage collection related to RAM. GC allows you to pretend that you have unlimited amount of memory and thus request as many objects in memory as you need. Runtime will automatically reclaim unusable objects. LE allows you pretending that you have unlimited computational resources - you can do as many computations as you need. Runtime just will not execute unnecessary (for given case) computations.

    What is the practical advantage of these "pretending" models? It releases developer (to some extent) from managing resources and removes some boilerplate code from your sources. But more important is that you can efficiently reuse your solution in wider set of contexts.

    Imagine that you have a list of numbers S and a number N. You need to find the closest to number N number M from list S. You can have two contexts: single N and some list L of Ns (e.i. for each N in L you look up the closest M in S). If you use lazy evaluation, you can sort S and apply binary search to find closest M to N. For good lazy sorting it will require O(size(S)) steps for single N and O(ln(size(S))*(size(S) + size(L))) steps for equally distributed L. If you don't have lazy evaluation to achieve the optimal efficiency you have to implement algorithm for each context.

    0 讨论(0)
  • 2020-11-29 17:50

    The most useful exploitation of lazy evaluation that I've used was a function that called a series of sub-functions in a particular order. If any one of these sub-functions failed (returned false), the calling function needed to immediately return. So I could have done it this way:

    bool Function(void) {
      if (!SubFunction1())
        return false;
      if (!SubFunction2())
        return false;
      if (!SubFunction3())
        return false;
    
    (etc)
    
      return true;
    }
    

    or, the more elegant solution:

    bool Function(void) {
      if (!SubFunction1() || !SubFunction2() || !SubFunction3() || (etc) )
        return false;
      return true;
    }
    

    Once you start using it, you'll see opportunities to use it more and more often.

    0 讨论(0)
  • 2020-11-29 17:51

    Here are two more points which I do not believe have been brought up in the discussion yet.

    1. Laziness is a synchronization mechanism in a concurrent environment. It is a lightweight and easy way to create a reference to some computation, and share its results among many threads. If multiple threads attempt to access an unevaluated value, only one of them will execute it, and the others will block accordingly, receiving the value once it becomes available.

    2. Laziness is fundamental to amortizing data structures in a pure setting. This is described by Okasaki in Purely Functional Data Structures in detail, but the basic idea is that lazy evaluation is a controlled form of mutation critical to allowing us implement certain types of data structures efficiently. While we often speak of laziness forcing us to wear the purity hairshirt, the other way applies too: they are a pair of synergistic language features.

    0 讨论(0)
  • 2020-11-29 17:52
    1. It can boost efficiency. This is the obvious-looking one, but it's not actually the most important. (Note also that laziness can kill efficiency too - this fact is not immediately obvious. However, by storing up lots of temporary results rather than calculating them immediately, you can use up a huge amount of RAM.)

    2. It lets you define flow control constructs in normal user-level code, rather than it being hard-coded into the language. (E.g., Java has for loops; Haskell has a for function. Java has exception handling; Haskell has various types of exception monad. C# has goto; Haskell has the continuation monad...)

    3. It lets you decouple the algorithm for generating data from the algorithm for deciding how much data to generate. You can write one function that generates a notionally-infinite list of results, and another function that processes as much of this list as it decides it needs. More to the point, you can have five generator functions and five consumer functions, and you can efficiently produce any combination - instead of manually coding 5 x 5 = 25 functions that combine both actions at once. (!) We all know decoupling is a good thing.

    4. It more or less forces you to design a pure functional language. It's always tempting to take short-cuts, but in a lazy language, the slightest impurity makes your code wildly unpredictable, which strongly militates against taking shortcuts.

    0 讨论(0)
  • 2020-11-29 17:54

    When you turn on your computer and Windows refrains from opening every single directory on your hard drive in Windows Explorer and refrains from launching every single program installed on your computer, until you indicate that a certain directory is needed or a certain program is needed, that is "lazy" evaluation.

    "Lazy" evaluation is performing operations when and as they are needed. It is useful when it is a feature of a programming language or library because it is generally harder to implement lazy evaluation on your own than simply to precalculate everything up front.

    0 讨论(0)
提交回复
热议问题