SlideShare una empresa de Scribd logo
1 de 29
Descargar para leer sin conexión
Composition, Birds &Composition, Birds &
RecursionRecursion
A scenic hike through the combinatorialA scenic hike through the combinatorial
forest.forest.
CompositionComposition
Function composition is all about functionsFunction composition is all about functions
and so is Javascript. This allows us to moveand so is Javascript. This allows us to move
toward Functional Programming in Javascript.toward Functional Programming in Javascript.
Functions are First Class - meaning, functions can be
treated as values.
Allowing Higher Order Functions, ie functions that take
functions as arguments and return new functions.
The ability to use anonymous functions and closures.
Other functional features like statelessness, side-effect free,
currying/partial application and recursion.
Some Basic FunctionsSome Basic Functions
Let's create some basic
functions that we can reuse.
Each function will:
1. Take a single parameter.
2. Perform a single task with
that parameter, and
3. return a new value
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
Working with FunctionsWorking with Functions
Now, let's use these to
process a list of numbers in
an "imperative" fashion.
 
imperative means telling
the "machine" how to do
something, and as a result
what you want to happen.
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
var list = [1,2,3,4,5],
results = [];
for (var i=0, l=list.length; i < l; i++) {
var n = inc(list[i]);
n = square(n);
n = double(n);
results.push(n);
}
console.log(results);
// => [8, 18, 32, 50, 72]
Working with FunctionsWorking with Functions
Now, let's use these to
process a list of numbers in
an "declarative" fashion.
 
declarative means telling
the "machine" what you
would like to happen, and let
the computer figure out how
to do it.
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
var list = [1,2,3,4,5], results;
results = list.map(inc)
.map(square)
.map(double);
console.log(results);
// => [8, 18, 32, 50, 72]
Worth noting...Worth noting...
By writing programs using a
declarative abstraction
Usually, we end up
writing less code than in
imperative style.
We can reason about our
code at a higher level,
focusing more on "what",
rather than the "how"
We build complexity by
"composing" declarative
functions.
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
var list = [1,2,3,4,5], results;
results = list.map(inc)
.map(square)
.map(double);
console.log(results);
// => [8, 18, 32, 50, 72]
Using composition instead...Using composition instead...
We can use composition
directly to build complexity,
using a higher-order
function.
compose is a curried
function (reduced to series of
functions that each take 1
argument)
Accepts two functions as
arguments and returns a
function.
compose can be composed.
works right -> left
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
var compose = function(f) {
return function(g) {
return function(x) {
return f(g(x));
};
};
};
var list = [1,2,3,4,5], results;
results = list.map(
compose(double)(compose(square)(inc))
);
console.log(results);
// => [8, 18, 32, 50, 72]
We can even compose map()We can even compose map()
Using another higher-order
function, mapWith, we can
now abstract and reuse
operations on lists.
 
We now have a set of
reusable abstractions:
a library of higher-order
functions that let us build up
complexity.
a set of domain specific
functions that focus on one
task and are easy to reason
about and test.
// Define using function expressions
// because functions ARE values!
var double = function(n) { return n * 2; },
square = function(n) { return n * n; },
inc = function(n) { return n + 1; };
var compose = function(f) {
return function(g) {
return function(x) {
return f(g(x));
};
};
};
var mapWith = function(fn) {
return function(list) {
return list.map(fn);
};
};
var list = [1,2,3,4,5],
modNumbers = mapWith(
compose(double)(compose(square)(inc))
);
var results = modNumbers(list);
console.log(results);
// => [8, 18, 32, 50, 72]
Combinators asCombinators as
OrinthologyOrinthology
A combinator is a higher-order function thatA combinator is a higher-order function that
uses only function application and/or otheruses only function application and/or other
combinators to define a result from itscombinators to define a result from its
arguments. Meaning...arguments. Meaning...
A combinator is a function with no free variables, ie, its
output is determined solely by its input.
Is pure, in that it produces no side-effects and doesn't
modify its input.
Is a higher-order function whose input is a function
and result is also a function.
What does this have to do with birds?What does this have to do with birds?
Raymond Smullyan wrote a classic book
entitled "To Mock a Mockingbird" dedicated
to describing these sets of functional
combinators using birds and their
calls/responses as a metaphor.
This was in honor of Haskell Curry, the
creator of Combinatory Logic/Lambda
Calculus who was an avid orinthologist as
well as mathematician and logician.
Let's look at some birds...Let's look at some birds...
Combinatory logic uses a very simple,
direct syntax for writing expressions:
 
In this combinator (a Finch), the calls are
applied from left -> right, just as in
Javascript.  So abc is the same as (ab)c.
 
You could say that combinators take a
string of symbols (like x, y, z, w, and so
forth), then they introduce some erasing,
some duplication, some permutation, and
add some parentheses.
Fabc => cba
The idiot bird (The idiot bird (identityidentity))
This bird, sometimes called identity takes any call you make to it and
it responds back with the same call.
// Ix => x
var idiot(x) { return x; }
The MockingbirdThe Mockingbird
This bird is a duplicative combinator, in that it has two copies of its input
(which is rare).  If you call some fn x to the mockingbird it will respond as if
the function had called to itself.
Sometimes called the U-combinator, passing the idiot to the mockingbird
calls the idiot with itself and returns, the idiot.
MI => II => I  but,
MM => MM => MM => ...  expands forever
// Mx = xx
function mockingbird(x) {
return x(x);
}
The Bluebird (compose)The Bluebird (compose)
Our previous friend compose is the bluebird combinator.  The core
of the bluebirds functionality is that it defers the application of x in
favor of first applying y.
Composing allows us to chain functions together, passing the
output of one as the input of the next.
// Bxyz = (x∘y)z = x(yz)
function bluebird(x) {
return function(y) {
return function(z) {
return x(y(z));
};
};
}
The LarkThe Lark
When you call out some birds x and y to the lark, it will respond by
calling the sound of y out to the mockingbird, then taking the
response and calling it out to the bird x, or what is the same,
applying y to the mockingbird then applying that resulting bird to x.
The lark is a way to compose some function with self application.
// Lxy => x(My) => x(yy)
function lark(x) {
return function(y) {
return x(mockingbird(y));
};
}
// Or,... Lxy = BxMy = x(My) = x(yy)
function lark(x) {
return bluebird(x)(mockingbird);
}
The MeadowLarkThe MeadowLark
When you call out some x and y to the meadowlark, it will respond
by calling out y to the mockingbird of x.
Interestingly the meadowlark behaves much like the mockingbird
duplicating for all time. In fact, this bird differs from mockingbird only
in that it ensures that there is a y.
// Mₑxy = Mxy = xxy
function meadowlark(x) {
return function(y) {
return mockingbird(x)(y);
};
}
The Sage Bird (Y/Z Combinator)The Sage Bird (Y/Z Combinator)
// Sage Bird => Y-Combinator
function sage(f) {
return (function(x) {
return f(x(x));
})(function(x) {
return f(x(x));
});
}
The Sage Bird is more commonly known as the Y-Combinator,
created by Haskell Curry.  If you look closely, you might notice some
of the previous combinator birds we've discussed so far.
 
The Y-Combinator is useful for performing recursion by finding the
fixed-point or convergence of a function (in recursive functions, the
convergence is where the recursion should stop; divergent functions run
forever).
// Lazy Y-Combinator (Z-Combinator)
function sage(f) {
return (function (x) {
return f(function (v) {
return x(x)(v);
});
})(function (x) {
return f(function (v) {
return x(x)(v);
});
}));
}
OR
The Sage Bird, How does it work?The Sage Bird, How does it work?
function factorial(recur) {
return function(n) {
return (n === 1) ? 1 : n * recur(n - 1);
};
};
sage(factorial)(1); // 1
sage(factorial)(12); // 479001600
In Javascript, the Y-Combinator isn't really needed to implement self
recursion, as we can easily define a name for our function and call it
ourself.  Though, direct recursion and self/anonymous recursion still
have the problem of hitting a stack overflow.
 
However, the Y-Combinator is useful to understand and interesting
in its own right.  Let's take a second and break it down using our new
found collection of birds.
function sage(f) {
return (function (x) {
return f(function (v) {
return x(x)(v);
});
})(function (x) {
return f(function (v) {
return x(x)(v);
});
});
}
function sage(f) {
return mockingbird(function (x) {
return f(function (v) {
return x(x)(v);
});
})
}
The Sage bird is composed of
various other birds. Let's work
from the outside-in.
 
At a high level, the Sage bird is
returning the invocation of a
function applied to itself. This
is the call of the Mockingbird,
so we can simplify.
// Mx = xx
function mockingbird(x) {
return x(x);
}
function sage(f) {
return mockingbird(function (x) {
return f(function (v) {
return x(x)(v);
});
})
}
Looking at the function
passed to Mockingbird, we
can see yet another
Mockingbird call x(x).
 
The larger function being
passed to our first
Mockingbird also looks
strikingly like the
MeadowLark, except the
function returned is
composed with f.
// Mₑxy = Mxy = xxy
function meadowlark(x) {
return function(y) {
return mockingbird(x)(y);
};
}
function sage(f) {
return mockingbird(function (x) {
return f(function (v) {
return mockingbird(x)(v);
});
})
}
function sage(f) {
return mockingbird(f(function (x) {
return function (v) {
return mockingbird(x)(v);
});
})
}
If we pull the composition with
f out of this function, it
becomes the Meadowlark, and
we can compose it with our
Bluebird.
 
 
// Mₑxy = Mxy = xxy
function meadowlark(x) {
return function(y) {
return mockingbird(x)(y);
};
}
function sage(f) {
return mockingbird(function (x) {
return f(function (v) {
return mockingbird(x)(v);
});
})
}
function sage(f) {
return mockingbird(bluebird(f)(meadowlark));
}
// Bxyz = (x∘y)z = x(yz)
function bluebird(x) {
return function(y) {
return function(z) {
return x(y(z));
};
};
}
function sage(f) {
return mockingbird(bluebird(f)(meadowlark));
}
// Lazy Y-Combinator (Z-Combinator)
function sage(f) {
return (function (x) {
return f(function (v) {
return x(x)(v);
});
})(function (x) {
return f(function (v) {
return x(x)(v);
});
}));
}
Understanding the Y-
combinator shows us:
1. The expressive power of
functional programming to
solve a unique problem
2. The problem: implementing
recursion when explicit
recursion isn't allowed
3. The power of combinators
and composition
// Test it out
function factorial(recur) {
return function(n) {
return n == 1 ? 1 : n * recur(n-1);
};
};
var fact = sage(factorial);
console.log(fact(10));
// => 3628800
console.log(fact(1000));
// => Infinity
console.log(fact(32768));
// => Uncaught RangeError: Maximum call stack size exceeded
The problem with recursion:The problem with recursion: Ye ole StackYe ole Stack
The problem with recursion in Javascript is that you
eventually run out of stack space because of the number
of function calls.
 
How do we solve this?
// Simple, recursive factorial function
function factorial(n) {
return n == 1 ? 1 : n * factorial(n-1);
}
The problem with recursion:The problem with recursion: Ye ole StackYe ole Stack
// Tail-call optimized factorial
function factorial(n, acc) {
acc = acc || 1;
return n ? factorial(n - 1, acc * n) : acc;
}
One way to solve this is to do tail-call optimization (done
at compile time), which means the function should return
either a value or a call to the function (without evaluating
its results)
Except, Javascript doesn't optimize for tail recursive calls
(Babel will, however).
Oh, well. I guess we'll just write loops...Oh, well. I guess we'll just write loops...
Trampolines to the rescue!
A trampoline is a mechanism for looping over thunk-
returning functions, and invoking them; simulating tail-
call elimination.
 
A thunk is just an un-evaluated expression,
so a "thunk-returning" function is one that returns aso a "thunk-returning" function is one that returns a
function that, when invoked, will perform the nextfunction that, when invoked, will perform the next
computationcomputation
Bouncy, bouncy, bouncy...Bouncy, bouncy, bouncy...
function factorial(n, acc) {
acc = acc || 1;
return n ?
function() { return factorial(n - 1, acc * n); } :
acc;
}
// trampoline decorator
function trampoline(fn){
return function(/*args*/){
var res = fn.apply(this, arguments);
while(res instanceof Function){
res = res();
}
return res;
}
}
trampoline(factorial)(32768)
// => Infinity
thunk
No need for
call stacks!
factorial returns a thunk if
there is another call to be
made; otherwise, it
returns a final value.
How does Babel do it?How does Babel do it?
// Tail-call optimized factorial
function factorial(n, acc) {
acc = acc || 1;
return n ?
factorial(n - 1, acc * n) :
acc;
}
Babel only supports tail-call
optimization on explicit function
calls.
It essentially turns the function
into iterative calls, eliminating
successive stack frames.
// Tail-call optimized factorial
"use strict";
function factorial(_x, _x2) {
var _again = true;
_function: while (_again) {
var n = _x,
acc = _x2;
_again = false;
acc = acc || 1;
if (n) {
_x = n - 1;
_x2 = acc * n;
_again = true;
continue _function;
} else {
return acc;
}
}
}

Más contenido relacionado

La actualidad más candente

Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3Philip Schwarz
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...Philip Schwarz
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Philip Schwarz
 
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...Function Applicative for Great Good of Palindrome Checker Function - Polyglot...
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...Philip Schwarz
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Philip Schwarz
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional ProgrammingHugo Firth
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4Philip Schwarz
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей КоваленкоFwdays
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5Philip Schwarz
 
Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Hermann Hueck
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!Hermann Hueck
 
From Function1#apply to Kleisli
From Function1#apply to KleisliFrom Function1#apply to Kleisli
From Function1#apply to KleisliHermann Hueck
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APIMario Fusco
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Philip Schwarz
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioLuis Atencio
 
Humble introduction to category theory in haskell
Humble introduction to category theory in haskellHumble introduction to category theory in haskell
Humble introduction to category theory in haskellJongsoo Lee
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshuSidd Singh
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With ScalaKnoldus Inc.
 

La actualidad más candente (20)

Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
Game of Life - Polyglot FP - Haskell - Scala - Unison - Part 3
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
 
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...Function Applicative for Great Good of Palindrome Checker Function - Polyglot...
Function Applicative for Great Good of Palindrome Checker Function - Polyglot...
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional Programming
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 4
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
 
Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!
 
From Function1#apply to Kleisli
From Function1#apply to KleisliFrom Function1#apply to Kleisli
From Function1#apply to Kleisli
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
 
Functional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis AtencioFunctional Programming in JavaScript by Luis Atencio
Functional Programming in JavaScript by Luis Atencio
 
State Monad
State MonadState Monad
State Monad
 
Humble introduction to category theory in haskell
Humble introduction to category theory in haskellHumble introduction to category theory in haskell
Humble introduction to category theory in haskell
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshu
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 

Similar a Composition birds-and-recursion

TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsEelco Visser
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойSigma Software
 
Functional Programming in JavaScript
Functional Programming in JavaScriptFunctional Programming in JavaScript
Functional Programming in JavaScriptWill Livengood
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Calvin Cheng
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
 
List-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic LanguagesList-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic LanguagesWim Vanderbauwhede
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScriptLuis Atencio
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 
Functions in advanced programming
Functions in advanced programmingFunctions in advanced programming
Functions in advanced programmingVisnuDharsini
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Function composition in Javascript
Function composition in JavascriptFunction composition in Javascript
Function composition in JavascriptAnand Kumar
 
Real World Haskell: Lecture 6
Real World Haskell: Lecture 6Real World Haskell: Lecture 6
Real World Haskell: Lecture 6Bryan O'Sullivan
 
React, Redux, ES2015 by Max Petruck
React, Redux, ES2015   by Max PetruckReact, Redux, ES2015   by Max Petruck
React, Redux, ES2015 by Max PetruckMaksym Petruk
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2Hang Zhao
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScriptChengHui Weng
 
React, Redux, ES2015 by Max Petruck
React, Redux, ES2015 by Max PetruckReact, Redux, ES2015 by Max Petruck
React, Redux, ES2015 by Max PetruckLingvokot
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISPDevnology
 

Similar a Composition birds-and-recursion (20)

TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
 
Functional Programming in JavaScript
Functional Programming in JavaScriptFunctional Programming in JavaScript
Functional Programming in JavaScript
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 
List-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic LanguagesList-based Monadic Computations for Dynamic Languages
List-based Monadic Computations for Dynamic Languages
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
 
Functional programming java
Functional programming javaFunctional programming java
Functional programming java
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Functions in advanced programming
Functions in advanced programmingFunctions in advanced programming
Functions in advanced programming
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Function composition in Javascript
Function composition in JavascriptFunction composition in Javascript
Function composition in Javascript
 
Real World Haskell: Lecture 6
Real World Haskell: Lecture 6Real World Haskell: Lecture 6
Real World Haskell: Lecture 6
 
React, Redux, ES2015 by Max Petruck
React, Redux, ES2015   by Max PetruckReact, Redux, ES2015   by Max Petruck
React, Redux, ES2015 by Max Petruck
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScript
 
React, Redux, ES2015 by Max Petruck
React, Redux, ES2015 by Max PetruckReact, Redux, ES2015 by Max Petruck
React, Redux, ES2015 by Max Petruck
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
 

Último

Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 

Último (20)

Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 

Composition birds-and-recursion

  • 1. Composition, Birds &Composition, Birds & RecursionRecursion A scenic hike through the combinatorialA scenic hike through the combinatorial forest.forest.
  • 3. Function composition is all about functionsFunction composition is all about functions and so is Javascript. This allows us to moveand so is Javascript. This allows us to move toward Functional Programming in Javascript.toward Functional Programming in Javascript. Functions are First Class - meaning, functions can be treated as values. Allowing Higher Order Functions, ie functions that take functions as arguments and return new functions. The ability to use anonymous functions and closures. Other functional features like statelessness, side-effect free, currying/partial application and recursion.
  • 4. Some Basic FunctionsSome Basic Functions Let's create some basic functions that we can reuse. Each function will: 1. Take a single parameter. 2. Perform a single task with that parameter, and 3. return a new value // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; };
  • 5. Working with FunctionsWorking with Functions Now, let's use these to process a list of numbers in an "imperative" fashion.   imperative means telling the "machine" how to do something, and as a result what you want to happen. // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; }; var list = [1,2,3,4,5], results = []; for (var i=0, l=list.length; i < l; i++) { var n = inc(list[i]); n = square(n); n = double(n); results.push(n); } console.log(results); // => [8, 18, 32, 50, 72]
  • 6. Working with FunctionsWorking with Functions Now, let's use these to process a list of numbers in an "declarative" fashion.   declarative means telling the "machine" what you would like to happen, and let the computer figure out how to do it. // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; }; var list = [1,2,3,4,5], results; results = list.map(inc) .map(square) .map(double); console.log(results); // => [8, 18, 32, 50, 72]
  • 7. Worth noting...Worth noting... By writing programs using a declarative abstraction Usually, we end up writing less code than in imperative style. We can reason about our code at a higher level, focusing more on "what", rather than the "how" We build complexity by "composing" declarative functions. // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; }; var list = [1,2,3,4,5], results; results = list.map(inc) .map(square) .map(double); console.log(results); // => [8, 18, 32, 50, 72]
  • 8. Using composition instead...Using composition instead... We can use composition directly to build complexity, using a higher-order function. compose is a curried function (reduced to series of functions that each take 1 argument) Accepts two functions as arguments and returns a function. compose can be composed. works right -> left // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; }; var compose = function(f) { return function(g) { return function(x) { return f(g(x)); }; }; }; var list = [1,2,3,4,5], results; results = list.map( compose(double)(compose(square)(inc)) ); console.log(results); // => [8, 18, 32, 50, 72]
  • 9. We can even compose map()We can even compose map() Using another higher-order function, mapWith, we can now abstract and reuse operations on lists.   We now have a set of reusable abstractions: a library of higher-order functions that let us build up complexity. a set of domain specific functions that focus on one task and are easy to reason about and test. // Define using function expressions // because functions ARE values! var double = function(n) { return n * 2; }, square = function(n) { return n * n; }, inc = function(n) { return n + 1; }; var compose = function(f) { return function(g) { return function(x) { return f(g(x)); }; }; }; var mapWith = function(fn) { return function(list) { return list.map(fn); }; }; var list = [1,2,3,4,5], modNumbers = mapWith( compose(double)(compose(square)(inc)) ); var results = modNumbers(list); console.log(results); // => [8, 18, 32, 50, 72]
  • 11. A combinator is a higher-order function thatA combinator is a higher-order function that uses only function application and/or otheruses only function application and/or other combinators to define a result from itscombinators to define a result from its arguments. Meaning...arguments. Meaning... A combinator is a function with no free variables, ie, its output is determined solely by its input. Is pure, in that it produces no side-effects and doesn't modify its input. Is a higher-order function whose input is a function and result is also a function.
  • 12. What does this have to do with birds?What does this have to do with birds? Raymond Smullyan wrote a classic book entitled "To Mock a Mockingbird" dedicated to describing these sets of functional combinators using birds and their calls/responses as a metaphor. This was in honor of Haskell Curry, the creator of Combinatory Logic/Lambda Calculus who was an avid orinthologist as well as mathematician and logician.
  • 13. Let's look at some birds...Let's look at some birds... Combinatory logic uses a very simple, direct syntax for writing expressions:   In this combinator (a Finch), the calls are applied from left -> right, just as in Javascript.  So abc is the same as (ab)c.   You could say that combinators take a string of symbols (like x, y, z, w, and so forth), then they introduce some erasing, some duplication, some permutation, and add some parentheses. Fabc => cba
  • 14. The idiot bird (The idiot bird (identityidentity)) This bird, sometimes called identity takes any call you make to it and it responds back with the same call. // Ix => x var idiot(x) { return x; }
  • 15. The MockingbirdThe Mockingbird This bird is a duplicative combinator, in that it has two copies of its input (which is rare).  If you call some fn x to the mockingbird it will respond as if the function had called to itself. Sometimes called the U-combinator, passing the idiot to the mockingbird calls the idiot with itself and returns, the idiot. MI => II => I  but, MM => MM => MM => ...  expands forever // Mx = xx function mockingbird(x) { return x(x); }
  • 16. The Bluebird (compose)The Bluebird (compose) Our previous friend compose is the bluebird combinator.  The core of the bluebirds functionality is that it defers the application of x in favor of first applying y. Composing allows us to chain functions together, passing the output of one as the input of the next. // Bxyz = (x∘y)z = x(yz) function bluebird(x) { return function(y) { return function(z) { return x(y(z)); }; }; }
  • 17. The LarkThe Lark When you call out some birds x and y to the lark, it will respond by calling the sound of y out to the mockingbird, then taking the response and calling it out to the bird x, or what is the same, applying y to the mockingbird then applying that resulting bird to x. The lark is a way to compose some function with self application. // Lxy => x(My) => x(yy) function lark(x) { return function(y) { return x(mockingbird(y)); }; } // Or,... Lxy = BxMy = x(My) = x(yy) function lark(x) { return bluebird(x)(mockingbird); }
  • 18. The MeadowLarkThe MeadowLark When you call out some x and y to the meadowlark, it will respond by calling out y to the mockingbird of x. Interestingly the meadowlark behaves much like the mockingbird duplicating for all time. In fact, this bird differs from mockingbird only in that it ensures that there is a y. // Mₑxy = Mxy = xxy function meadowlark(x) { return function(y) { return mockingbird(x)(y); }; }
  • 19. The Sage Bird (Y/Z Combinator)The Sage Bird (Y/Z Combinator) // Sage Bird => Y-Combinator function sage(f) { return (function(x) { return f(x(x)); })(function(x) { return f(x(x)); }); } The Sage Bird is more commonly known as the Y-Combinator, created by Haskell Curry.  If you look closely, you might notice some of the previous combinator birds we've discussed so far.   The Y-Combinator is useful for performing recursion by finding the fixed-point or convergence of a function (in recursive functions, the convergence is where the recursion should stop; divergent functions run forever). // Lazy Y-Combinator (Z-Combinator) function sage(f) { return (function (x) { return f(function (v) { return x(x)(v); }); })(function (x) { return f(function (v) { return x(x)(v); }); })); } OR
  • 20. The Sage Bird, How does it work?The Sage Bird, How does it work? function factorial(recur) { return function(n) { return (n === 1) ? 1 : n * recur(n - 1); }; }; sage(factorial)(1); // 1 sage(factorial)(12); // 479001600 In Javascript, the Y-Combinator isn't really needed to implement self recursion, as we can easily define a name for our function and call it ourself.  Though, direct recursion and self/anonymous recursion still have the problem of hitting a stack overflow.   However, the Y-Combinator is useful to understand and interesting in its own right.  Let's take a second and break it down using our new found collection of birds.
  • 21. function sage(f) { return (function (x) { return f(function (v) { return x(x)(v); }); })(function (x) { return f(function (v) { return x(x)(v); }); }); } function sage(f) { return mockingbird(function (x) { return f(function (v) { return x(x)(v); }); }) } The Sage bird is composed of various other birds. Let's work from the outside-in.   At a high level, the Sage bird is returning the invocation of a function applied to itself. This is the call of the Mockingbird, so we can simplify. // Mx = xx function mockingbird(x) { return x(x); }
  • 22. function sage(f) { return mockingbird(function (x) { return f(function (v) { return x(x)(v); }); }) } Looking at the function passed to Mockingbird, we can see yet another Mockingbird call x(x).   The larger function being passed to our first Mockingbird also looks strikingly like the MeadowLark, except the function returned is composed with f. // Mₑxy = Mxy = xxy function meadowlark(x) { return function(y) { return mockingbird(x)(y); }; } function sage(f) { return mockingbird(function (x) { return f(function (v) { return mockingbird(x)(v); }); }) }
  • 23. function sage(f) { return mockingbird(f(function (x) { return function (v) { return mockingbird(x)(v); }); }) } If we pull the composition with f out of this function, it becomes the Meadowlark, and we can compose it with our Bluebird.     // Mₑxy = Mxy = xxy function meadowlark(x) { return function(y) { return mockingbird(x)(y); }; } function sage(f) { return mockingbird(function (x) { return f(function (v) { return mockingbird(x)(v); }); }) } function sage(f) { return mockingbird(bluebird(f)(meadowlark)); } // Bxyz = (x∘y)z = x(yz) function bluebird(x) { return function(y) { return function(z) { return x(y(z)); }; }; }
  • 24. function sage(f) { return mockingbird(bluebird(f)(meadowlark)); } // Lazy Y-Combinator (Z-Combinator) function sage(f) { return (function (x) { return f(function (v) { return x(x)(v); }); })(function (x) { return f(function (v) { return x(x)(v); }); })); } Understanding the Y- combinator shows us: 1. The expressive power of functional programming to solve a unique problem 2. The problem: implementing recursion when explicit recursion isn't allowed 3. The power of combinators and composition
  • 25. // Test it out function factorial(recur) { return function(n) { return n == 1 ? 1 : n * recur(n-1); }; }; var fact = sage(factorial); console.log(fact(10)); // => 3628800 console.log(fact(1000)); // => Infinity console.log(fact(32768)); // => Uncaught RangeError: Maximum call stack size exceeded The problem with recursion:The problem with recursion: Ye ole StackYe ole Stack The problem with recursion in Javascript is that you eventually run out of stack space because of the number of function calls.   How do we solve this?
  • 26. // Simple, recursive factorial function function factorial(n) { return n == 1 ? 1 : n * factorial(n-1); } The problem with recursion:The problem with recursion: Ye ole StackYe ole Stack // Tail-call optimized factorial function factorial(n, acc) { acc = acc || 1; return n ? factorial(n - 1, acc * n) : acc; } One way to solve this is to do tail-call optimization (done at compile time), which means the function should return either a value or a call to the function (without evaluating its results) Except, Javascript doesn't optimize for tail recursive calls (Babel will, however).
  • 27. Oh, well. I guess we'll just write loops...Oh, well. I guess we'll just write loops... Trampolines to the rescue! A trampoline is a mechanism for looping over thunk- returning functions, and invoking them; simulating tail- call elimination.   A thunk is just an un-evaluated expression, so a "thunk-returning" function is one that returns aso a "thunk-returning" function is one that returns a function that, when invoked, will perform the nextfunction that, when invoked, will perform the next computationcomputation
  • 28. Bouncy, bouncy, bouncy...Bouncy, bouncy, bouncy... function factorial(n, acc) { acc = acc || 1; return n ? function() { return factorial(n - 1, acc * n); } : acc; } // trampoline decorator function trampoline(fn){ return function(/*args*/){ var res = fn.apply(this, arguments); while(res instanceof Function){ res = res(); } return res; } } trampoline(factorial)(32768) // => Infinity thunk No need for call stacks! factorial returns a thunk if there is another call to be made; otherwise, it returns a final value.
  • 29. How does Babel do it?How does Babel do it? // Tail-call optimized factorial function factorial(n, acc) { acc = acc || 1; return n ? factorial(n - 1, acc * n) : acc; } Babel only supports tail-call optimization on explicit function calls. It essentially turns the function into iterative calls, eliminating successive stack frames. // Tail-call optimized factorial "use strict"; function factorial(_x, _x2) { var _again = true; _function: while (_again) { var n = _x, acc = _x2; _again = false; acc = acc || 1; if (n) { _x = n - 1; _x2 = acc * n; _again = true; continue _function; } else { return acc; } } }