Context.
Memoization is a functional technique operating over recursive functions with overlapping invocations aiming to optimize time performance by using an internal cache that remembers previous results with already used parameters. A typical use case is the fibonacci function. Below, it is shown a non memoized and memoized version of that function and an assisting function for timing purposes:
function time (fn) {
return function () {
var before = Date.now();
var result = fn.apply(this, arguments);
var after = Date.now();
return {
value : result,
time : after - before
};
};
}
var fib = function (n) {
if (n < 2) return n;
else return fib(n-1) + fib(n-2);
};
var mfib = function (n) {
var cache = {};
var memoizefib = function (n) {
if (n < 2) return n;
else {
var k1 = JSON.stringify(n-1);
var k2 = JSON.stringify(n-2);
var v1 = k1 in cache ? cache[k1] : (cache[k1] = memoizefib(n-1));
var v2 = k2 in cache ? cache[k2] : (cache[k2] = memoizefib(n-2));
return v1 + v2;
}
};
return memoizefib (n);
};
If now we test our functions we realize that memoization dramatically reduces execution time:
(function test (n) {
var tfib = time(fib);
var tmfib = time(mfib);
console.log(tfib(n)); // -> { value: 433494437, time: 5780 }
console.log(tmfib(n)); // -> { value: 433494437, time: 1 }
})(43);
Problem.
As it frequently happens in functional programming, memoization becomes a useful tool when applied at the higher order to allow defining a memoize function that can transform over a generic function fn. Typical solutions similar to the next one can be found on the Web [1][2][3]:
function memoize (fn) {
var cache = {};
return function () {
var args = [].slice.call (arguments);
var key = JSON.stringify(args);
return key in cache ?
cache[key] :
cache[key] = fn.apply(this, args); (1)
};
}
fn.js - http://eliperelman.com/fn.js
underscore - http://underscorejs.org
Addy Osmani on Memoization - http://addyosmani.com/blog/faster-javascript-memoization
Question.
Nevertheless, surprisingly none of these solutions works!!! After revolving around the code. I think that the problem is in (1) because the recursion it is not applied over the memoized version of fn but over primitive fn and hence memoization is only applied once. Here are my results:
(function test (n) {
var tfib = time(fib);
var tmfib = time(memoize(fib));
console.log (tfib(n)); // -> { value: 433494437, time: 5768 }
console.log (tmfib(n)); // -> { value: 433494437, time: 5723 } :(
})(43);
It seems that in Javascript it is not possible to apply this technique at higher order. Am I right? Does anybody have any solution or alternative code to get a higher order memoization function?
Interesting problem. Why not just memoize the function onto itself?
function factorial(n) { return n ? n * factorial(n-1) : 1; }
// simple memoization with one argument and console reporting
function memoize(fn) {
var cache = {};
return function(x) {
if (x in cache) { console.log('retrieved value from cache for', x); }
return x in cache ? cache[x] : cache[x] = fn.apply(this, arguments);
};
}
// redefine factorial to be its memoized version
factorial = memoize(factorial);
Once you do this, factorial will now be calling its memoized version.
> factorial(6)
720
> factorial(7)
retrieved value from cache for 6
5040
Applying this to your case (no need for mfib):
(function test (n) {
var tfib = time(fib);
console.log(tfib(n));
fib = memoize(fib); // <-- memoize on top of itself
var tmfib = time(fib);
console.log(tmfib(n));
})(30);
Results:
Object {value: 832040, time: 714}
Object {value: 832040, time: 22}
Note that this solution very much applies to "internal memoization" used within a single recursive computation, not just additional external calls to the function as in the factorial case above. By redefining the function with its memoized version, the internal recursive calls are now made to the memoized function. That accounts for the dramatic time improvement from 714 to 22.
If you are looking for "internal" memoization within a single recursive computation, the factorial function (which is given in the currently accepted answer - which BTW I also think is wrong) is a bad candidate and can't be used to showcase it. This is because, there's a single chain of recursion, so once you compute, e.g. the value for 5! you are not going to need it again within the same computation. To showcase what you are asking for, you would indeed need to use an example like the Fibonnaci sequence (which you are yourself using in the question).
The higher-order memoize function you wrote will not work internally within the same computation as it is calling the non-memoized version of it. The currently accepted answer suggests "redefining" the function to be its memoized version. However I think this is wrong. The memoize function closes over the function it was provided with as an argument (functions are values). Changing the variable that used to point to that function value to some other function value (the memoized version) accomplishes nothing.
So, I don't think it is possible to generalize it. That is, I don't believe it is possible to implement a memoize function that externally memoizes a function and makes it work also for a single recursive computation.
Here's what would work for Fibonnaci (like I said, not generalizable):
var fib = (function() {
function fib(n) {
if ((n===1) || (n==2))
return 1;
else
return memoizedFibonacci(n-1)+memoizedFibonacci(n-2);
}
var cache = {};
function memoizedFibonacci(n) {
if (n in cache) { console.log('retrieved value from cache for', n); }
return n in cache ? cache[n] : cache[n] = fib(n);
};
return fib;
})();
console.log(fib(10));
console.log(fib(10));
The above code produces on the output:
retrieved value from cache for 2
retrieved value from cache for 3
retrieved value from cache for 4
retrieved value from cache for 5
retrieved value from cache for 6
retrieved value from cache for 7
retrieved value from cache for 8
55
retrieved value from cache for 9
retrieved value from cache for 8
55
... which is consistent with the expectation for "internal memoization" for the first recursive computation. That the value for 10 is not cached is insignificant for this example and could be trivially fixed but it would add very little (basically you would need to access the cache from the fib function as well).
Related
We're going to make a decorator, caching computed results of deterministic functions (for simplisity let's assume one-argument functions).
In common case is could be done this way:
function makeCacheable(origFunc){
let registry = {};
return function (a){
if (a in registry){
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
}
A problem appears when origFunc is recursive: only top-level calls go through the wrapping cache, but the rest of recursive call stack doesn't meet the cache. No need to explain why this happens. I wonder is there a natural way to make a recursive function cacheable in the same manner?
function fibonacciF(n) {
if (n <= 2) return 1;
let a = 1, b = 1;
for (let i = 2; i < n; ++i){
[a, b] = [b, a+b];
}
return b;
}
function fibonacciR(n) {
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
let fiboF = makeCacheable(fibonacciF); // OK
let fiboR = makeCacheable(fibonacciR); // actually is not what expected
The function calls a function named fibonacciR. If you want to make this call go through the cache, you have to overwrite fibonacciR:
fibonacciR = makeCacheable(fibonacciR);
Is there a natural way to make a recursive function cacheable in the same manner?
No. In general, a function implementation cannot be inspected, and it doesn't make a difference whether it's implemented recursively or with a loop or something else. Using pure functional programming, we can only use the whole function as a building block for the cached version (fiboR), but we cannot alter its behaviour or take only parts of the function unless the implementation is cooperative (e.g. by using some kind of recursion operator that can be user-supplied).
In the above solution, we break these rules by overwriting a variable that is used inside the function, but this is not always possible even in JavaScript.
You could make it work, if you would use the same (function) variable for storing the decorated version of it. To allow for returning back to the original, you could add a property original to the function object:
function makeCacheable(origFunc){
let registry = {};
let f = function (a){
if (a in registry){
console.log(`retrieving value from registry[${a}]`);
return registry[a];
}
let res = origFunc(a);
registry[a] = res;
return res;
}
// Add property for exposing the original function:
f.original = origFunc;
return f;
}
function fibonacciR(n) {
console.log(`Called fibonnacci(${n})`);
return n <= 2 ? 1 : (fibonacciR(n-1) + fibonacciR(n-2));
}
// Demo illustrating the registry is being used:
console.log('Call fibonnacciR(5) with cache turned on:');
var fibonacciR = makeCacheable(fibonacciR);
var f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
// Demo illustrating the function can be restored:
console.log('Call fibonnacciR(5) with cache removed:');
fibonacciR = fibonacciR.original;
f5 = fibonacciR(5);
console.log(`Result: fibonnaciR(5) = ${f5}`);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Reading some legacy code, and found
A.prototype.setSize: function () {
var v1 = new Vector2();
return function (size ) {
var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
this.min.sub( halfSize );
return this;
};
}(),
I am wondering:
why define setSize as a function which return another function
Also the defined function is executed right away.
any light to shed on this?
Updated:
I can simply use
A.prototype.setSize: function (size) {
var v1 = new Vector2();
var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
this.min.sub( halfSize );
return this;
},
Is the first snippet better than second?
So the returned function can access the value of v1 each time it is called without making v1 a global (or otherwise non-private)
That is so the returned function is assigned to setSize
It function closure. Used to hide variables from global scope. Read on and see some examples here
JS function closures
The purpose in that particular case is to avoid creating a new Vector object each time setSize is called. It's a caching strategy. The alternative would be to just have a flat function:
A.prototype.setSize: function (size) {
var v1 = new Vector2();
var halfSize = v1.copy(size).multiplyScalar(0.5);
this.min.sub(halfSize);
return this;
}
I would only use the closure cached version of setSize if I found I was having performance problems because of new Vector2().
A classic example is:
function createAdder(x) {
return function add(y) {
return x + y;
}
}
var addTwo = createAdder(2);
// addTwo is a function that takes one input and adds 2 to it
addTwo(3); // 5
addTwo(9); // 11
The idea is that you want to create a function, but the function you want to create depends on something. In this case, we wanted to create an addX function.
See Chapter 5 of Eloquent Javascript for more. Particularly the Higher Order Functions section.
It also can be more DRY. Consider:
function createSecretAdder() {
var secretNumber = generateSecretNumber(); // THIS TAKES A LONG TIME
return function(n) {
return secretNumber + n;
}
}
var secretAdder = createSecretAdder(); // slow
secretAdder(2); // fast
secretAdder(7); // fast
vs.
function createSecretAdder() {
return function(n) {
var secret = getSecretNumber(); // THIS TAKES A LONG TIME
return secretNumber + n;
}
}
var secretAdder = createSecretAdder(); // fast
secretAdder(2); // slow
secretAdder(7); // slow
The former is DRYer and faster than the latter. This should address your comment and the update to your question.
Note: you'll have to understand closures to understand how this stuff works.
As for why it's immediately invoked, see here.
I'm trying to understand how a function works that is run with two parentheses and two parameters. Like so:
add(10)(10); // returns 20
I know how to write one that takes two params like so:
function add(a, b) {
return a + b;
}
add(10,10); // returns 20
How could I alter that function so it could be run with one set of parameters, or two, and produce the same result?
Any help is appreciated. Literally scratching my head over this.
Thanks in advance!
How could I alter that function so it could be run with one set of parameters, or two, and produce the same result?
You can almost do that, but I'm struggling to think of a good reason to.
Here's how: You detect how many arguments your function has received and, if it's received only one, you return a function instead of a number — and have that function add in the second number if it gets called:
function add(a,b) {
if (arguments.length === 1) {
return function(b2) { // You could call this arg `b` as well if you like,
return a + b2; // it would shadow (hide, supercede) the one above
};
}
return a + b;
}
console.log(add(10, 10)); // 20
console.log(add(10)(10)); // 20
I said "almost" above because just because the add function received only one argument, that doesn't guarantee that the caller is going to call the result. They could write:
var x = add(10);
...and never call the function that x now refers to.
Welcome to the wonderful world of first order functions
In JavaScript, a function can return a function since a function is just another object. A simple implementation is something like:
function add(x){
return function addOther(y){
return x + y;
};
}
This is possible because of closures and first order functions.
This also lets you do partial application, libraries like Ramda utilize this to great extent.
var addThree = add(3)
addThree(5); // 8
To extend what both T. J. Crowder and Benjamin Gruenbaum said, libraries like Ramda (disclosure: I'm one of the authors) allow you to convert a simple function like this:
function add(a, b) {
return a + b;
}
into the style under discussion by wrapping it in a call to a curry function:
var add = R.curry(function add(a, b) {
return a + b;
});
add(3, 5); //=> 8
add(3)(5); //=> 8
var add3 = add(3);
add3(5); //=> 8
The best article I know on this subject is Hugh Jackson's Why Curry Helps. I wrote a more detailed one at Favoring Curry.
Update
Here is a version of curry somewhat simpler than the one in Ramda. It would do the above and quite a bit more, but doesn't do some of the things that Ramda does with placeholder values:
// here is a function that takes a function and returns a curried version
// of it, that is, a version that performs the sort of partial application
// you describe.
var curry = function(fn) {
// first, we detect how many arguments the function has.
var fnArity = fn.length;
var partialApply = function(args) {
// now, let's create a function that's curried
return function () {
// collect the previous args as the partial, and add the new
// ones you just received
var newArgs = (args || []).concat([].slice.call(arguments, 0));
// if we have "enough" arguments, we don't need any more partial
// application and we can call the function.
if (newArgs.length >= fnArity) {
return fn.apply(this, newArgs);
} else { // else we return a partially applied version
return partialApply(newArgs);
}
};
};
return partialApply([]); // a function is itself partially applied with 0 args
};
function add() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
function total() {
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return total;
}
total.toString = function () { return sum };
return total;
}
This will work for any no of arguments and parentheses.
https://medium.com/#imdebasispanda/super-function-with-closure-86a58a9a980b
I'm developing my own functional-programming library, and now referring the underscore.
memoize _.memoize(function, [hashFunction])
Memoizes a given function by caching the computed result. Useful for speeding up slow-running computations. If passed an optional hashFunction, it will be used to compute the hash key for storing the result, based on the arguments to the original function. The default hashFunction just uses the first argument to the memoized function as the key.
var fibonacci = _.memoize(function(n) {
return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});
The above code that enables automatic memorisation without dealing array looks sort of magic, and I saw the source-code below, but still the inner design is not clear to me.
// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
var memoize = function(key) {
var cache = memoize.cache;
var address = hasher ? hasher.apply(this, arguments) : key;
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return cache[key];
};
memoize.cache = {};
return memoize;
};
Can someone give me a brief idea of what is going on?
Appreciated.
memoize has a cache (memoize.cache = {}) that uses for storing the result of the function call. When it's called, it determines an address to store the result by two means: either a call to the hasher function, or the key parameter.
The hasher function works like this (from the underscore page):
If passed an optional hashFunction, it will be used to compute the
hash key for storing the result, based on the arguments to the
original function. The default hashFunction just uses the first
argument to the memoized function as the key.
Then, it calls the function you passed func.apply(...), and stores the result at cache[address].
The second time you call the memoized function, the result will already be in cache (!_.has(..) will return false) and the computation won't be repeated.
I dont' understand why it returns cache[key] and not cache[address] tough...seems to me that cache[address] would be the correct choice.
Update
As pointed out in the comments, the code you present is not the latest implementation of memoize. This is the latest implementation (1.6.0):
_.memoize = function(func, hasher) {
var memo = {};
hasher || (hasher = _.identity);
return function() {
var key = hasher.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
};
};
It works the same way, except from the fact that it is a little more elegant; if an hasher function it's not provided, it uses _.identity as a key, that is a function that simply returns the value passed as an argument:
_.identity = function(value) { return value; }
Aside from this, cache is now called memo but works the same way.
The length property of functions tells how long the 'expected' argument list is:
console.log((function () {}).length); /* 0 */
console.log((function (a) {}).length); /* 1 */
console.log((function (a, b) {}).length); /* 2 etc. */
However, it is a readonly method:
f = function (a) {};
alert(f.length); // 1
f.length = 3;
alert(f.length); // 1
Is there a way to programmatically set that length? The closest I've come so far is to use the Function constructor:
f = new Function("a,b,c", "/* function body here */");
f.length; // 3
However, using Function is essentially the same as eval and we all know how bad that is. What other options do I have here?
It turns out the length property on functions is configurable, which means you can use .defineProperty to change the value of length on a function. Example:
function hi() {}
hi.length === 0; // Expected
Object.defineProperty(hi, "length", { value: 5 })
hi.length === 5; // Intriguing
This works in the latest version of Chrome and Firefox, but it does not work in Safari (v9.1.1).
For now, here's the best solution I could think of.
makeFunc = function (length, fn) {
switch (length) {
case 0 : return function () { return fn.apply(this, arguments); };
case 1 : return function (a) { return fn.apply(this, arguments); };
case 2 : return function (a,b) { return fn.apply(this, arguments); };
case 3 : return function (a,b,c) { return fn.apply(this, arguments); };
case 4 : return function (a,b,c,d) { return fn.apply(this, arguments); };
case 5 : return function (a,b,c,d,e) { return fn.apply(this, arguments); };
case 6 : return function (a,b,c,d,e,f) { return fn.apply(this, arguments); };
case 7 : return function (a,b,c,d,e,f,g) { return fn.apply(this, arguments); };
case 8 : return function (a,b,c,d,e,f,g,h) { return fn.apply(this, arguments); };
case 9 : return function (a,b,c,d,e,f,g,h,i) { return fn.apply(this, arguments); };
default : return function (a,b,c,d,e,f,g,h,i,j) { return fn.apply(this, arguments); };
}
};
Example usage:
var realFn = function () {
return "blah";
};
lengthSix = makeFunc(6, realFn);
lengthSix.length; // 6
lengthSix(); // "blah"
Personally, I always cringe whenever I use copy and paste when programming, so I'd be very happy to hear of any better options.
Update
I thought of a method which could work for any arbitrary size, unlike the example above which is limited by how many times you want to copy-and-paste. Essentially, it dynamically creates a function (using new Function) which will return a function of the right size which then just proxies through to whatever function you pass to it. Yeah that does hurt your head. Anyway, I thought I'd benchmark it against the above...
http://jsperf.com/functions-with-custom-length (you can see the 'evil' code there too).
The evil method is many hundreds of times slower than the hacky copypasta method, so there you go.
I am doing something like what you're asking for using roughly the following:
/* Make a new function with a given size */
function SizedFunc(num_args) {
if(SizedFunc.sizedFuncs === undefined) SizedFunc.sizedFuncs = {};
if(SizedFunc.sizedFuncs[num_args] === undefined) {
var argNames = [];
for(var i = 0; i < num_args; ++i) {
argNames.push('arg' + i);
}
SizedFunc.sizedFuncs[num_args] = new Function(argNames, 'return this.apply(null, arguments);');
}
return SizedFunc.sizedFuncs[num_args];
}
This does use a Function constructor but in a strictly limited way and only ever once per function size to create a function wrapper (which is cached for that size) after that I use wrapper.bind(real_function) to provide the implementation as a function expression/object.
Advantages are that any size is supported and we aren't hard coding the function definitions but actual function implementations are never done in an 'eval' like way and the string passed to the Function constructor is always the same.
/* ---- example ---- */
var a = SizedFunc(4).bind(function() { console.log.apply(null, arguments); });
var b = SizedFunc(4).bind(function(a, b, c, d) { console.log(a + b, c + d); });
console.log(typeof a); // -> function
console.log(typeof b); // -> function
console.log(a.length); // -> 4
console.log(b.length); // -> 4
a(1, 2, 3, 4) // -> 1 2 3 4
a(1, 2, 3, 4, 5); // -> 1 2 3 4 5
b(1, 2, 3, 4) // -> 3 7
I'm sure there are plenty of reasons this is bad, too (starting with the use of bind meaning functions created this way can't be bound to an object) but it is useful in situations where one needs to be able to create a function of arbitrary length dynamically.
According to the ECMA Script standard, revision 5.1 on page 103, the .length parameter on a Function object is not writable so it is set when the function is declared and not changable (if implemented per spec).
Thus, the only way to create a function with a particular .length upon demand is to either have a bunch of functions lying around of various length (as nickf suggests), create a Function object (as you've already mentioned) or use eval() with a dynamically created string. I don't know what problem yu're actually trying to solve, but I personally find nothing wrong with using eval() if you know the source of the code you're using it with and have a way of either checking it or knowing what it will or won't have in it. In this case, programmatically generating a certain number of parameters in a string before calling eval() on it poses no security risk I'm aware of.
If this is all your own code, you can just create a new property on the function .dynLength that is mutable and set it to whatever you want and have your code use that.
There’s an npm module util-arity which does what you want:
const arity = require('util-arity');
arity(3, () => {}).length; //» 3