3 ms·
The dynamic binding of `this` at the callsite is one of Javascript's biggest mistakes. It's a tremendous source of run-time errors, and we have to hack around i
by acjohnson55 10y ago
The dynamic binding of `this` at the callsite is one of Javascript's biggest mistakes. It's a tremendous source of run-time errors, and we have to hack around it with closures and arrow functions. How counterintuitive is that? It's exhausting to reason about what `this` refers to within a given block of code.
I very frequently want to pass methods around as callbacks and almost never want my functions re-bound as methods on alternative objects. The only times I can think of that I want to re-bind is when I'm writing library code.
- int_19h 10y agoThe real problem is the lack of distinction between functions and methods. Dynamic "this" is really just a hack to make functions behave like methods when invoked via an object member. Python has an interesting solution to this, which is a lot more complicated - it has a more generic concept of "descriptors" that's used to wrap functions into magic sauce that makes them methods, taking care of "self" etc - but with most of that complexity hidden from either side (definition and invocation).
- acjohnson55 10y agoBut how important is the function vs. method distinction, really? I can't think of a reason the typical higher order function should care about whether its argument is a method on some object or not. That seems like a concern that should mostly be encapsulated in the function/method. Dynamic `this` assumes we want methods to be portable between objects. That's nice and all, but I can't think of the last time I thought it was the best approach to solving a problem in real application code.
- int_19h 10y agoIt's solely a syntactic thing in this case - so that you can invoke it as x.foo(y) rather than foo(x, y) or x.foo(x, y). So you need some magic for the receiver to become the function argument. It can be argued that a better way to do this is to just have freestanding generic functions that dispatch on the first argument (or better yet, multimethods that dispatch on as many as you want), and then just consider x.f(y) to be a syntactic sugar for f(x, y). But generics themselves are fairly complicated, and many people don't like that extra complexity.
- orf 10y agoI wouldn't say the Python solution is more complicated (complex, maybe), it's quite elegant and it essentially boils down to just pre-setting the first argument to the class instance or class value. You can do it yourself: >> def x(*args): print(args) >> new_func = a.__get__('silly sausage') >> new_func() ('silly sausage',) When you do instance.method() Python will look up 'method' inside 'instance'. If 'method' is a descriptor (with functions are), then `__get__` is called and the first argument is set to 'instance' Here are the docs if anyone is interested: https://docs.python.org/3/howto/descriptor.html https://docs.python.org/3/howto/descriptor.html
- int_19h 10y agoYeah, I meant descriptors themselves. Conceptually, having an ability in the language for an object to do some special handling when it's retrieved as a member of another object is a very powerful tool, and once you have it, it solves this particular problem neatly. But it's also an unusual thing to have, and few people are aware that something like this is at play every time you write something like `a.b`.