I'm studying JavaScript from the book JavaScript: The Good Parts, in the memoization section there is an example about using memoize technique to do Fibonacci problem
We create a general function call memoizer, it takes an memo array and the fundamental function, returns a shell function that manages the memo and calls fundamental function
var memoizer = function(memo, fundamental) {
var shell = function(n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
};
return shell;
};
And then create fibonacci like this:
var fibonacci = memoizer([0, 1], function(shell, n) {
return shell(n-1) + shell(n-2);
});
If I run fibonacci(10), the result will be displayed exactly.
But the thing that makes me confused is the n parameter shell function in memoizer function. I know that it is the value that we want to compute. But where is it come from? How can I call fibonacci(10), for example, can pass the value 10 to n? And what is exactly the var fibonacci? Is it a function or points to a function object as memoizer?
Thanks for any help!
So, to understand this fully, you need to understand things below as fundamental pieces.
Closure How do JavaScript closures work?
Scope What is the scope of variables in JavaScript?
First class object What is meant by 'first class object'?
So, now look at the code.
var memoizer is assigned as a function that returns an another function inside.
var memoizer = function(memo, fundamental) {
var shell = function(n) {
... do some works ...
};
return shell;
};
Can you see it? var shell is returned at the end of the line in memoizer
And whatever the inner logic is in memoizer, the result of it is assigned to var fibonacci
var fibonacci = memoizer([0, 1], function(shell, n) {
return shell(n-1) + shell(n-2);
});
So, it means fibonacci equals the result of memoizer (Since we excuted it), and the result of memoizer equals shell function. If you read those links given to you by me well, you can understand what is going on behind the scenes.
By the way, the code you've given isn't the best way. Because anyway closure makes an activated object alive that isn't necessary.
This code below is an another way of making fibonacci, this isn't the absolute best way, however, I recommend you to compare this code with your code, and figure the differences out.
var result = [];
result[0] = 1;
result[1] = 1;
function fibonacci(n){
var i;
for(i = 2; i < n; i++){
if(!result[i]){
result[i] = result[i-1] + result[i-2];
}
}
return result[i-1];
}
console.log(fibonacci(10));
Related
Example 1.
var fibonacci = function () {
var memo = [0, 1];
var fib = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}();
Example 2.
var memoizer = function (memo, fundamental) {
var shell = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
};
return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
return shell(n - 1) + shell(n - 2);
});
Above are 2 code snippets from Crockford's book to demonstrate the concept of memoization.
Question 1. How do I invoke function fibonacci from any of 2 examples? By usual way fibonacci (5)?
Question 2. As I can see, argument "n" is not defined anywhere when calling var fib = function (n) { or var shell = function (n) {.
In the first example of fibonacci function I'd expect "n" to be defined right after the 2nd line var memo = [0, 1];, and I'd expect "n" to be defined as follows: n = arguments[0];.
However since this doesn't seem to be the case, so I have to ask: how is "n" determined when fibonacci is invoked?
Thanks.
Page from Crockford's books
Question 1: How do I call each one?
The first example, note the }() at the end. This is invoking the function, which in turn gives the fib function back. So fibonacci() in the first example is really fib() with it's own internal references (e.g. memo and fib), memo only being accessible by fib but lasting as a reference as long as a reference to fib exists (the variable holding fibonacci's return).
The second example is similar, except it's substituting a memoizer that accepts an array of items and returns shell, which has access to the array it was passed.
Question 2: What is n as an argument doing?
Since you're really calling a reference to an internally created but externally available fib() and shell() when you call either fibonacci function, you're passing in a new number, which then has it's fibonacci sequence "memoized" by storing it in the internally available memo given at the beginning.
The point is that memoization is like a hash store where computations already known (since they were previously performed and "memoized") are accessible (preventing re-computation), and using Javascript's closure construct allows you to use internally-scoped variables to manage that access.
I'm trying to solve a puzzle, and am at my wit's end trying to figure it out.
I'm supposed to make a function that works like this:
add(1); //returns 1
add(1)(1); //returns 2
add(1)(1)(1); //returns 3
I know it can be done because other people have successfully completed the puzzle. I have tried several different ways to do it. This is my most recent attempt:
function add(n) {
//Return new add(n) on first call
if (!(this instanceof add)) {
return new add(n);
}
//Define calc function
var obj = this;
obj.calc = function(n) {
if (typeof n != "undefined") {
obj.sum += n;
return obj.calc;
}
return obj.sum;
}
//Constructor initializes sum and returns calc(n)
obj.sum = 0;
return obj.calc(n);
}
The idea is that on the first call, a new add(n) is initialized and calc(n) is run. If calc receives a parameter, it adds n to sum and returns itself. When it eventually doesn't receive a parameter, it returns the value of sum.
It makes sense in theory, but I can't get it to work. Any ideas?
--edit--
My code is just the route I chose to go. I'm not opposed to a different approach if anyone can think of one.
To answer "how dow this work". Given:
function add(n) {
function calc(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
var sum = add(1)(2)(3); // 6
When add is called the first time, it stores the value passed in in a variable called n. It then returns the function calc, which has a closure to n and a special valueOf method (explained later).
This function is then called with a value of 2, so it calls add with the sum of n + x, wich is 1 + 2 which 3.
So a new version of calc is returned, this time with a closure to n with a value of 3.
This new calc is called with a value of 3, so it calls add with n + x, which this time is 3 + 3 which is 6
Again add returns a new calc with n set to 6. This last time, calc isn't called again. The returned value is assigned to the variable sum. All of the calc functions have a special valueOf method that replaces the standard one provided by Object.prototype. Normally valueOf would just return the function object, but in this case it will return the value of n.
Now sum can be used in expressions, and if its valueOf method is called it will return 6 (i.e. the value of n held in a closure).
This seems pretty cool, and sum will act a lot like a primitve number, but it's actually a function:
typeof sum == 'function';
So be careful with being strict about testing the type of things:
sum * 2 // 12
sum == 6 // true
sum === 6 // false -- oops!!
Here's a somewhat streamlined version of #RobG's great answer:
function add(n) {
function calc(x) { return n+=x, calc; }
calc.valueOf = function() { return n; };
return calc;
}
The minor difference is that here calc just updates n and then returns itself, rather than returning itself via another call to add, which puts another frame on the stack.
Making self-replication explicit
calc is thus a pure self-replicating function, returning itself. We can encapsulate the notion of "self replication" with the function
function self_replicate(fn) {
return function x() {
fn.apply(this, arguments);
return x;
};
}
Then add could be written in a possibly more self-documenting way as
function add(n) {
function update(x) { n += x; }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Parallel to Array#reduce
Note that there is a certain parallelity between this approach to repeatedly calling a function and Array#reduce. Both are reducing a list of things to a single value. In the case of Array#reduce the list is an array; in our case the list is parameters on repeated calls. Array#reduce defines a standard signature for reducer functions, namely
function(prev, cur)
where prev is the "accumulator" (value so far), cur is the new value being fed in, and the return value becomes the new value the accumulator. It seems useful to rewrite our implementation to make use of a function with that kind of signature:
function add(n) {
function reducer(prev, cur) { return prev + cur; }
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Now we can create a more general way to create self-replication-based reducers based on a reducer function:
function make_repeatedly_callable_function(reducer) {
return function(n) {
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Now we can create add as
var add = make_repeatedly_callable_function(function(prev, cur) { return prev + cur; });
add(1)(2);
Actually, Array#reduce calls the reducer function with third and fourth arguments, namely the index into the array and the array itself. The latter has no meaning here, but it's conceivable we might want something like the third argument to know what "iteration" we're on, which is easy enough to do by just keeping track using a variable i:
function reduce_by_calling_repeatedly(reducer) {
var i = 0;
return function(n) {
function update(x) { n = reducer( n, x, i++); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Alternative approach: keeping track of values
There are certain advantages to keeping track of the intermediate parameters the function is being called with (using an array), and then doing the reduce at the end instead of as we go along. For instance, then we could do Array#reduceRight type things:
function reduce_right_by_calling_repeatedly(reducer, initialValue) {
var array_proto = Array.prototype,
push = array_proto.push,
reduceRight = array_proto.reduceRight;
return function(n) {
var stack=[],
calc = self_replicate(push.bind(stack));
calc.valueOf = reduceRight.bind(stack, reducer, initialValue);
return calc(n);
};
}
Non-primitive objects
Let's try using this approach to build ("extend") objects:
function extend_reducer(prev, cur) {
for (i in cur) {
prev[i] = cur[i];
}
return prev;
}
var extend = reduce_by_calling_repeatedly(extend_reducer);
extend({a: 1})({b: 2})
Unfortunately, this won't work because Object#toValue is invoked only when JS needs a primitive object. So in this case we need to call toValue explicitly:
extend({a: 1})({b: 2}).toValue()
Thanks for the tip on valueOf(). This is what works:
function add(n) {
var calc = function(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
--edit--
Could you please explain how this works? Thanks!
I don't know if I know the correct vocabulary to describe exactly how it works, but I'll attempt to:
Example statement: add(1)(1)
When add(1) is called, a reference to calc is returned.
calc understands what n is because, in the "mind" of the interpreter, calc is a function child of add. When calc looks for n and doesn't find it locally, it searches up the scope chain and finds n.
So when calc(1) is called, it returns add(n + x). Remember, calc knows what n is, and x is simply the current argument (1). The addition is actually done inside of calc, so it returns add(2) at this point, which in turn returns another reference to calc.
Step 2 can repeats every time we have another argument (i.e. (x)).
When there aren't any arguments left, we are left with just a definition of calc. The last calc is never actually called, because you need a () to call a function. At this point, normally the interpreter would return a the function object of calc. But since I overrode calc.valueOf it runs that function instead.
When calc.valueOf runs, it finds the most recent instance of n in the scope chain, which is the cumulative value of all previous n's.
I hope that made some sense. I just saw #RobG 's explanation, which is admittedly much better than mine. Read that one if you're confused.
Here's a variation using bind:
var add = function _add(a, b) {
var boundAdd = _add.bind(null, a + b);
boundAdd.valueOf = function() {
return a + b;
}
return boundAdd;
}.bind(null, 0);
We're taking advantage of a feature of bind that lets us set default arguments on the function we're binding to. From the docs:
bind() also accepts leading default arguments to provide to the target
function when the bound function is called.
So, _add acts as a sort of master function which takes two parameters a and b. It returns a new function boundAdd which is created by binding the original _add function's a parameter to a + b; it also has an overridden valueOf function which returns a + b (the valueOf function was explained quite well in #RobG's answer).
To get the initial add function, we bind _add's a parameter to 0.
Then, when add(1) is called, a = 0 (from our initial bind call) and b = 1 (passed argument). It returns a new function where a = 1 (bound to a + b).
If we then call that function with (2), that will set b = 2 and it'll return a new function where a = 3.
If we then call that function with (3), that will set b = 3 and it'll return a new function where a = 6.
And so on until valueOf is called, at which point it'll return a + b. Which, after add(1)(2)(3), would be 3 + 3.
This is a very simple approach and it meets the criteria the OP was looking for. Namely, the function is passed an integer, keeps track of that integer, and returns itself as a function. If a parameter is not passed - the function returns the sum of the integers passed to it.
let intArray = [];
function add(int){
if(!int){
return intArray.reduce((prev, curr) => prev + curr)
}
intArray.push(int)
return add
}
If you call this like so:
console.log(add(1)(1)());
it outputs 2.
I am currently going through 'Javascript: The good parts' by Douglas Crockford, an there is an example demonstrating the concept of memoization.
var memoizer = function (memo, fundamental) {
var shell = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
};
return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
return shell(n - 1) + shell(n - 2);
});
What I don't understand is, where is the value for n coming from?
In the code var shell = function (n), you're specifying that when you call the function shell, you're going to provide it with an input argument n. So if you called shell(5), n would be equal to 5, or any other number that you passed in.
You need to look at what's being called and returned in each function call -- fibonacci is set to the returned value of the memoizer function, and memoizer returns the shell function which takes in n. So although it's never called in your example code, in the end you'd call, say, fibonacci(5) where 5 is your n. Just follow the function calls and returns.
n is an input. It doesn't "come" from any where in the code you've posted, you have to supply it a value.
I am still fighting my battle against my low IQ :D
This is the usual infamous cycle with closures:
function r(){
var a = [];
var i;
for(i=0;i<10;i++){
a[i]=(function(x){
return function(){return x;}
})(i);
return a;
}
This is quite clear to me now.
In order to understand closures better, I played with the code and came up with:
function r(){
var a = [];
var i;
for(i=0;i<10;i++){
a[i] = (function(){
var x=i;
return function(){return x;}
})();
}
return a;
}
Is my code fully equivalent?
Merc.
Is my code fully equivalent?
Yes.
I find it slightly easier to read the second way, because it saves having to look to the end of the immediately-executed function to find out what's passed in as a parameter (not that that's a big problem with short functions like this), but the first way is more compact and probably more common so...
I guess you didn't try them, the first one doesn't even work! Use firebug to test your code. Here is a version of the first example which actually doesn't give errors:
function r() {
var a = [];
var i;
for (i=0; i<10; i++) {
a[i] = (function (x) {
return function () {
return x;
}
})(i);
}
return a;
}
So, after adding the missing closing brace, they are equivalent, they build an array of functions that return the numbers from 0 to 9, they don't build an array of numbers from 0 to 9. So for example, calling r()[5](); returns 5 (is the sixth element of the array).
I am to write up some code using Javascript. Here is what we are to do:
"Implement a javascript Fibonacci numbers using closures. Specifically, write an function that stores two consecuitive Fibonacci numbers, initially 0 and 1. The function also defines and returns a nested function getNext(). The getNext() function updates the two stored Fibonacci numbers to the next two Fibonacci numbers and returns the current one. E.g. on the first call to getNext() the return value is 0, on the next call it is 1, then 1 again, then 2, etc."
I kind of understand this but not really. Could someone maybe help clarify? Thanks!
The basic idea behind closures is that, since closers bind all local data by value, you can use them to initialize and then modify variables that are only local to that "instance" of the generated function.
Since this seems like homework, I'm going to answer a different question using closures: Use closures to get perfect squares (1, 4, 9, etc.), one at a time.
function makeSquareIteratorFunction() {
var squareRoot = 1;
var getNext = function() {
// Calculate the number you need to return
var square = squareRoot * squareRoot;
// Apply side effects. In this case just incrementing the counter, but with
// Fibonacci you will need to be a little more creative :-)
// You might also prefer to do this first. Depends on your approach.
squareRoot = squareRoot + 1;
// Return the value
return square;
};
// Return the function object, which can then be called later
return getNext;
}
// Usage
var getNextSquare = makeSquareIteratorFunction();
alert(getNextSquare()); // 1
alert(getNextSquare()); // 4
alert(getNextSquare()); // 9
Now, it's worth pointing out that the local variables defined in the outer function (makeSquareIteratorFunction) are localized and bound to the closure. So if you call makeSquareIteratorFunction() multiple times, the later ones will be independent of the first one:
var getNextSquare1 = makeSquareIteratorFunction();
alert(getNextSquare1()); // 1
alert(getNextSquare1()); // 4
var getNextSquare2 = makeSquareIteratorFunction();
alert(getNextSquare2()); // 1 (!) because it's a new closure, initialized the same way
alert(getNextSquare1()); // 9 (!) because it was "on" 4 last time
Hopefully that helps explain it a little? If not, leave a comment. :-)
I just wanted to post a little bit more up to date answer - the fibonacci closure is more readable written using modern JavaScript
function fibonacci() {
let x = 0;
let y = 1;
let z = 0;
return function getNext() {
[z, x, y] = [x, y, x + y];
return z;
};
}
let fun = fibonacci();
for (let i = 0; i < 10; i++) {
console.log(fun());
}
var fibonacci = (function () {
var arr = [0, 1];
return function () {
var num = arr[arr.length - 1],
len = arr.length;
arr.push(arr[len - 1] + arr[len - 2]);
return num;
};
}());
//test
var i;
for (i = 0; i < 10; i++) {
console.log(fibonacci());
}
//1,1,2,3,5,8,13,21,34,55
See the description in http://sarathsaleem.github.com/JavaScriptTasks/
I did this as an answer to this question
Write a function which will return you first two times 1, then 2, then 3, then 5 and so on (Fibonacci numbers). Don’t use any global variables.
fibonacci = ([f0, f1] = [0, 1]) => () => ([f0, f1] = [f1, f0 + f1])[0];
I just wanted to give a more up to date answer written using modern JavaScript.