Eloquent Javascript: Higher Order Functions - javascript

I'm going through Eloquent Javascript: Higher Order Functions example below and already read questions and answers here and here. But I'm still very confused.
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
How can (0) be passed into noisy(f) since noisy() only takes one parameter and that is (Boolean)? I can see the inner function f(arg) is basically Boolean(0), but I don't understand how two parameters can get passed into a function that only allow one parameter. Would "noisy(Boolean)(0)(1)(2)(3);" be a valid function call? If so, how would you differentiate each value after Boolean within the noisy function? Which value will be referenced by "arg"?
The book noted the example function is modifying another function. Which function is being modified? I'm not understanding what the author meant by "modified".

but I don't understand how two parameters can get passed into a
function that only allow one parameter
noisy returns a function, Boolean is passed to noisy, 0 is passed to anonymous function returned from noisy, where f is Boolean, val becomes Boolean(0).
For example
function fn1(arg1) {
return function fn2(arg2) {
console.log(arg1, arg2)
}
}
// Call fn1, inside fn1 fn2 is called with `"b"` as parameter.
fn1("a")("b") // `a b`, `fn2`

This is the concept of currying in JavaScript where you can curry functions to return partially applied functions or pass in other functions
How can (0) be passed into noisy(f) since noisy() only takes one parameter and that is (Boolean)?
The answer to this is the curried function noisy() which expects a function f as parameter and returns another function. The returned function has a closure over noisy and as a result it can identify that Boolean was passed as parameter to noisy even after it was returned. That's why calling noisy(Boolean)(0) basically substitutes f=Boolean, arg=0
Refer this for more on currying: http://javascript.crockford.com/www_svendtofte_com/code/curried_javascript/ and closures: https://developer.mozilla.org/en/docs/Web/JavaScript/Closures

Related

What is the name of a function with four parentheses

For example:
const factory = {
myFunc(str1) {
console.log(str1)
return (comp) => {
return comp;
}
}
}
console.log(factory.myFunc("foo")("bar"));
The myFunc has four parentheses: factory.myFunc("foo")("bar").
How do you call such a function?
Its called function currying.
Actually read it like factory.myFunc("foo") is returning a function (say x) and calling that function immediately with "bar" argument (like x("bar")).
I don't know about the name, but what you are describing is actually two seperate functions. myFunc simply returns another function.
The line factory.myFunc("foo")("bar") first runs the myFunc funtion with foo as a parameter, this returns another function, which is then immediately run with the parameter bar.
It takes 2 parentheses & 1 argument to call myFunc, you need other 2 parentheses & 1 argument to call function it returns.
This sequence of calls is commonly called chaining of function calls. Sometimes, this sequence of actions is also referred to as pipe.
There's also such a term as currying but I'd say it rather describes a technique of declaring functions in a special way that enables you to pass arguments 1 by 1.
In this case, however, I wouldn't say it's currying since myFunc does something that has nothing to do with what returned function does while in currying (as it understood in Lodash for instance) all intermediate function calls serve just for passing arguments while the only function that does some actual job after collecting all arguments is the last one.
I would call myFunc just "method of factory".
It's also a higher order function as #ASDFfgerte correctly points out in comment.

Passing function as parameter on javascript

I recently started to learn javascript and saw this code. It was very different than C++ so please tell me what it means.
function getWeather(lat, lng){
fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${API_KEY}&units=metric`
)
.then(function(response){
return response.json();
})
.then(function(json){
const temp = json.main.temp;
const place = json.name;
weather.innerText = `${temp} # ${place}`;
});
}
so basically it gets api and fetch it. After that it continues with .then(function(response)
I have no idea where that response come from. I can guess that response part is something returned from fetch function but still I don't understand how that happens.
const parsedToDos = JSON.parse(loadedToDos);
//for each takes function and execute function on each items.
parsedToDos.forEach(function(toDo){
paintToDo(toDo.text);
});
similar to the previous example, it takes toDo as parameter and it is not even global or local variable in this code but still used. Can anyone tell me the logic behind this?
Which arguments a function receivedsis determined by the caller of the function. If you have the following function
function add(a, b) {
return a + b;
}
Then "you" can call it as
add(1, 3)
Sometimes it is not directly "you" who calls the function, but another function. E.g.
function add1(a) {
return add(a, 1);
}
here add is called by add1. add1 will always pass 1 as second argument.
In addition to that, sometimes functions accept other functions as arguments and call them at some point. Again an example:
function doSomething(callback) {
return callback(40, 2);
}
Here doSomething accepts a function as argument and will always pass 40 and 2 as arguments. If I pass a function that expects to be passed two numbers it will work as expected:
// Works
doSomething(function (a, b) { return a + b; });
If I don't not, then I get some unexpected behavior or an error:
// Error :(
doSomething(function (a, b) { a.foo.bar = b });
But if that happens then I haven't read the documentation properly, because functions which accept callbacks usually explain which arguments are passed to the callback. For example for forEach (emphasis mine):
forEach() calls a provided callback function once for each element in an array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized (i.e. on sparse arrays, see example below).
callback is invoked with three arguments:
the value of the element
the index of the element
the Array object being traversed
Similar for .then.
In summary, arguments are provided by the caller. If you pass a callback to a function then that function will most likely be caller and pass arguments. Read the documentation or look at the source code to find out which arguments these are.

How does this function modify the other? (Higher Order Functions)

What is this code doing? How is it executing? What is x equal to?
Another useful type of higher-order function modifies the function value it is given:
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));
The function negate() returns a Function object that, when called, will return !func(x); for whatever argument x is passed. This Function object is being stored in the variable isNotNaN with func bound to the built-in function isNaN(). In the next line the function object stored in isNotNaN is being called with the argument NaN (a JavaScript keyword). It is at this point that x becomes bound to NaN. The return value is passed to the function show() (which isn't shown here).
For more info, read up on JavaScript functions here and consult the docs for JavaScript's Function object and function expression.
EDIT: Why do this? Sometimes it's useful to have a function that inverts a given boolean function. For instance, suppose you have some complex predicate and you want to filter an array for all elements for which the predicate is false. You can use negate() to turn the predicate function into a function that evaluates to true for those elements and just use Array.prototype.filter() to do the job. Think of it as a utility function that saves you having to write a lot of function(x) { return !predicate(x); } every time you want the inverse of a boolean-valued function. It's kind of trivial, but a lot of JS libraries (e.g., underscore.js, jquery, etc.) have a boatload of utility functions like this.
P.S. I would have written it more generally:
function negate(func) {
return function() {
return !func.apply(null, arguments);
};
}
That way, it can be used with boolean-valued functions of an arbitrary number of arguments.

Please explain me this higher-order function javascript code

I'm studying higher order functions following the Eloquent JavaScript book.
I haven't been able to understand this code, why is "Boolean" passed as noisy first argument?
This is supposed to be function that changes other function, I just don't get how it works!
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val; };
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
noisy accepts any one-argument function as its argument. It returns a new function that calls that function, but displays messages before and after it calls it.
Boolean is just an example function that they used. It converts its argument to a boolean datatype.
Boolean is a constructor function for the Boolean type. It could be any function.

Passing "extra" arguments to a function stored in a variable - Javascript

I'm new to Javascript, I'm self-teaching, so this might be an obvious area, but no matter how I phrase the question I can't really seem to get my head around this one issue. At the moment I'm reading through http://eloquentjavascript.net/chapter6.html (which was on mozilla's MDN). I've come across this a couple of times now, I would just like a simple break down if possible.
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
show(isNotNaN(NaN));
I don't understand how at the very last step isNotNaN (a variable) is passing an 'extra argument' (NaN) to the function stored in isNotNaN (negate(isNaN). "show(isNotNaN(NaN));"
I came across this same problem when the concept of enclosure was trying to be explained. But I don't get where this argument "NaN" is going in the above function, as it seems to me like the last statement ends up something like:
show(negate(isNaN, NaN));
I would be happy to provide more details. This concept of passing an extra argument to a variable already holding a function with an argument confuses the hell out of me!
There's no "extra" argument. The negate() function itself returns a function defined as a function expression, which can then be called with any number of original (not extra) arguments passed. A closure is used for the returned function to keep a reference to isNaN as func.
var isNotNaN = negate(isNaN);
At this point, isNotNaN contains a reference to the function
function(x) {
return !func(x);
};
Again, func here refers to the isNaN argument passed to the negate function, which is the immediate parent in the scope chain. The result is similar, but not the same as
var isNotNaN = function (x) {
return !isNaN(x);
};
The reason it is not the same is, if we change the value of isNaN, the behaviour of this function will change. In the example you posted, however, the value of func is equal to the original value of isNaN and cannot be changed by anything outside of its scope thanks to the closure.
Essentially, you can pass in any function and get a new function that returns the negated result of the original function in return. For example:
var isNotArray = negate(Array.isArray);
isNotArray(12);
//-> true
In fact, negate(isNaN) simply return a function to the variable isNotNaN. This function take a parameter (named x in your case), then execute the function isNaN on the parameter before negating it and returning the result.
Perhaps this example can clear some things out for you regarding closures:
function foo(x){
function bar(y){
return x+y;
}
return bar;
}
var fooRef = foo(1); // fooRef references foo() with x set to 1
console.log(fooRef(2), foo(1)(2)); // 3, 3
http://jsfiddle.net/ePwy8/

Categories

Resources