What happens when you declare .autoCurry() on a function declaration in JavaScript? - 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.

Related

Confusing function in javascript functional programming

I'm new to functional programming and I'm trying to learn it in javascript. I found some examples and wrote my own snippet, but I don't understand WHY it works. There is a function called whatTheHeckIsThis. Can someone tell me what it is doing or what its purpose is? Note that when running this code, the output is true.
function boolFlipper(someFn){
return function whatTheHeckIsThis(x,y){
return !someFn(x,y);
};
}
var checkStrings = function(x, y){
return x === y;
}
var flipperTester = boolFlipper(checkStrings);
var str1 = "this string";
var str2 = "that string";
console.log(flipperTester(str1, str2));
My confusion is why can't I just do this instead:
function boolFlipper(someFn){
return !someFn(x,y);
}
a reference to whatTheHeckIsthis() will be returned and stored into flipperTester
After this, flipperTester can be used like a function.
You can use this language feature to abstract some code.
Simple example:
function addTen(x) { return x + 10 }
function multiplyByTen(x) { return x * 10 }
...
var doMath
// somewhere a user selected something
if (userInputSaysAdd) doMath = addTen
if (userInputSaysMultiply) doMath = multiplyByTen
// this will be the choosen function
doMath(someValue)
Your second version doesn't work for 2 reasons:
The purpose of boolFlipper is to return a new function, which you can assign to another variable and later call.
Your function doesn't have x and y parameters.
To solve #2 you could write:
function boolFlipper(someFn, x, y) {
return !someFn(x, y);
}
You would then have to call it like:
console.log(boolFlipper(checkStrings, str1, str2));
But you still couldn't do:
flipperTester = boolFlipper(checkStrings);
The original snippet returns a closure, which is bound in the environment where someFn is equal to the function passed as an argument to bookFlipper(). You can then assign this function to a variable, and call it with new arguments, that are assigned to x and y, and then the the function saved in someFn() is called, the return value is negated with !, and this is returned.
For more information about closures, see How do JavaScript closures work?
In JavaScript functions are objects, so you can return them. When you return a function you are getting a function object, so you can call it as any other function. For example:
function myFun() {
return function() {
console.log("test");
};
}
var functionInside = myFun();
/* This is like doing:
var functionInside = function() {
console.log("test");
};
*/
functionInside(); // This will execute the function.
Example with your code:
This variable:
var flipperTester = boolFlipper(checkStrings);
contains a function like this:
var flipperTester = function (x,y) {
return !someFn(x,y);
}
And this is something similar to
function flipperTester(x,y) {
return !someFn(x,y);
}
So when you do:
flipperTester(str1, str2)
You are executing that function. The variable "someFn" inside there is the function "checkStrings", because you passed it when you initialize flipperTester variable.
boolFlipper is, for our purposes here, a function decorator: it takes a function and modifies it to do something else. A more instructive example might be a logging function:
var alsoLogs = f => (...args) => {
var result = f(...args);
console.log(result);
return result;
};
// now we have a function that adds 2 numbers:
var add = function add(a, b) { return a + b; };
// and we want to also log the result
var addAndLog = alsoLogs(add); // addAndLog is a function, would be the whatTheHeckIsThis from your example
addAndLog(2, 3); // logs 5 to the console
If you don't understand all the ES6 syntax that's ok, just understand that alsoLogs take a function f and returns a function that does the exact same thing as f but also logs the result to the console.
Since we as programmers are lazy, we don't want to have to write functions to glue together other functions every time we want to do this, so we write a function to do it for us, compose.
So now we can just say something like:
var addAndLog = R.compose(console.log, add);
addAndLog(2, 3); // logs 5 to the console

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

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.

Overriding a function's toString() in node exports

I am trying to override a toString() method, but getting into difficulties.
Already looked here and here, but still no luck.
My code is as follows:
var Foo = function(arg) {
// some code here...
return function (a, b, c) {
// return function code...
};
};
Foo.prototype.toString = function () {
return "string representation of function";
};
exports.bar(arg) {
return Foo(arg);
};
In another module:
var mod = require('the-module-from-above');
console.log(mod.bar().toString()); // prints return function source code.
My question is, how come my toString() function isn't called, and how can I make it get called?
thank you.
You only set things on a function's prototype if you're using the function as a constructor with new. Since you don't appear to be doing that here, you need to set the toString function on the actual function you return.
function fooToString() {
return "string representation of function";
}
var Foo = function(arg) {
// some code here...
var ret = function (a, b, c) {
// return function code...
};
ret.toString = fooToString;
return ret;
};
You could also add the toString function when you actually create the object in the bar function, if you'd prefer to do that.
exports.bar(arg) {
var foo = Foo(arg);
foo.toString = fooToString;
return foo;
};

Prototypes of objects within objects

I'm trying to make a function that can be applied to a value returned from another function both within a function. Since that's probably a terrible explanation, here's a simplified sample:
function MainFnc() {
this.subFnc=function(a) {
return a*2
}
this.subFnc.subSubFnc=function(a) {
return this*a
}
}
This isn't my actual code - it's for a far better reason than multiplying numbers. This is just a simplified example of what I'm trying to achieve. My question is whether or not it's actually possible to go this deep, and if so how? The method I've portrayed in this sample code evidently does not work.
Thanks for any help.
Edit: Here's an example of it in use since not everyone understands clearly what I want to do with this:
anObject=new MainFnc;
alert(anObject.subFnc(2)); //returns 4
alert(anObject.subFnc(2).subSubFnc(2); //returns 8
This is not exactly what I'm doing, it's just easier to understand using simple multiplication.
This is about as close as you can get:
function foo(n){
this.value = n;
return this;
};
foo.prototype = {
valueOf : function(){
return this.value;
},
multiplyBy : function(n){
return new foo(this.value * n);
}
};
foo.prototype.toString = foo.prototype.valueOf;
var x = new foo(2);
var y = x.multiplyBy(2).multiplyBy(2).multiplyBy(2);
// y == 16
Update based on your comment:
MainFnc is an object which is created in a variable (ie MainVar). So if I wanted to try MainVar.subFnc(2) it'd return 4. If I wanted to try MainVar.subFnc(2).subSubFnc(2), however, it'd return 8.
Right now, you're returning a number from your subFnc, and so the expression MainVar.subFnc(2).subSubFnc(2) breaks down like this:
Look up the property subFnc on MainVar; it returns a function reference.
Call the function with this = MainVar; this returns the number 2.
Look up the property subSubFnc on the number 2; it returns undefined.
Call the function with this = 2; fails because you can't call undefined as a function.
More: You must remember this and Mythical Methods
To do what you're doing, you'd have to have subFnc return an object with function properties. You could do it like this:
function MainFnc(val) {
this.value = val;
this.mult=function(a) {
return new MainFnc(this.value * a);
};
this.div=function(a) {
return new MainFnc(this.value / a);
};
this.get = function() {
return this.value;
};
}
...and then call it like this:
var MainVar = new MainFnc(3);
alert(MainVar.mult(3).mult(4).div(6).get()); // alerts "6" (3 * 3 * 4 / 6 = 6)
Live example
Note the get function to return the underlying number. You might also add a toString:
this.toString = function() {
return String(this.value);
};
But the above isn't taking advantage of prototypical inheritance at all (and it will be important to, if you're creating all of those objects; we need to keep them lightweight); you might consider:
function MainFnc(val) {
this.value = val;
}
MainFnc.prototype.mult = function(a) {
return new MainFnc(this.value * a);
};
MainFnc.prototype.div = function(a) {
return new MainFnc(this.value / a);
};
MainFnc.prototype.get = function() {
return this.value;
};
MainFnc.prototype.toString = function() {
return String(this.value);
};
Original Answer:
With that code, if you did this:
var f = new MainFnc();
alert(f.subFnc(3)); // alerts "6"
alert(f.subFnc.subSubFnc(3)); // NaN
...because this inside subSubFnc when called like that is subFnc, and multipling a function reference tries to convert it to a number, which comes out NaN, and so the result of the multiplication is NaN.
Remember that in JavaScript, this is defined entirely by how a function is called, not where the function is defined. When you call a function via dotted notation (a.b();), the object you're looking up the property on becomes this within the function call, and so with a.b.c();, this within c() is b, not a. More: You must remember this and Mythical Methods

Categories

Resources