I got this code from the Headfirst Javascript book. I changed the function names to be clearer. I'm trying to wrap my head around this.
I assigned add to the function outer with a number. That number remains for some reason - returns a reference to inner with n = num (which returns the added values?
Anytime I change outers n value, the inner will use that new value?
I believe I'm right on that. Is there anywhere I can read more about it? See better examples? Or can anyone explain this better?
function outer(n) {
var inner = function(x) { //or x = 0
return n + (x || 0); //added default 0 for testing to prevent NaN
}
return inner;
}
var num = 2;
var add = outer(num);
console.log(`Adding 2 to num(${num}): ${add(2)}`);
add = outer(5);
console.log(add());
console.log(add(2));
In JavaScript, functions can act as regular data. If you are OK with the idea of passing a number or string around, then passing a function around is no different. This allows you the ability to do some very cool and powerful things.
Here, instead of the add function simply giving you your numeric answer, it's giving you back a function with your number embedded into it. This means that add doesn't really add anything, add is a function for creating functions (similar to the idea of a "Factory" in class based programming).
Changing the names may make things easier:
function createAddFunction(numberThatWillBeHardWiredIntoReturnedFunction) {
var resultingFunction= function(x) { //or x = 0
return numberThatWillBeHardWiredIntoReturnedFunction + (x || 0);
}
return resultingFunction;
}
var num = 2;
// This will cause add to be a function that is hard-wired to add 2 to another number
var add = createAddFunction(num);
console.log(`Adding 2 to num(${num}): ${add(2)}`);
// This will cause add to be a function that is hard-wired to add 5 to another number
add = createAddFunction(5);
console.log(add());
console.log(add(2));
Let's rename the functions to make it even clearer. The outer function takes a parameter and uses it to create a new function. This new function is returned for future use.
function createFunctionThatAdds(n){
var adds_n = function(x) { return n + (x || 0); };
return adds_n;
}
var adds_2 = createFunctionThatAdds(2);
var adds_5 = createFunctionThatAdds(5);
console.log(adds_2(10));
console.log(adds_5(10));
The technique used is called currying. It's part of functional javascript.
You can read more about it here.
The idea behind it is that you can use a function to generate another function, which you can use further in your code.
Currying is made possible, because of a closure.
There are a lot of libraries that are built based on that principe, for example Ramda.
Related
I have a function that returns a variable, I'd just like to know what's the correct syntax for doing something (such as doing math or writing a new variable using that returned variable.
Example Function:
function exampleFunction(number) {
var data_filter = number + number;
return data_filter;
}
The function returns data_filter, and I'd like to know what's the correct syntax for doing something with it, such as inputting it in another function.
What you have here is fine.
As one of the comment suggests typically you assign the result to a variable. Take a simple example here:
let myNumber = 10;
let myHalvedNumber = halveNumber(myNumber);
console.log(myNumber)
console.log(myHalvedNumber);
function halveNumber(numberToHalve){
return numberToHalve/2;
}
The best way to think about it in practice is to treat the function/input combination { f(x) } as a proxy for the result itself. This means that both of these examples are correct and how you choose to employ it is your own preference.
//These two approaches are identical and both valid:
//1) Assign to a variable for further use - typically better for variable re-use:
let myHalvedNumber = halveNumber(10);
aSecondFunction(myHalvedNumber);
//2) Use the result directly in a second call - typically shorter and arguably easier to maintain/read
aSecondFunction(halveNumber(10));
function halveNumber(myNumber){
return myNumber/2;
}
function aSecondFunction (myNumber){
console.log("the number is: " + myNumber)
}
In JavaScript, one can write:
var variableWithALongName = 4;
var amount = 5;
((a) => {
amount += a * (a + 1);
})(variableWithALongName);
console.log(amount); // 25
The function involved here is an anonymous function, used only in this part of the code, which does not return any value, it just modifies something (it just does some stuff). Instead of that simple function, there could be a more complicated function which takes some complicated arguments and uses them many times.
Is there anything like that in C#?
I am aware of an over 10 years old similar question and I see one of its answers seems to be more useful and more about actual anonymous functions than the official documentation. However, I am interested in functions that don't return any value. The closest to the above JS code I can currently think of is this (e.g. using Unity's Debug.Log):
int variableWithALongName = 4;
int amount = 5;
new Func<int, bool>((a) => {
amount += a * (a + 1);
return true;
})(variableWithALongName);
Debug.Log(amount); // 25
However, that function still returns something and, although it is just an (arbitrary) bool value that is never used, I wonder if even that can be avoided, to make that C# code more similar to the JS one.
Also, just to be clear, by anonymous function I think of a function that doesn't take up any name, i.e. that doesn't need something like someName = ... followed by someName(parameters) somewhere else in code. I'm pointing this out because I have noticed that some of these are also being called anonymous functions for reasons unknown to me.
Here is C# equivalent of provided js code
var variableWithALongName = 4;
var amount = 5;
(new Action<int>(a=> amount += a * (a + 1))).Invoke(variableWithALongName);
Console.WriteLine(amount);
I have the following adding function, which appeared originally here.
add takes only one argument, but it may do so an 'infinite' number of times through the 'magic' of currying and closures.
function add (a) {
var f = b => add(a + b);
f.valueOf = () => a;
return f;
}
var add4 = add(2)(2);
var add6 = add4(2);
var add10 = add6(2)(2);
var add14 = add10(2)+2;
//var add16 = add14(2); no longer works because of type conversion above.
console.log(+add4, +add6, +add10, add14);
//logs 4, 6, 10, 14
You can see, above, that the function can keep creating functions with new a values that can go on taking additional arguments. The function can also act as a normal variable for the purpose of math operations, such as var sum = add(x)+y;.
However, once the type conversion takes place, the sum from the previous example ceases to be a function and is converted to a number.
Now that the background is out of the way, my questions is this: is there a (relatively easy) way to prevent the type coercion of the add function while still allowing it to be used in arithmetic operations? Or, in other words, is there a simple way to directly modify the valueOf (and/or a values) without adding much boilerplate (preferrably while maintaining the add(x)+y; structure)?
I think that the coercion to number you are trying to avoid does not relate to add() function, it is the way '+' operator of Javascript works. Therefore changing this behavior is not an 'easy' task. It could take changing the way javascript parser work.
The simplest workaround I can think of (not sure of course how exactly you are using this function) is to always wrap the result with extra add() call, e.g.:
add(2)(3) + 8; // 13, number
can be wrapped like this:
add( add(2)(3) + 8 ); // function with valueOf = 13
Again, not sure about your exact use case though.
First up - n00b with Javascript here and I did try to search for something which represented similar concept as the one I have below but I couldn't find anything useful..sorry if my search skills are rather limited.
I'm going through the Eloquent Javascript and under the "Nested Scopes" section, there was some code showing how the scope of functions works; the following is the code (And a bit that I've added to experiment)
var landscape = function() {
var result = "";
var flat = function(size) {
for (var count = 0; count < size; count++)
result += "_";
};
var mountain = function(size) {
result += "/";
for (var count = 0; count < size; count++)
result += "'";
result += "\\";
};
// my nonsensical code -- begin
var myfunc = function(text) {
console.log("this is only a block of text -", text);
};
// my non sensical code -- end
flat(3);
mountain(4);
flat(6);
mountain(1);
flat(1);
// this is what I was trying to do and see what happens here..
mountain = myfunc("meh");
// end of my nonsense
return result;
};
console.log(landscape());
I understand that if within my function (myfunc) if I assign a value to result then when result is returned in the last line, it will get overwritten with whatever value is being assigned to it in myfunc
My question here I guess is what does it really mean to be able to assign one function variable to another (mountain = myfunc) and is there a real world usage to such a "feature"? If not, why does Javascript allow such an assignment?
This line:
mountain = myfunc("meh");
Assigns the return value of myfunc to mountain.
Since myfunc only logs something, it returns undefined (which is the default return value when no explicit return value is given).
Therefore, at the end of the example you've given mountain is undefined.
This is very useful, however, when you have functions that return other values. For example:
function add(a, b) {
return a + b;
}
function multiply(c, d) {
return c * d;
}
function divide(e, f) {
return e/f;
}
var multipliedThing = multiply(add(1,2), add(3,4));
var anotherMultipliedThing = multiply(add(5,6), add(7,8))
var result = divide(multiplied, anotherMultipliedThing);
// => 0.12727272727272726
The above is a bit contrived, but it shows a use case for assigning the return values of functions to variables.
The core concept of functions is general is to accept some value and return a value. With JavaScript (and many other languages) you get the "benefit" (I put that in quotes because it's debatable in some circumstances) of functions giving side effects (that is, mutating other values outside of the function). Therefore, if a function's purpose is for side effects, you might not need to return anything.
Look up "functional programming" if you're interested in a little bit of theory.
Here:
mountain = myfunc("meh");
you are calling myfunc with "meh" as parameter and assign its return value to mountain. The function logs a text and finishes. Since it does not have a return statement, it returns undefined and as a result, mountain will hold undefined at the end of the day. If, instead of that, you are doing this:
mountain = myfunc;
then the function named myfunc will be assigned to mountain, so, if you call mountain after this operation, it will execute myfunc.
My question here I guess is what does it really mean to be able to
assign one function variable to another (mountain = myfunc) and is
there a real world usage to such a "feature"? If not, why does
Javascript allow such an assignment?
The meaning of that is that you are able to store functions inside variables. It is a very useful feature, which you are using yourself when you define landscape, myfunc and mountain initially. Basically, a function can have properties, so there is literally an arsenal of possibilities you can do with a variable holding a function.
Lets consider this example:-
function X(){
var Y = function(arg1,arg2){
document.write(arguments.length);
document.write(arg2);
};
Y(arguments);
}
x(1,2,3,4,5);
/*Outputs 1 and undefined respectively.
Because here i am actually passing an array like-object to Y. */
By using apply here i am getting the desired results.
function X(){
var Y = function(arg1,arg2){
document.write(arguments.length);
document.write(arg2);
};
Y.apply(this,arguments);
}
x(1,2,3,4,5) //outputs 5 and 2
I want to create an apply like method that takes an Array of argument and invoke that function by passing arguments as seperate parameter values.
Like:
var arr=[1,2,3,4];
Y.apply_like_method(arr);
//and returns like Y(1,2,3,4)
Given this code:
var arr=[1,2,3,4];
Y.apply_like_method(arr);
//and returns like Y(1,2,3,4)
To make that work:
Function.prototype.apply_like_method = function(args) {
return this.apply(this, args);
}
Disclaimer: For illustration purposes only.
In other words, there's no way around .apply().
Just for shits and giggles using eval.
function myApply(fun, ar){
var i, r = [];
for(i=0; i<ar.length; ++i)
r[i] = 'ar['+i+']';
eval('fun('+r.join(',')+');');
}
You want to use the call method instead. See the MDN. What you are describing though is a hybrid of the call method and apply method; you want the ability to supply parameters individually, but to supply them to the function as an array. That, to my knowledge, doesn't exist currently and it would be easier to use apply/call as it was originally intended, or use a javascript object to pass the params into the function.