js currying function example - javascript

How to understand the currying function?
How the newSum and newFind works?
var currying = function(fn) {
var args = [];
return function() {
if (!!arguments.length) {
[].push.apply(args, arguments); // What's the meaning of this writing?
return arguments.callee;
} else {
return fn.apply(this, args);
}
}
}
// accumulation currying
var sum = (function(num){
var ret = 0;
return function(){
for(var i = 0, len = arguments.length; i < len; i++) {
ret += arguments[i];
}
return ret;
}
})();
var newSum = currying(sum);
newSum(1)(2)(3)(4)() // 10
// element find currying
var find = function(arr, el){
return arr.indexOf(el) !== -1;
}
var newFind = currying(find)([1,2,3]);
newFind(1);
newFind(2);

The currying function, and gets a function as an argument, and returns a new function, that when invoked:
If arguments are provided, they are accumulated in the args array
If arguments are not provided, the original function is called with all accumulated arguments.
So, if we look at this call for example: newSum(1)(2)(3)(4)() - there are 5 function invocations:
Calling newSum with 1. Getting the curried function with 1 accumulated.
Calling the curried function with 2 - getting the same function with 1 and 2 accumulated, and so on for 3 and 4.
Calling the curried function without arguments - applying all the accumulated arguments (1, 2, 3, 4) to the original sum function - and getting the correct value, 10.
About [].push.apply(args, arguments); and fn.apply(this, args);: apply is a method on Function.prototype that basically lets you call a function, supplying a context object and an array of arguments. So basically [].push.apply(...) is a trick of concatenating an array into another array, in our case, concat arguments (which is the list of arguments provided to a function upon invocation) into args (the accumulating list of arguments). fn.apply(this, args); is simply calling the original function with all the accumulated arguments. You can read more about it in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
By the way, newFind(1); and newFind(2); both return a function, that will look for the index of the element only when invoked, meaning newFind(1)() === true

Related

What is fn.bind.apply(fn, arguments) doing?

I saw this shortcut given as an answer on a code Kata but I am having difficulty understanding exactly what the below example is doing.
function func(fn) {
return fn.bind.apply(fn, arguments);
}
So far my understanding is that bind creates a new function similar to doing the following:
function func(fn) {
return function () {
return fn.apply(fn, arguments);
};
}
Is this the case? Any clearer answers or breakdowns of what is going on would be great.
fn.bind
is just
Function.prototype.bind
So we're applying bind to fn, returning
fn.bind(arguments[0]/* doesn't matter, it's fn*/, arguments[1], arguments[2], etc.)
So the bound function is called with arguments being the arguments of func after fn.
Another way to write it would have been:
function func(fn) {
var args = [].slice.call(arguments, 1);
return function () {
var localArgs = [].slice.call(arguments);
return fn.apply(fn, args.concat(localArgs));
};
}
The fact that the context of the call is the initial function (arguments[0]) is most certainly only a side effect. The important thing is we wrap the arguments with the function, but make it possible to dynamically pass other arguments.
Example 1, wrapping all arguments :
function add(a,b){
return a+b
}
var f = func(add, 2 ,3); // f is a function which will always apply add to 2 and 3
console.log(f()) // logs 5
Exemple 2, currying:
function multiply(a,b){
return a*b
}
var multBy2 = func(multiply, 2);
console.log(multBy2(3)) // logs 6

Javascript recursion arguments

I'm having an issue with how my arguments are being passed to a new recursion level. Here's a simplified version of what I'm doing:
var newFunction = function(obj) {
var result = "";
var args = [];
Array.prototype.push.apply(args, arguments);
var thisArg = args.shift()
//do stuff to add onto result with thisArg. This block works, so I'm skipping.
if (args.length !== 0) {
result += newFunction(args);
};
return result;
};
The issue I'm having is related to how 'args' is getting passed into newFunction to cycle back through. When the recursive callback is made, args is passed into the new function scope as a single array argument:
original arguments = ("string", true, 9, "string 2")
new arguments in recursion = ([true, 9, string 2])
It NEEDS to be:
original arguments = ("string", true, 9, "string 2")
new arguments in recursion = (true, 9, "string 2")
I'm pretty sure it's related to how I'm using .apply for the args variable. I'm just not sure how to get around that, since you can't .shift() the 'arguments' object. The way I'm doing it is setting args to be an array; so when it gets passed in, it is passing it as a single array. This is the problem with my code...
Do you see what I'm doing wrong? Thanks in advance.
You can use .apply():
result += newFunction.apply(undefined, args);
The .apply() function is like .call, but it expands the array elements out so that (effectively) the array is copied, element by element, into the arguments object in the newly-called function.
In ECMAScript 5, using apply:
var newFunction = function(thisArg) {
var result = "",
args = [].slice.call(arguments, 1);
// ...
if (args.length) result += newFunction.apply(void 0, args);
return result;
};
In ECMAScript 6, using rest parameters and the spread operator,
var newFunction = function(thisArg, ...args) {
var result = "";
// ...
if (args.length) result += newFunction(...args);
return result;
};

How to access the arguments of a function that is an argument in Javascript

I am having a hard time wrapping my head around this idea. Suppose I have the following
var func1 = function(func2){
return func2
}
var addTwo = function(x) {return x + 2};
var two = func1(addTwo(2))
console.log(two) // returns 4
If I wanted to add code to func1 that refers to the argument(s) in addTwo or any other function that I choose as an argument how would I do this? I want access to the arguments of the functional argument in func1. I hope that makes sense.
You could write it like this.
var func1 = function(val, func2){
return func2(val);
}
var addTwo = function(x) {return x + 2};
var two = func1(2, addTwo);
console.log(two); // returns 4
I think this may be what you want:
function log_and_call(func, args) {
args = [].slice.call(arguments, 1); // Get arguments except first
console.log(args);
return func.apply(this, args);
}
var addTwo = function(x) {return x + 2; };
log_and_call(addTwo, 2); // Logs [2] and returns 4
var multiply = function(x, y) { return x * y; }
log_and_call(multiply, 3, 4); // Logs [3, 4] and returns 12
arguments is a special variable that contains a list of all the arguments passed to the current function. This uses slice to skip over the func argument and just get the rest.
You can't call it as log_and_call(addTwo(2)) because when you write addTwo(2), that calls the function and returns its value, and that value is passed to log_and_call. There's no way for log_and_call to intercede in that call or see the structure of it, it just gets the result.

What happens when you declare .autoCurry() on a function declaration in JavaScript?

I came across this syntax in "Hey Underscore, You're Doing it Wrong" JavaScript talk (4:15). I would like to know what it means.
var add = function(x,y){
return x + y;
}.autoCurry();//What is happening in this line.
First let's looks at what curry and autocurry actually do. I've annotated the source of these two functions (originally found in the wu.js library):
////
// Type:
//
// ((a,b, ... c) -> d) -> a -> b -> ... -> c -> d
//
// Example:
//
// function add(a, b) { return a + b; }
// add2 = curry(add, 2)
// add2(3)
// // 5
function curry(fn /* variadic number of args */) {
var args = Array.prototype.slice.call(arguments, 1);
function f() { return fn.apply(this, args.concat(toArray(arguments))); }
return f;
}
////
// Example:
//
// function add(a, b) { return a + b; }
// autoCurry(add);
//
// add(2)(3)
// // 5
//
// add(2, 3)
// // 5
function autoCurry(fn, numArgs) {
numArgs = numArgs || fn.length;
function f() {
if (arguments.length < numArgs)
{
return numArgs - arguments.length > 0 ?
autoCurry(curry.apply(this, [fn].concat(toArray(arguments))),
numArgs - arguments.length) :
curry.apply(this, [fn].concat(toArray(arguments)));
}
else
{
return fn.apply(this, arguments);
}
}
f.toString = function() { return fn.toString(); };
f.curried = true;
return f;
}
In other words,
autoCurry(add)
Takes a function that takes two arguments and returns a number, and returns a function A that takes a single argument and returns a function B. Where B is a function that takes a single argument and returns a number:
add(1) -> returns a function add1(), which itself takes a single argument.
Next, the speaker in that talk does the following:
Function.prototype.autoCurry = function(n) { return autoCurry(this, n); }
This simply applies the autoCurry method to any given function (self) so that
var add = function(x,y){
return x + y;
}.autoCurry();
Has the same effect as:
var add = function(x,y) { return x + y; };
add = autoCurry(add)
Well, I can't tell you what, exactly autoCurry is doing... ...but what I can tell you is this:
They've modified the Function constructor's prototype Function.prototype.autoCurry = function () { };
Every new function you make on that page will now have access to this method as one of its properties.
var myFunc = function () { return true; }; myFunc.autoCurry();
You can chain statements together, happily in JS.
var myObj = { run : function () { } }, result = myObj.run(); is the same as
var result = { run : function () { } }.run();, as long as you don't care about myObj after.
So:
You are creating a function, and as soon as it's created, you're running a method on it, and the return statement of that method (the last thing in the chain) is being saved to the variable.
Now, currying is a form of taking a function and wrapping it in other functions, which allows you to call it with only a portion of the arguments needed.
function add_two_numbers = function (x, y) { return x + y; }
Currying would allow you to do this:
var save_x_for_later = curry(add_two_numbers),
save_y_and_add = save_x_for_later(3),
result = save_y_and_add(5);
result; // 8
As for your new title, the answer is the following:
You will get an error thrown in your face:
.autoCurry() is not a part of the language.
It was written, by hand, and put on the Function.prototype as Function.prototype.autoCurry = function () { }
I could go into an implementation of currying, but there's a lot of stuff to wrap your head around, if you haven't done much functional programming, or if "lambda" is a head-scratching term.
In JavaScript, a function instantiation expression:
function name( arg1, arg2, ... ) { /* code */ }
creates a function and results in a reference to the function object. Thus, the .autoCurry() is a reference to a property on that object, which is apparently assumed to be a function.
I suspect that the example you're looking at has some other code that adds "autoCurry" to the Function prototype object. That way, every function object has access to that function as the "autoCurry" property.

Trying to understand underscore.js source - call and apply used in library

In Jeremy Ashkenas's awesome Underscore.js library, I tried to understand one thing about the source file. I do not understand this:
var slice = Array.prototype.slice;
args = slice.call(arguments, 2);
So that:
args = Array.prototype.slice.call(arguments, 2);
.call or .apply are the methods of the functions. But here, which functions do .call refer to? The first parameter should be the context, but arguments is context? The second parameter should be the params to pass in the functions. Here they are number 2. What does this mean? Sometimes in the library, it uses 1 or 0. Are they the number of the params to pass in the functions?
_.bind = function bind(func, context) {
var bound, args;
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError;
args = slice.call(arguments, 2);
return bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
};
};
Question 2:
I do not quite understand the logic of this function. Need help to understand. An example should be very helpful.
// Invoke a method (with arguments) on every item in a collection.
_.invoke = function(obj, method) {
var args = slice.call(arguments, 2);
return _.map(obj, function(value) {
return (method.call ? method || value : value[method]).apply(value, args);
});
};
Thank you for help.
The "slice" function on the Array prototype expects that this will refer to the array on which it's supposed to operate. In other words, if you have a real array:
var myArray = [1, 2, 3];
and you call slice():
var sliced = myArray.slice(1);
Then in that call to slice(), this refers to the array "myArray". As Raynos notes in a comment:
myArray.slice(1)
is the same as
myArray.slice.call(myArray, 1);
Thus when you use call() to invoke the function, and pass it arguments as the context object, the slice() code operates on arguments. The other parameters passed via .call() are simply the parameter or parameters for slice() itself. In my example above, note that I passed 1 to the function.
Now as to your second question, that .invoke() function first isolates the arguments passed in after the first two. That means that when you use _.invoke() you pass it two or more arguments: the first is the list to operate on, the second is the method, and the (optional) subsequent arguments are passed to the method for each element of the list.
That call to _.map() is complicated (and in fact I think it's got a little nonsense in it). What it's doing is iterating over the list, calling a function for each value in the list. What that function does to first determine whether the "method" parameter really is a function. If it is, then it calls that function via .apply() with the element of the list as the context. If "method" is not a function, then it assumes it's the name of a property of each list element, and that the properties are functions.
So for example, with a simple list it's pretty simple:
var myList = [1, 2, 3];
var result = _.invoke(myList, function(n) { return this * n; }, 2);
That will give the result [2, 4, 6] because the function I passed multiplies its context object (this) by the parameter passed, and I passed 2 in the call to _.invoke().
With a more complicated list, I can use the second flavor of _.invoke() and call a method on each object in the list:
var getName = function(prefix) { return prefix + " " + this.name; };
var list = [
{ name: "Bob", getName: getName },
{ name: "Sam", getName: getName },
{ name: "Lou", getName: getName }
];
var result = _.invoke(list, "getName", "Congressman");
That will call the "getName" function on each object in the list and return a list made from the results. The effect will be the list ["Congressman Bob", "Congressman Sam", "Congressman Lou"].
Now about that nonsense. In the code for _.invoke():
return _.map(obj, function(value) {
return (method.call ? method || value : value[method]).apply(value, args);
});
That subexpresion method || value will always return the value of "method", or at least almost always barring some exotic trick. If method.call is truthy, then a reference to method must also be truthy. Also, if it were my code, I'd inspect method outside the _.map() callback so that the decision doesn't have to be made over and over again. Maybe something like:
return _.map(obj, method.call ?
function(value) { method.apply(value, args); } :
function(value) { value[method].apply(value, args); }
);

Categories

Resources