3 ms·
Being able to redefine everything is never a virtue as it introduces non-locality. You can't reason about what a particular piece of code is doing without under
by rsj_hn 8y ago
Being able to redefine everything is never a virtue as it introduces non-locality. You can't reason about what a particular piece of code is doing without understanding the full data flow that got you to this point and any re-definitions that might have happened along the way (with one re-definition overwriting the previous one).
For example, look at the following code:
function test(a) {
if (a > 1) {
console.log("bigger");
return;
} else if (a <= 1) {
console.log("smaller");
return;
} else {
console.log("Why is this happening to me?!");
}
}
var a = { x : 1,
valueOf: function() {
this.x -= 1;
return this.x==0?1:2;
}
}
test(a);
- tptacek 8y agoI'm not looking to recapitulate the debate about whether monkey patching is good or not. It's probably bad most of the time. That doesn't make the possibility of doing it at all, ever, bad. If it helps you, just substitute "mainstream feature" for "virtue".
- rsj_hn 8y agoThere is a difference between being able to monkey patch * objects created in the same scope * objects created outside the current scope but global * global objects * core language features For anyone who has to read code someone else wrote, as you go down this list life becomes much more painful. Even something as simple as forcing all the patches to be in one place so there is an unambiguous place to look for them would make a huge difference.
- tptacek 8y agoWell, you can do those things in Ruby, you can do them in Javascript, you can even do them in Python. Is there a high-level "interpretable" language that takes a hard line on this, or is it just a standard we're retrofitting onto Javascript?
- rsj_hn 8y agoNo, you cannot. In python you can certainly define your own object which might be a list and override the list accessor for your object, but you cannot override the general list accessor for all lists or those lists that you don't have a reference to. This is a big difference between a language like python and javascript. In javascript, buried deep in a function scope of some library might be code that overrides Function.prototype.apply, and then everywhere else in your code that a function is invoked, the new behavior will take effect. Nothing like that type of interference is possible in Python. In Python, you can only monkey patch those things that you have a reference for.
- JoachimSchipper 8y agoEh, this works fine (on Python 2.7): class A(object): def foo(self): return 'foo' a = A() a.foo() # returns 'foo' a.__class__.foo = lambda self: 'bar' A().foo() # new instance (!) returns 'bar' You're correct for list ("TypeError: can't set attributes of built-in/extension type 'list'"), but that's more a implementation limitation than a principled stance.
- rsj_hn 8y agoYou just looked up the class of a which is A and then you patched the foo method in the class definition of A. This is no different than you saying A.foo = lambda ... But what you can't do in Python is monkey patch a method to a class for which you don't have a reference. Try it. This is not an "implementation limitation", it is because Python is not a prototype language, so you can't monkey patch what it means to "call a function" for every method in every class because there is no "Function" object that is a prototype of all method calls in Python that plays a similar role to Function in Javascript. Similarly you can't patch "Object" de-reference and change the behavior of every single object de-reference. Those prototype chains are not exposed to you. In javascript you can override methods of classes which you can't reference. That's huge. Imagine one person creates an object with a foo method, and someone else changes what it means for all objects of any class to call any method. Think about what you have to audit to determine what the behavior of foo is -- in Python, you just need to audit anything that has a reference to the class where foo is defined. In javascript, you need to know what all the code is doing. That's a big difference.