A friend of mine and I were having a discussion regarding currying and partial function application in Javascript, and we came to very different conclusions as to whether either were achievable. I came up with this implementation of Function.prototype.curry, which was the basis of our discussion:
Function.prototype.curry = function() {
if (!arguments.length) return this;
var args = Array.prototype.slice.apply(arguments);
var mmm_curry = this, args;
return function() {
var inner_args = Array.prototype.slice.apply(arguments);
return mmm_curry.apply(this, args.concat(inner_args));
}
}
Which is used as follows:
var vindaloo = function(a, b) {
return (a + b);
}
var karahi = vindaloo.curry(1);
var masala = karahi(2);
var gulai = karahi(3);
print(masala);
print(other);
The output of which is as follows in Spidermonkey:
$ js curry.js
3
4
His opinion was that since the Javascript function primitive does not natively support "partial function application", it's completely wrong to refer to the function bound to the variable karahi as partially applied. His argument was that when the vindaloo function is curried, the function itself is completely applied and a closure is returned, not a "partially applied function".
Now, my opinion is that while Javascript itself does not provide support for partial application in its' function primitives (unlike say, ML or Haskell), that doesn't mean you can't create a higher order function of the language which is capable of encapsulating concept of a partially applied function. Also, despite being "applied", the scope of the function is still bound to the closure returned by it causing it to remain "partially applied".
Which is correct?
Technically you're creating a brand new function that calls the original function. So if my understanding of partially applied functions is correct, this is not a partially applied function. A partially applied function would be closer to this (note that this isn't a general solution):
vindaloo.curry = function(a) {
return function(b) {
return a + b;
};
};
IIUC, this still wouldn't be a partially applied function. But it's closer. A true partially applied function would actually look like this if you can examine the code:
function karahi(b) {
return 1 + b;
};
So, technically, your original method is just returning a function bound within a closure. The only way I can think of to truly partially apply a function in JavaScript would be to parse the function, apply the changes, and then run it through an eval().
However, your solution is a good practical application of the concept to JavaScript, so practically speaking accomplishes the goal, even if it is not technically exact.
I think it's perfectly OK to talk about partial function application
in JavaScript - if it works like partial application, then it must
be one. How else would you name it?
How your curry function accomplishes his goal is just an implementation
detail. In a similar way we could have partial application in the ECMAScript spec,
but when IE would then implement it just as you did, you would have
no way to find out.
The technical details don't matter to me - if the semantics remain the same and, for all intents and purposes, the function acts as if it were really a partially-applied function, who cares?
I used to be as academic about things, but worrying about such particulars doesn't get real work done in the end.
Personally, I use MochiKit; it has a nice partial() function which assists in the creation of such. I loves it.
You should check out Curried JavaScript Functions. I haven't completely wrapped my head around his curry function, but it might have your answer.
Edit: I would agree with your assessment, however.
His opinion was that since the Javascript function primitive does not natively support "partial function application"
You can do currying in ES6 pretty elegantly:
> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]
Related
I am reading a book where it says one way to handle impure functions is to inject them into the function instead of calling it like the example below.
normal function call:
const getRandomFileName = (fileExtension = "") => {
...
for (let i = 0; i < NAME_LENGTH; i++) {
namePart[i] = getRandomLetter();
}
...
};
inject and then function call:
const getRandomFileName2 = (fileExtension = "", randomLetterFunc = getRandomLetter) => {
const NAME_LENGTH = 12;
let namePart = new Array(NAME_LENGTH);
for (let i = 0; i < NAME_LENGTH; i++) {
namePart[i] = randomLetterFunc();
}
return namePart.join("") + fileExtension;
};
The author says such injections could be helpful when we are trying to test the function, as we can pass a function we know the result of, to the original function to get a more predictable solution.
Is there any difference between the above two functions in terms of being pure as I understand the second function is still impure even after getting injected?
An impure function is just a function that contains one or more side effects that are not disenable from the given inputs.
That is if it mutates data outside of its scope and does not predictably produce the same output for the same input.
In the first example NAME_LENGTH is defined outside the scope of the function - so if that value changes the behaviour of getRandomFileName also changes - even if we supply the same fileExtension each time. Likewise, getRandomLetter is defined outside the scope - and almost certainly produces random output - so would be inherently impure.
In second example everything is referenced in the scope of the function or is passed to it or defined in it. This means that it could be pure - but isn't necessarily. Again this is because some functions are inherently impure - so it would depend on how randomLetterFunc is defined.
If we called it with
getRandomFileName2('test', () => 'a');
...then it would be pure - because every time we called it we would get the same result.
On the other hand if we called it with
getRandomFileName2(
'test',
() => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.charAt(Math.floor(25 * Math.random()))
);
It would be impure, because calling it each time would give a different result.
There's more than one thing at stake here. At one level, as Fraser's answer explains, assuming that getRandomLetter is impure (by being nondeterministic), then getRandomFileName also is.
At least, by making getRandomFileName2 a higher-order function, you at least give it the opportunity to be a pure function. Assuming that getRandomFileName2 performs no other impure action, if you pass it a pure function, it will, itself, transitively, be pure.
If you pass it an impure function, it will also, transitively, be impure.
Giving a function an opportunity to be pure can be useful for testing, but doesn't imply that the design is functional. You can also use dependency injection and Test Doubles to make objects deterministic, but that doesn't make them functional.
In most languages, including JavaScript, you can't get any guarantees from functions as first-class values. A function of a particular 'shape' (type) can be pure or impure, and you can check this neither at compile time nor at run time.
In Haskell, on the other hand, you can explicitly declare whether a function is pure or impure. In order to even have the option of calling an impure action, a function must itself be declared impure.
Thus, the opportunity to be impure must be declared at compile time. Even if you pass a pure 'implementation' of an impure type, the receiving, higher-order function still looks impure.
While something like described in the OP would be technically possible in Haskell, it would make everything impure, so it wouldn't be the way you go about it.
What you do instead depends on circumstances and requirements. In the OP, it looks as though you need exactly 12 random values. Instead of passing an impure action as an argument, you might instead generate 12 random values in the 'impure shell' of the program, and pass those values to a function that can then remain pure.
There's more at stake than just testing. While testability is nice, the design suggested in the OP will most certainly be impure 'in production' (i.e. when composed with a proper random value generator).
Impure actions are harder to understand, and their interactions can be surprising. Pure functions, on the other hand, are referentially transparent, and referential transparency fits in your head.
It'd be a good idea to have as a goal pure functions whenever possible. The proposed getRandomFileName2 is unlikely to be pure when composed with a 'real' random value generator, so a more functional design is warranted.
Anything that contains random (or Date or stuff like that). Will be considered impure and hard to test because what it returns doesn't strictly depends on its inputs (always different). However, if the random part of the function is injected, the function can be made "pure" in the test suite by replacing whatever injected randomness with something predictable.
function getRandomFileName(fileExtension = "", randomLetterFunc = getRandomLetter) {}
can be tested by calling it with a predictable "getLetter" function instead of a random one:
getRandomFileName("", predictableLetterFunc)
In Douglas Crockford's book "Javascript: The Good Parts" he provides code for a curry method which takes a function and arguments and returns that function with the arguments already added (apparently, this is not really what "curry" means, but is an example of "partial application"). Here's the code, which I have modified so that it works without some other custom code he made:
Function.prototype.curry = function(){
var slice = Array.prototype.slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to null, which will cause `this` to refer to the window
return that.apply(null, args.concat(slice.apply(arguments)));
};
};
So if you have an add function:
var add = function(num1, num2) {
return num1 + num2;
};
add(2, 4); // returns 6
You can make a new function that already has one argument:
var add1 = add.curry(1);
add1(2); // returns 3
That works fine. But what I want to know is why does he set this to null? Wouldn't the expected behavior be that the curried method is the same as the original, including the same this?
My version of curry would look like this:
Function.prototype.myCurry = function(){
var slice = [].slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to whatever `this` is when myCurry is called
return that.apply(this, args.concat(slice.apply(arguments)));
};
};
Example
(Here is a jsfiddle of the example)
var calculator = {
history: [],
multiply: function(num1, num2){
this.history = this.history.concat([num1 + " * " + num2]);
return num1 * num2;
},
back: function(){
return this.history.pop();
}
};
var myCalc = Object.create(calculator);
myCalc.multiply(2, 3); // returns 6
myCalc.back(); // returns "2 * 3"
If I try to do it Douglas Crockford's way:
myCalc.multiplyPi = myCalc.multiply.curry(Math.PI);
myCalc.multiplyPi(1); // TypeError: Cannot call method 'concat' of undefined
If I do it my way:
myCalc.multiplyPi = myCalc.multiply.myCurry(Math.PI);
myCalc.multiplyPi(1); // returns 3.141592653589793
myCalc.back(); // returns "3.141592653589793 * 1"
However, I feel like if Douglas Crockford did it his way, he probably has a good reason. What am I missing?
Reader beware, you're in for a scare.
There's a lot to talk about when it comes to currying, functions, partial application and object-orientation in JavaScript. I'll try to keep this answer as short as possible but there's a lot to discuss. Hence I have structured my article into several sections and at the end of each I have summarized each section for those of you who are too impatient to read it all.
1. To curry or not to curry
Let's talk about Haskell. In Haskell every function is curried by default. For example we could create an add function in Haskell as follows:
add :: Int -> Int -> Int
add a b = a + b
Notice the type signature Int -> Int -> Int? It means that add takes an Int and returns a function of type Int -> Int which in turn takes an Int and returns an Int. This allows you to partially apply functions in Haskell easily:
add2 :: Int -> Int
add2 = add 2
The same function in JavaScript would look ugly:
function add(a) {
return function (b) {
return a + b;
};
}
var add2 = add(2);
The problem here is that functions in JavaScript are not curried by default. You need to manually curry them and that's a pain. Hence we use partial application (aka bind) instead.
Lesson 1: Currying is used to make it easier to partially apply functions. However it's only effective in languages in which functions are curried by default (e.g. Haskell). If you have to manually curry functions then it's better to use partial application instead.
2. The structure of a function
Uncurried functions also exist in Haskell. They look like functions in "normal" programming languages:
main = print $ add(2, 3)
add :: (Int, Int) -> Int
add(a, b) = a + b
You can convert a function in its curried form to its uncurried form and vice versa using the uncurry and curry functions in Haskell respectively. An uncurried function in Haskell still takes only one argument. However that argument is a product of multiple values (i.e. a product type).
In the same vein functions in JavaScript also take only a single argument (it just doesn't know it yet). That argument is a product type. The arguments value inside a function is a manifestation of that product type. This is exemplified by the apply method in JavaScript which takes a product type and applies a function to it. For example:
print(add.apply(null, [2, 3]));
Can you see the similarity between the above line in JavaScript and the following line in Haskell?
main = print $ add(2, 3)
Ignore the assignment to main if you don't know what it's for. It's irrelevant apropos to the topic at hand. The important thing is that the tuple (2, 3) in Haskell is isomorphic to the array [2, 3] in JavaScript. What do we learn from this?
The apply function in JavaScript is the same as function application (or $) in Haskell:
($) :: (a -> b) -> a -> b
f $ a = f a
We take a function of type a -> b and apply it to a value of type a to get a value of type b. However since all functions in JavaScript are uncurried by default the apply function always takes a product type (i.e. an array) as its second argument. That is to say that the value of type a is actually a product type in JavaScript.
Lesson 2: All functions in JavaScript only take a single argument which is a product type (i.e. the arguments value). Whether this was intended or happenstance is a matter of speculation. However the important point is that you understand that mathematically every function only takes a single argument.
Mathematically a function is defined as a morphism: a -> b. It takes a value of type a and returns a value of type b. A morphism can only have one argument. If you want multiple arguments then you could either:
Return another morphism (i.e. b is another morphism). This is currying. Haskell does this.
Define a to be a product of multiple types (i.e. a is a product type). JavaScript does this.
Out of the two I prefer curried functions as they make partial application trivial. Partial application of "uncurried" functions is more complicated. Not difficult, mind you, but just more complicated. This is one of the reasons why I like Haskell more than JavaScript: functions are curried by default.
3. Why OOP matters not
Let's take a look at some object-oriented code in JavaScript. For example:
var oddities = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].filter(odd).length;
function odd(n) {
return n % 2 !== 0;
}
Now you might wonder how is this object-oriented. It looks more like functional code. After all you could do the same thing in Haskell:
oddities = length . filter odd $ [0..9]
Nevertheless the above code is object-oriented. The array literal is an object which has a method filter which returns a new array object. Then we simply access the length of the new array object.
What do we learn from this? Chaining operations in object-oriented languages is the same as composing functions in functional languages. The only difference is that the functional code reads backwards. Let's see why.
In JavaScript the this parameter is special. It's separate from the formal parameters of the function which is why you need to specify a value for it separately in the apply method. Because this comes before the formal parameters, methods are chained from left-to-right.
add.apply(null, [2, 3]); // this comes before the formal parameters
If this were to come after the formal parameters the above code would probably read as:
var oddities = length.filter(odd).[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
apply([2, 3], null).add; // this comes after the formal parameters
Not very nice is it? Then why do functions in Haskell read backwards? The answer is currying. You see functions in Haskell also have a "this" parameter. However unlike in JavaScript the this parameter in Haskell is not special. In addition it comes at the end of the argument list. For example:
filter :: (a -> Bool) -> [a] -> [a]
The filter function takes a predicate function and a this list and returns a new list with only the filtered elements. So why is the this parameter last? It makes partial application easier. For example:
filterOdd = filter odd
oddities = length . filterOdd $ [0..9]
In JavaScript you would write:
Array.prototype.filterOdd = [].filter.myCurry(odd);
var oddities = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].filterOdd().length;
Now which one would you choose? If you're still complaining about reading backwards then I have news for you. You can make Haskell code read forwards using "backward application" and "backward composition" as follows:
($>) :: a -> (a -> b) -> b
a $> f = f a
(>>>) :: (a -> b) -> (b -> c) -> (a -> c)
f >>> g = g . f
oddities = [0..9] $> filter odd >>> length
Now you have the best of both worlds. Your code reads forwards and you get all the benefits of currying.
There are a lot of problems with this that don't occur in functional languages:
The this parameter is specialized. Unlike other parameters you can't simply set it to an arbitrary object. Hence you need to use call to specify a different value for this.
If you want to partially apply functions in JavaScript then you need to specify null as the first parameter of bind. Similarly for call and apply.
Object-oriented programming has nothing to do with this. In fact you can write object-oriented code in Haskell as well. I would go as far as to say that Haskell is in fact an object-oriented programming language, and a far better one at that than Java or C++.
Lesson 3: Functional programming languages are more object-oriented than most mainstream object-oriented programming languages. In fact object-oriented code in JavaScript would be better (although admittedly less readable) if written in a functional style.
The problem with object-oriented code in JavaScript is the this parameter. In my humble opinion the this parameter shouldn't be treated any differently than formal parameters (Lua got this right). The problem with this is that:
There's no way to set this like other formal parameters. You have to use call instead.
You have to set this to null in bind if you wish to only partially apply a function.
On a side note I just realized that every section of this article is becoming longer than the preceding section. Hence I promise to keep the next (and final) section as short as possible.
4. In defense of Douglas Crockford
By now you must have picked up that I think that most of JavaScript is broken and that you should shift to Haskell instead. I like to believe that Douglas Crockford is a functional programmer too and that he is trying to fix JavaScript.
How do I know that he's a functional programmer? He's the guy that:
Popularized the functional equivalent of the new keyword (a.k.a Object.create). If you don't already do then you should stop using the new keyword.
Attempted to explain the concept of monads and gonads to the JavaScript community.
Anyway, I think Crockford nullified this in the curry function because he knows how bad this is. It would be sacrilege to set it to anything other than null in a book entitled "JavaScript: The Good Parts". I think he's making the world a better place one feature at a time.
By nullifying this Crockford is forcing you to stop relying on it.
Edit: As Bergi requested I'll describe a more functional way to write your object-oriented Calculator code. We will use Crockford's curry method. Let's start with the multiply and back functions:
function multiply(a, b, history) {
return [a * b, [a + " * " + b].concat(history)];
}
function back(history) {
return [history[0], history.slice(1)];
}
As you can see the multiply and back functions don't belong to any object. Hence you can use them on any array. In particular your Calculator class is just a wrapper for list of strings. Hence you don't even need to create a different data type for it. Hence:
var myCalc = [];
Now you can use Crockford's curry method for partial application:
var multiplyPi = multiply.curry(Math.PI);
Next we'll create a test function to multiplyPi by one and to go back to the previous state:
var test = bindState(multiplyPi.curry(1), function (prod) {
alert(prod);
return back;
});
If you don't like the syntax then you could switch to LiveScript:
test = do
prod <- bindState multiplyPi.curry 1
alert prod
back
The bindState function is the bind function of the state monad. It's defined as follows:
function bindState(g, f) {
return function (s) {
var a = g(s);
return f(a[0])(a[1]);
};
}
So let's put it to the test:
alert(test(myCalc)[0]);
See the demo here: http://jsfiddle.net/5h5R9/
BTW this entire program would have been more succinct if written in LiveScript as follows:
multiply = (a, b, history) --> [a * b, [a + " * " + b] ++ history]
back = ([top, ...history]) -> [top, history]
myCalc = []
multiplyPi = multiply Math.PI
bindState = (g, f, s) -->
[a, t] = g s
(f a) t
test = do
prod <- bindState multiplyPi 1
alert prod
back
alert (test myCalc .0)
See the demo of the compiled LiveScript code: http://jsfiddle.net/5h5R9/1/
So how is this code object oriented? Wikipedia defines object-oriented programming as:
Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known as methods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.
According to this definition functional programming languages like Haskell are object-oriented because:
In Haskell we represent concepts as algebraic data types which are essentially "objects on steroids". An ADT has one or more constructors which may have zero or more data fields.
ADTs in Haskell have associated functions. However unlike in mainstream object-oriented programming languages ADTs don't own the functions. Instead the functions specialize upon the ADTs. This is actually a good thing as ADTs are open to adding more methods. In traditional OOP languages like Java and C++ they are closed.
ADTs can be made instances of typeclasses which are similar to interfaces in Java. Hence you still do have inheritance, variance and subtype polymorphism but in a much less intrusive form. For example Functor is a superclass of Applicative.
The above code is also object-oriented. The object in this case is myCalc which is simply an array. It has two functions associated with it: multiply and back. However it doesn't own these functions. As you can see the "functional" object-oriented code has the following advantages:
Objects don't own methods. Hence it's easy to associate new functions to objects.
Partial application is made simple via currying.
It promotes generic programming.
So I hope that helped.
Reason 1 - not easy to provide a general solution
The problem is that your solution is not general. If the caller doesn't assign the new function to any object, or assigns it to a completely different object, your multiplyPi function will stop working:
var multiplyPi = myCalc.multiply.myCurry(Math.PI);
multiplyPi(1); // TypeError: this.history.concat is not a function
So, neither Crockford's nor your solution can assure that the function will be used correctly. Then it may be easier to say that the curry function works only on "functions", not "methods", and set this to null to force that. We might only speculate though, since Crockford doesn't mention that in the book.
Reason 2 - functions are being explained
If you asking "why Crockford didn't use this or that" - the very likely answer is: "It wasn't important in regard to the demonstrated matter." Crockford uses this example in the chapter Functions. The purpose of the sub-chapter curry was:
to show that functions are objects you can create and manipulate
to demonstrate another usage of closures
to show how arguments can be manipulated.
Finetuning this for a general usage with objects was not purpose of this chapter. As it is problematic if not even impossible (see Reason 1), it was more educational to put there just null instead if putting there something which could raise questions if it actually works or not (didn't help in your case though :-)).
Conclusion
That said, I think you can be perfectly confident in your solution! There's no particular reason in your case to follow Crockfords' decision to reset this to null. You must be aware though that your solution only works under certain circumstances, and is not 100% clean. Then clean "object oriented" solution would be to ask the object to create a clone of its method inside itself, to ensure that the resultant method will stay within the same object.
But what I want to know is why does he set this to null?
There is not really a reason. Probably he wanted to simplify, and most functions that make sense to be curried or partially applied are not OOP-methods that use this. In a more functional style the history array that is appended to would be another parameter of the function (and maybe even a return value).
Wouldn't the expected behavior be that the curried method is the same as the original, including the same this?
Yes, your implementation makes much more sense, however one might not expect that a partially applied function still needs to be called in the correct context (as you do by re-assigning it to your object) if it uses one.
For those, you might have a look at the bind method of Function objects for partial application including a specific this-value.
From MDN:
thisArg The value of this provided for the call to fun. Note that this
may not be the actual value seen by the method: if the method is a
function in non-strict mode code, null and undefined will be replaced
with the global object, and primitive values will be boxed.
Hence, if the method is in non-strict mode and the first argument is null or undefined, this inside of that method will reference Window. In strict mode, this is null or undefined. I've added a live example on this Fiddle.
Furthermore passing in nullor undefined does not do any harm in case the function does not reference this at all. That's probably why Crockford used null in his example, to not overcomplicate things.
I'm a JavaScript slightly-more-than-beginner.
While reading the source for EventEmitter, I stumbled upon this interesting and, to me, elegant function:
// alias a method while keeping the correct context
function alias(name) {
return function aliasClosure() {
return this[name].apply(this, arguments);
};
}
I have two main questions:
First: why is the aliasClosure a named function? Is it useful in some way other than clarity? Also, is is really a closure? To me, it looks just like a semi-anonymous function.
Second: I rewrote this function like this:
function alias2(name) {
return this[name].bind(this);
}
Is it equivalent? I think it should, since the this context is the same and it's preserved in both versions.
Is there a reason to prefer one over the other?
No, these are not at all equivalent. From looking at the alias() function I think you would use it something like this:
> Array.prototype.strjoin = alias('join'); // make 'strjoin' an alias of 'join'
> [1, 2, 3].strjoin(" + ");
"1 + 2 + 3"
Using alias2() in the above code will not work.
Providing a name in a function instantiation expression makes a name available for stack traces. (I'm told newer debuggers don't always need it if the function is created in certain contexts, like a var initialization.)
I think the second is equivalent, mostly, though .bind() has some obscure special cases it handles.
edit wait - no, they're not equivalent. The first one involves this explicitly, and performs the lookup on each call. The first function doesn't need this to be bound to anything when it's called, while yours will throw an exception in that case.
One change that would make the two functions almost equal is wrapping bind inside a closure, like this:
function alias2(name) {
return function() {
return this[name].bind(this);
}
}
Still, bind behaves obscurely in rare cases.
Can I replace s standard DOM functions like removeChild to show for example alert before some node removed from parent? Something like that but my example is with errors
var original = node.removeChild;
node.removeChild = function(node, original){
alert('message');
original(node);
}
If you want to apply this across the document do this
var original = Node.prototype.removeChild;
Node.prototype.removeChild = function(node) {
//custom logic
original.apply(this, arguments);
}
If you want to apply the change only to a selected node then
var original = node.removeChild;
node.removeChild = function(node){
//custom logic
original.apply(this, arguments);
}
First of all, the usage of the new keyword is completely incorrect. That will severely change the behaviour. function is an instance of Function, the "mothership" of all JavaScript functions.
When using the new keyword, the function will be immediately executed and the behaviour very different from what you expect. See Section 13 of the ECMA Language Specification for more details on how to create function objects. Read it here, at page 98.
Second, it is strongly discouraged to alter any native object prototype. It leads to the most tedious and painful bugs in human history. Anybody coming in after you to edit the code will spend a long time before figuring out where that alert originates from.
Keep those two actions separate, they are completely unrelated. Wrapping them up in a prototype function is very bad design, for the above reason any many more, such as:
Using for in loops. You will iterate through more properties that you should if you forget to use hasOwnProperty.
Yourself and other developers will have a hard time figuring out why random things are happing with a basic DOM Node remove operation occurs.(you will forget, happens to everybody).
I am going to be radical an just say no. While it may technically work on the browsers you care about and be the basis for prototype.js, you should never modify DOM objects, or their prototypes, like this.
There is a long post on the topic: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ but the TL;DR is that these are "hosted objects" and modification to their behavior is not guaranteed. It may work today on browser x but there's no guarantee about browser y or even x tomorrow.
Your implementation looks fine, except that you don't need to pass original as an argument there.
var original = node.removeChild;
node.removeChild = function(node) {
alert('message');
original(node);
}
What's the shortest way (characters) of creating a "new function" alias.
Basically this is for code golf and minifying code beyond reason.
So when you usually would write:
a=function(a,b,c){return a+b+c;}
You could write something like (also let's abstract return keyword as well with global variable R):
a=$("a,b,c","R=a+b+c")
a=$(a,b,c){R=a+b+c}
(Not sure if the second one is possible.)
For the first example the best I've come up with is:
$=function(a,b){return new Function(a,"R=0;"+b+";return R")}
Both the sizes (usage, declaration) matter but usage size is more important.
I don't think new Function() is of viable use for most functions even without performance concerns because unlike function() {} no closure is created. The compiled function will only have access to its own local scope and the global object. Think about that for a second. Javascript without closures is like Java without classes or C without pointers. Clearly everything would break.
Anyways, if you only intend to use this alias for short lambada like expressions that don't need clousers, one obvious way to make things even more terse is to leave off the parameters deceleration. Simply assume that a = arguments[0]; b = arguments[1]; etc...
$=function(b){return new Function('a,b,c,d,e,f,g,h,i,j', b);};
Another way would be to automatically return the value of the last expression, instead of needing it to be explicitly declared
$=function(body) {
return function(a,b,c,d,e,f,g,h,i,j) { return eval(body); };
};
Horrifying isn't it? This works because eval()...well it returns the value of the last evaluated expression. No return needed. Of course this method is an even bigger hit to performance, as the code in body is reevaluated each time the function is called, while with new Function the code is (or should be) only compiled once.
Anyways performance be dammed, with the previous method your function declaration is down to this
var myeyes = $('a+b+c');
alert(myeyes(1,2,3)); //6
Purdy huh? Still, I think it would look better like this
'a+b+c'
Looks like a string yes? Well...it is a sting, but in the hands of the right function, it could be evaluated as if it were a full on function literal
//Lets just assume that IE does not exist mmkay?
var funcs = ['map', 'filter', 'every', 'some'];
for (var i=0; i<funcs.length; i++) {
(function() {
//Store original function
var name = funcs[i]
var _super = Array.prototype[name];
Array.prototype[name] = function() {
//$ !== jQuery
if (typeof arguments[0] == 'string') arguments[0] = $(arguments[0]);
return _super.apply(this, arguments);
};
}());
}
Now you can write
[1,2,3,4,5].map('a*a');
instead of
[1,2,3,4,5].map(function(a){return a*a;});
which is even better than Firefox's Expression Closure
[1,2,3,4,5].map(function(a) a*a);
Try it out here: http://jsbin.com/iyogu3/edit
If only we could actually write function expressions like this without calling upon the eval monster. Really, one of my main gripes with Javascript syntax is the requirement to spam function(){} throughout your code. Some kind of shorthand function literal syntax (not the aforementioned half-assed expression closure) that was interpreted the same as a regular verbose function literal would go a long way to making my code look a little less ridiculous. And it might help minifying a tiny bit as well.
For simple expressions, you could use:
function L(a,x){return new Function(a,'return '+x)}
Usage:
n=L('a,b,c','a+b+c');
You might get milage out of something silly like:
eval("t=Fa+b};t(1,2)".replace("F", "function(a,b){return "))
Here's a variant that has a larger overhead but saves one character per function definition.
"#" will be replaced with "return ".
$=function(a,b){return new Function(a,b.replace(/#/g,"return "))}
a=$("a,b,c","#a+b+c")
Your code:
a=function(a,b,c){return a+b+c;}
Shortened code:
a=(a,b,c)=>a+b+c
The shortest function declaration possible in js is 4 characters
Example: _=>1