I know that the purpose of memoize is to cache values so code can be run faster by not having to re-calculate the same answer everytime. My issue stems from returning a function (i think). The google chrome debugger isn't that useful for me here because everytime I try to run this memoize function, it just goes from the argus variable (on line 4 i believe) all the way down to the semi-colon. Furthermore, result always returns an empty object instead of storing a value in result.
I start by defining a function:
function add(a,b){
return a+b;
}
This is my attempt at the memoize function:
_.memoize = function(func) {
var result = {};
var flag = 0;
var argus = Array.prototype.slice.call(arguments)
return function() {
if(result[key] === arguments){
flag = 1
}
else if(flag = 0){
result[argus] = func.apply(this, argus);
}
return result[argus];
};
};
I'd call memoize by doing _.memoize(add(2,5)) but the result doesn't get stored in the result object.
Am I even close to getting this memoize function working properly? Any guidance you guys can give here would be appreciated.
The biggest point you're missing is that _.memoize is called on the function first, and it returns a new function. You are calling it on the result of a function call (which is the number 7 in this case).
In order to get it to work, you need to rearrange a few things.
Also note that it's not wise to try to use an array itself as the index to an object. One approach to get around that would be to convert the arguments array to JSON and use that as the index on the results object:
function add(a, b) {
console.log('Called add(' + a + ', ' + b + ')');
return a + b;
}
var _ = {};
_.memoize = function(func) {
var results = {};
return function() {
var args = Array.prototype.slice.call(arguments);
var key = JSON.stringify(args);
if (!(key in results)) {
results[key] = func.apply(this, args);
}
return results[key];
};
};
var madd = _.memoize(add);
console.log(madd(2, 4));
console.log(madd(9, 7));
console.log(madd(2, 4));
Question: How would you make this work?
add(2)(5); // 7
add(2, 5); // 7
I am trying to solve the question above:
I know that the first solution uses currying and would be implemented as follows:
var add = functoin(x){
return function (y){
return x+y;
};
};
while the second is jsut your normal function:
var add = functoin(x,y){
return x+y;
};
Is there a way to make both work at the same time?
You can use a higher-order function to wrap other functions with that behaviour.
This kind of function is often called curry, and it comes with many libraries (lodash, for example).
curry returns a new function that checks whether all the expected arguments have been supplied. If they have, it calls originalFunction. If not, it returns a partially applied function,
This implementation uses Function#length to test call arity, so it works with any number of arguments.
function curry (fn) {
return function (...args) {
if (args.length >= fn.length) {
return fn.call(this, ...args)
} else {
return curry(fn.bind(this, ...args))
}
}
}
function add (x, y) {
return x + y;
}
// You can curry any function!
const curriedAdd = curry(add);
console.log(curriedAdd(1, 2)); // 3
console.log(curriedAdd(1)(2)); // 3
console.log(curriedAdd(1)); // a function
You could inspect the amount of arguments passed in and return one or the either depending on it:
function add(a, b) {
if (arguments.length == 2) {
return a + b;
}
return function(b) {
return add(a, b);
}
}
console.log(add(2)(5)); // 7
console.log(add(2, 5)); // 7
What's the difference between:
// Example 1 sum(8,2)
console.log(sum(8,2)); // Outputs what??
// Example 2 sum(8)(2)
console.log(sum(8)(2)); // Outputs what??
function sum(x,y) {
return x+y;
}
function sum(x) {
return function(y){
return x+y;
}
}
Why is one used over the other and why?
What you are trying to do is called Function Currying
Try this:
function sum(x) {
return function(y) { return x + y; }
};
var sumWith4 = sum(4);
var finalVal = sumWith4(5);
finalVal = sumWith4(8);
One of the advantages is that it helps in reusing abstract function. For example in the above example I can reuse sumWith4 to add 4 to any number with out calling sum(4,5) explicitly. This was a very simple example. There would be scenarios where in part of the function would be evaluated based on the first param and the other part on the second. So you can create a partial function by providing it with the first param and then reuse the partial function repeatedly for multiple different second params.
I will be assuming that you mean to ask the difference between the invocation of functions which appear like:-
someFunction(x, y)
someFunction(x)(y)
This happens with the use of Closures which happens to be a concept wherein an inner function can carry the environment in which it was created.
var sum = function (x){
return function(y) {
return x+y;
};
};
var addWith5 = sum(5);
/*
This will return a function and not a value
addWith5 = function(y){return 5+y;};
*/
console.log(addWith5(5)); // this will return 11
/*
You can also use add function directly
*/
console.log(sum(5)(6)); // this will return 11
/*
The function returned by sum(5), gets called with the parameter (6)
*/
//Try using this, to make it more clear
function a(x){
return x;
}(5);
// returns 5
EDIT
Removed "closures is a JS concept."
can someone explain to me what is going on in the following code. The function is receiving n as parameter, so where is the m coming from? The whole code is confusing.. if someone can explain?
function greaterThan(n) {
return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// → true
This is exhibiting a functional programming technique called currying. (related also to partial function appliction)
Greater than > usually takes 2 arguments (one on the left and one on the right). This is a way to feed one at a time.
It might be easier to see what is happening if you call it inline:
greaterThan(10)(11);
As you can see from the example above, the 10 gets passed in for the n parameter and then the 11 gets passed in for the m parameter.
The first application that passes the 10 outputs a function that looks like this:
function(m) { return m > 10; };
This is the first application in the partial application.
From there it is easy to see how the 11 is passed in to get the final result.
So, to break it down:
function greaterThan(n) {
return function(m) { return m > n; };
}
//var greaterThan10 = greaterThan(10); -- is equivalent to:
var greaterThan10 = function(m) { return m > 10; };
console.log(greaterThan10(11)); //--> true
m is 11, passed in during the second call.
When you call greaterThan(10), it returns a new function that looks like:
function(m) {
return m > 10;
}
which is then saved as greaterThan10. This is called currying.
greaterThan is a function that returns another function as a result, m is a paraterer of that returned function. So in your code:
var greaterThan10 = function(m) { return m > 10; };
and
console.log(greaterThan10(11)); is the same as console.log(11 > 10);
when you call function greaterThan it returns another function but not a number of float. Inner function knows about n because it inside function greaterThan.
Because wrapper function returns another function you can call second one like this
var result = greaterThan(10)(11);
first argument 10 will be used for wrapper function but result is function so you can pass arguments for inner function immediately.
this is possible only if you have return function(){...}
you can try something like
var a = function (x){
return function(y){
return function(z){
return x*y*z;
}
}
}
var result = a(5)(3)(8);
You have two functions there.
The n comes from when the first function is called.
The m comes from when the second function (which is the return value of the first function) is called.
greaterThan10 = greaterThan(10);
// ^^ n
greaterThan10(11))
// ^^ returned function
// ^^ m
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