Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of lazy evaluation in this comment?

in the Boilerplate I am using for a React Redux project I came across this comment in the code:

This is a thunk, meaning it is a function that immediately returns a function for lazy evaluation. It is incredibly useful for creating async actions, especially when combined with redux-thunk!

Now, if I understand this correctly, lazy evaluation is the process of returning a function. What is the purpose of returning a function though, and how is this great for creating async actions?

Oh also, is a thunk just a function?

like image 790
Michael Jones Avatar asked Aug 11 '16 19:08

Michael Jones


People also ask

What do you mean by lazy evaluation?

In programming language theory, lazy evaluation, or call-by-need, 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 (sharing).

Is lazy evaluation good?

Always using lazy evaluation also implies early optimization. This is a bad practice which often results in code which is much more complex and expensive that might otherwise be the case. Unfortunately, premature optimization often results in code that performs slower than simpler code.

What is lazy evaluation in C?

Lazy evaluation or call-by-need is a evaluation strategy where an expression isn't evaluated until its first use i.e to postpone the evaluation till its demanded. Functional programming languages like Haskell use this strategy extensively.

Is lazy evaluation strict or non strict?

Lazy evaluation is a form of non-strict evaluation in which arguments are not evaluated until required. A computation that does not terminate under strict evaluation, can terminate under lazy evaluation.


2 Answers

A thunk is a function that takes no arguments and returns something (or does something as a side effect). Lazy evaluation is the process of deferring the evaluation of an expression until later, and this can be done with thunks:

// Not lazy
var value = 1 + 1  // immediately evaluates to 2

// Lazy
var lazyValue = () => 1 + 1  // Evaluates to 2 when lazyValue is *invoked*

You can also make return values lazy:

// Not lazy
var add = (x, y) => x + y
var result = add(1, 2)  // Immediately evaluates to 3

// Lazy
var addLazy = (x, y) => () => x + y;
var result = addLazy(1, 2)  // Returns a thunk which *when evaluated* results in 3.

Finally we can defer some asynchronous action:

// Not lazy
var callApi = spec => fetch(spec.url, spec.options);
// Immediately returns a Promise which will be fulfilled when the network response is processed.
var result = callApi({url: '/api', options: {}});

// Lazy
var callApiLazy = spec => () => fetch(spec.url, spec.options);
var result = callApiLazy({url: '/api', options: {}});
// result is a thunk that when evaluated will return a Promise ...
// which will be fulfilled when the network response is processed.

Now a thunk does not have to take zero arguments - you could return a lazy value that requires more arguments to successfully evaluate. This is properly known as "currying":

// Curried add (not lazy)
var add = x => y => x + y
var add3 = add(3)
var result = add3(7)  // Immediately evaluates to 10

redux-thunk lets you return functions, rather than objects, as actions and invokes your function with a dispatch function. You can then lazily produce an action (or actions) either synchronously or asynchronously. Most of the time, you would want to use this to allow you to dispatch asynchronously.

See also:

  • http://www.datchley.name/currying-vs-partial-application/
like image 89
Sean Vieira Avatar answered Oct 16 '22 05:10

Sean Vieira


Normally, Redux action creators are synchronous, meaning that, when you call them, you would expect them to return an Action and the Reducers to be called immediately and the state to change on the fly. You also expect this process to be really fast, because nothing but a small CPU-bound operation would be performed.

However, sometimes you want your action creator to go to the server, or do some non-CPU bound operation that would take a while. That's when it makes sense to return a function instead.

When your action creator returns a function, it returns immediately. From the perspective of who calls the action creator, nothing strange happened. Everything is as usual. But internally, instead of returning the Action object, your action creator returned a function like this..

function DoSomethingAsync() {
    return (dispatch) => {
        // go do something realllly slowly.
        // ok now get the RESULT and call a regular action
        dispatch(mySyncAction(RESULT));
    }
}

Normally DoSomethingAsync would return an Object. What the Redux-Thunk middleware does is to detect that a function was returned instead.. So, it does nothing but to call this function passing the same dispatch as usual.

Now it's responsability of the callback to call dispatch to dispatch a SYNC action.

like image 32
André Pena Avatar answered Oct 16 '22 04:10

André Pena