Understanding the syntax of a deferred execution chain Understanding the syntax of a deferred execution chain javascript javascript

Understanding the syntax of a deferred execution chain


It's actually really easy to understand. Let's look at what's going on here when the expression is evaluated:

First the delayedAdd(2, 3) function will be called. It does some stuff and then returns. The "magic" is all about its return value which is a function. To be more precise it's a function that expects at least one argument (I'll get back to that).

Now that we evaluated delayedAdd(2, 3) to a function we get to the next part of the code, which is the opening parenthesis. Opening and closing parenthesis are of course function calls. So we're going to call the function that delayedAdd(2, 3) just returned and we're going to pass it an argument, which is what gets defined next:

That argument is yet another function (as you can see in your example). This function also takes one argument (the result of the computation) and returns it multiplied by itself.

This function that was returned by the first call to delayedAdd(2, 3) returns yet another function, which we'll call again with an argument that is another function (the next part of the chain).

So to summarize we build up a chain of functions by passing our code to whatever function delayedAdd(2, 3) returned. These functions will return other functions that we can pass our functions again.

I hope this makes the way it works somewhat clear, if not feel free to ask more.


mhlz's answer is very clear. As a supplementary, here I compose a delayedAdd for your to better understand the process

function delayedAdd(a, b) {  var sum = a + b  return function(f1) {    var result1 = f1(sum)    return function(f2) {      f2(result1)    }  }}

Where in your example code, the function you passed as f1 is:

function (result) {  return result * result}

and f2 is:

function (result) {  console.log(result)}


Functions are first-class citizens in JS - that means (among others), they can take the role of actual parameters and function return values. Your code fragment maps functions to functions.

The signatures of the functions in your chained call might look like this.

delayedAdd: number -> fn                     // returns function type a         a: fn ( number -> number) -> fn     // returns function type b         b: fn ( number -> void )  -> void   // returns nothing ( guessing, cannot know from your code portion )

General setting

Of course, JS is a weakly typed language, so the listed signatures are derived from the code fragment by guessing. There is no way to know whether the code actually does what is suggested above apart from inspecting the sources.

Given that this showed up in the context of 'chaining', the signatures probably rather look like this:

delayedAdd: number x number -> fn (( fn T -> void ) -> ( fn T -> void ))

Which means that delayedAdd maps two numbers to a function x, which maps functions of arbitrary signatures to functions of the same signature as itself.

So who would do anything like this ? And why ?

Imagine the following implementation of x:

 // // x // Collects functions of unspecified (possibly implicit) signatures for later execution. // Illustrative purpose only, do not use in production code. // // Assumes  function x ( fn ) {     var fn_current;     if (this.deferred === undefined) {         this.deferred = [];     }     if (fn === undefined) {         // apply functions         while ( this.deferred.length > 0 ) {             fn_current = this.deferred.shift();             this.accumulator = fn_current(this.accumulator);         }         return this.accumulator;     }     else {         this.deferred.push ( fn );     }     return this; }

Together with a function delayedAdd that actually returns an object of the following kind ...:

 function delayedAdd ( a1, a2) {     return x ( function () { a1 + a2; } ); }

... you'll effectively register a chain of functions to be executed at some later point of time (e.g. in a callback to some event).

Notes and reminders

  • JS functions are JS objects
  • The signatures of the registered functions may actually be arbitrary. Considering them to be unified just serves to keep this exposition simpler (well ...).

Caveat

I do not know whether the outlined codeis what node.js does (but it could be ... ;-))