When we write about a JavaScript function named 'f', we often refer to it as f(). We might write in an email, "You should call the function f() at this point". By choosing that way of writing we want to make it clear we are talking about a function, not about an "ordinary variable", which in JavaScript can hold any kind of object.
But, the notation "f ()" should not be used to refer to the function 'f'. Why? Because "f()" refers to the value returned by the function 'f' .
But doesn't this make it too easy to confuse 'f', which is a function, with variables named 'f', which may hold any type of object as well? Yes, it makes it more difficult.
But not really IF we take the viewpoint that a variable whose value never changes represents a function that takes 0 arguments, and will thus always "return" the same value - assuming we never change its value. And, it's good to use the convention that JavaScript itself uses. In JavaScript 'f()' means the value returned by the function 'f' when f is called.
According to functional programming a "function" is only a (pure) function if it always returns the same result for the same argument. Many JavaScript "functions" thus are not (real) (pure) functions. Variables which refer to values that are not JavaScript "functions" can be conceptually seen as "0-arity functions", if we never change their value after initial assignment. Or we should more properly say that the values stored in such variables are in fact 0 -arity functions.
I think the benefit of being able to distinguish between referring to a function f, and its value f(), is more important than the ability to indicate with a special form or syntax whether we are referring to a function or a variable holding some other type of value.
UPDATE: It needs to be emphasized that what I write about here is a convention for referring to JavaScript functions when writing about them. You can of course pick your own convention as you like. The way we define a function named 'f' in JavaScript is: "function f(){...}". Therefore it can be argued that a shorthand for that is "f()". I have used that convention myself in the past. But now I think I've seen the light: "f" stands for the function, "f()" for its result.
To emphasize that this is about how to write about JavaScript functions, I also changed the title of this post and dropped "... in JavaScript" from its end. This is not about "What f() means in JavaScript". That means what it means in JavaScript, the programming language. This post is about what f() means when we write about the JavaScript function 'f'.
Note the added expressive burden I face when writing this blog-post. I must not only make it clear whether I am referring to a function or its application. I also need to make clear whether I'm talking about JavaScript code, or writing about JavaScript (or even writing about writing about) code in a blog-post like this for instance. I hope I was able to be at least somewhat understandable!
© 2014 Panu Viljamaa. This work is licensed under a Creative Commons Attribution 4.0 International License
Saturday, January 25, 2014
Sunday, January 12, 2014
Improved map() & reduce() ?
In a previous post JavaScript function F () I presented the function F () which allows you to create functions from simple String expressions.
F() makes using JavaScript map() and other "functors" more concise, allowing you to replace:
[1,2,3].map(function (x){return x * 10});
with:
[1,2,3].map(F('x * 10'));
But I and some commentators felt the above still looked a bit cryptic for common use. Having to know what F() means is an extra mental load for readers of this code, as is the extra set of parentheses needed. And F() needs to be more or less cryptic, because it is supposed to be a shorthand after all.
So, here might be a better solution (but see the caveat at the end of this post):
1. Go to section titled "Polyfill" at MDN's Array.prototype.map. It gives the code to implement map() on older browsers which don't support that natively.
2. Read and be aware of the license(s) provided under which you can use their code, linked to at the bottom of their page.
3. Copy their code as instructed to your own script.
4. Replace the beginning of their code :
if (!Array.prototype.map)
{ Array.prototype.map = function(fun /*, thisArg */)
...
with this:
function F (aString)
{ return new Function("x", "y", "z", "w", "return " + aString);
}
Array.prototype.map
= function (funARG)
{ var fun = funARG;
if (typeof fun == "string")
{ fun = F(fun);
}
...
The above replaces the native implementation of map() if it did exist with our enhanced version of MDN's polyfill. If it didn't, it creates the method map() for the Array prototype.
You can now replace:
[1,2,3].map(F('x * 10'));
with the more simple:
[1,2,3].map('x * 10');
You can do a similar enhancement to their reduce() -code, available on the same site. Then you can write:
[1,2,3].reduce('x + y');
Documentation of map() and reduce() and their polyfills can be found at https://developer.mozilla.org/. Interestingly, I think the above makes the case that using a polyfill is sometimes better than having the native implementation (which theoretically can differ between browsers as well).
In general I think the point is that using functional expressions like map() should make programming simpler, not more verbose and complicated. It would be great if ECMA at some point added a shorthand syntax for anonymous functions to the JavaScript standard. But, it can in fact be argued that the solution above is good just because it does not require any new syntax, just an 'overloaded' semantics for map() and other functors.
UPDATE / CAVEAT: In fact I can not recommend this solution for general use. Depending on your application and the JavaScript libraries it uses, the solution above might break your application.. The reason is that when you add a method to the prototype of Array, it means that when looping over an array, that added property will on some browsers become one of the properties being looped over. That might break some existing code not only in your application but also in the libraries you use. So, for me at least it is back to using the function F(). Avoid adding your own methods to JavaScript built-in prototypes, at least things you can iterate over!
F() makes using JavaScript map() and other "functors" more concise, allowing you to replace:
[1,2,3].map(function (x){return x * 10});
with:
[1,2,3].map(F('x * 10'));
But I and some commentators felt the above still looked a bit cryptic for common use. Having to know what F() means is an extra mental load for readers of this code, as is the extra set of parentheses needed. And F() needs to be more or less cryptic, because it is supposed to be a shorthand after all.
So, here might be a better solution (but see the caveat at the end of this post):
1. Go to section titled "Polyfill" at MDN's Array.prototype.map. It gives the code to implement map() on older browsers which don't support that natively.
2. Read and be aware of the license(s) provided under which you can use their code, linked to at the bottom of their page.
3. Copy their code as instructed to your own script.
4. Replace the beginning of their code :
if (!Array.prototype.map)
{ Array.prototype.map = function(fun /*, thisArg */)
...
with this:
function F (aString)
{ return new Function("x", "y", "z", "w", "return " + aString);
}
Array.prototype.map
= function (funARG)
{ var fun = funARG;
if (typeof fun == "string")
{ fun = F(fun);
}
...
The above replaces the native implementation of map() if it did exist with our enhanced version of MDN's polyfill. If it didn't, it creates the method map() for the Array prototype.
You can now replace:
[1,2,3].map(F('x * 10'));
with the more simple:
[1,2,3].map('x * 10');
You can do a similar enhancement to their reduce() -code, available on the same site. Then you can write:
[1,2,3].reduce('x + y');
Documentation of map() and reduce() and their polyfills can be found at https://developer.mozilla.org/. Interestingly, I think the above makes the case that using a polyfill is sometimes better than having the native implementation (which theoretically can differ between browsers as well).
In general I think the point is that using functional expressions like map() should make programming simpler, not more verbose and complicated. It would be great if ECMA at some point added a shorthand syntax for anonymous functions to the JavaScript standard. But, it can in fact be argued that the solution above is good just because it does not require any new syntax, just an 'overloaded' semantics for map() and other functors.
UPDATE / CAVEAT: In fact I can not recommend this solution for general use. Depending on your application and the JavaScript libraries it uses, the solution above might break your application.. The reason is that when you add a method to the prototype of Array, it means that when looping over an array, that added property will on some browsers become one of the properties being looped over. That might break some existing code not only in your application but also in the libraries you use. So, for me at least it is back to using the function F(). Avoid adding your own methods to JavaScript built-in prototypes, at least things you can iterate over!
© 2014 Panu Viljamaa. This work is licensed under a Creative Commons Attribution 4.0 International License
Saturday, January 11, 2014
The JavaScript function F()
The JavaScript ECMA-262 standard 5th edition provides for Array-iterators like map() and reduce(). This means you don't need to write boiler-plate code for for -loops. Instead you can write things in a more functional way like this:
[1,2,3].map(function (x){return x * 10});
What diminishes the utility of iterators like map() is that unlike some other languages, JavaScript does not have a shorthand syntax for anonymous functions. You need to write a whole function-definition to call map(), as seen above.
So what could be done to reduce our workload and increase readability of our code even further? Answer: Define function F() as follows:
function F(aString)
{ var s, f2 ;
s = 'f2 = function (x,y,z,w)'
+ '{return ' + aString + '}';
eval(s);
return f2;
}
You can now make your code shorter like this:
a = [1,2,3].map(F('x * 10'));
// vs. [1,2,3].map(function (x){return x * 10});
ok (a[0] == 10);
ok (a[1] == 20);
ok (a[2] == 30);
n = [1,2,3,4].reduce(F('x + y'));
// vs. [1,2,3,4].reduce(function (x,y){return x + y;});
ok(n == 10);
The function ok () used above is a simple way to express expected behavior of code in code. It can be defined simply as:
function ok (arg)
{ if (!arg) {throw "ok() not ok"; }
}
After publishing the first version of this post I got a suggestion from Georgiy Shibaev at Google+ JavaScript community to use the Function -constructor instead of eval. And indeed it allows us to write the function F() in a simpler way:
function F (aString)
{ return new Function("x", "y", "z", "w", "return " + aString);
}
Performance-wise there doesn't seem to be any difference between the two versions, tested on IE10. The Function -constructor still needs to do an eval internally, since you pass it a String argument. I think this is a good use-case, and example how the Function-constructor is useful sometimes.
There are some caveats to using F (). It can not create functions that would contain if-then-else or other statements inside it. But you can use the ternary operator ? : . If you need something more complicated then of course you can always write a full function definition.
Documentation of map() and reduce(), including how to implement them on older browsers can be found at: https://developer.mozilla.org/
UPDATE: My next blog-post Improved map() & reduce() improves this solution further.
UPDATE-2: In earlier version I called this function 'f()'. But on 2nd thought this function is better named F (), to avoid possible conflicts with local variables, which typically at least start lowercase. I've made the change above
[1,2,3].map(function (x){return x * 10});
What diminishes the utility of iterators like map() is that unlike some other languages, JavaScript does not have a shorthand syntax for anonymous functions. You need to write a whole function-definition to call map(), as seen above.
So what could be done to reduce our workload and increase readability of our code even further? Answer: Define function F() as follows:
function F(aString)
{ var s, f2 ;
s = 'f2 = function (x,y,z,w)'
+ '{return ' + aString + '}';
eval(s);
return f2;
}
You can now make your code shorter like this:
a = [1,2,3].map(F('x * 10'));
// vs. [1,2,3].map(function (x){return x * 10});
ok (a[0] == 10);
ok (a[1] == 20);
ok (a[2] == 30);
n = [1,2,3,4].reduce(F('x + y'));
// vs. [1,2,3,4].reduce(function (x,y){return x + y;});
ok(n == 10);
The function ok () used above is a simple way to express expected behavior of code in code. It can be defined simply as:
function ok (arg)
{ if (!arg) {throw "ok() not ok"; }
}
function F (aString)
{ return new Function("x", "y", "z", "w", "return " + aString);
}
Performance-wise there doesn't seem to be any difference between the two versions, tested on IE10. The Function -constructor still needs to do an eval internally, since you pass it a String argument. I think this is a good use-case, and example how the Function-constructor is useful sometimes.
There are some caveats to using F (). It can not create functions that would contain if-then-else or other statements inside it. But you can use the ternary operator ? : . If you need something more complicated then of course you can always write a full function definition.
Documentation of map() and reduce(), including how to implement them on older browsers can be found at: https://developer.mozilla.org/
UPDATE: My next blog-post Improved map() & reduce() improves this solution further.
UPDATE-2: In earlier version I called this function 'f()'. But on 2nd thought this function is better named F (), to avoid possible conflicts with local variables, which typically at least start lowercase. I've made the change above
© 2014 Panu Viljamaa. This work is licensed under a
Creative Commons Attribution 4.0
International License
Subscribe to:
Posts (Atom)