-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Execution order for inner and outer functions #29
Comments
I'm curious, what is driving your expectation with top-down execution of decorators? Conceptually, you are decorating a descriptor, so the method all the way at the bottom will would be evaluated first to create the descriptor. Are you saying then you'd expect it to jump back to the top of the list of decorators? To be bottom-up makes sense to me because you are decorating the entirety of the items below it, e.g.
each decorator decorates the descriptor that was generated by the method/decorator to the right of it, so you could almost take that and pretend it were a method call, e.g.
|
For me, the expectation is that they'll execute in the order in which they're written i.e. a pipeline:
The functional composition interpretation might make more sense if they're written like that, but, so far, I've always written them like this: @foo
@bar
@baz
method { ... } i.e. like a series of statements rather than a single expression. Perl's attributes are written in the style you suggest (newlines aren't allowed), but, as I say, they're executed in lexical (top down) order. The function composition analogy suggests we expect to build functions like that, but I don't think that's the case. Classes and decorators are new, but (IMO) JavaScript language features/libraries have tended to prefer chaining (jQuery, lodash, promises, the function bind operator &c.) to the _(fn).foo().bar().baz()
$(fn).foo().bar().baz() Indeed, those fluent features/libraries arguably exist, at least in part, to rescue us from the readability/comprehensibility issues associated with deeply nested, right-to-left function composition. |
Actually, that's not quite how decorators in Python work: $ python3
Python 3.4.3 (default, Jul 13 2015, 12:18:23)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def decorator(msg):
... print("Decorating with", msg)
... def wrapper(fn):
... print("Returning newly decorated function for", msg)
... return lambda: (print("Running", msg) or fn())
... return wrapper
...
>>> @decorator("Top")
... @decorator("Middle")
... @decorator("Bottom")
... def test_function():
... print("Now running test_function")
...
Decorating with Top
Decorating with Middle
Decorating with Bottom
Returning newly decorated function for Bottom
Returning newly decorated function for Middle
Returning newly decorated function for Top
>>> test_function()
Running Top
Running Middle
Running Bottom
Now running test_function As you can see, there are 3 phases:
Only in Phase 2 is the order reversed. The reason for this is to ensure that the run time order of the decorated functions is in source order. If the decorators were applied in Phase 2 in source order then they would run in Phase 3 in reverse order, which would be counter-intuitive too. |
As a follow-up to the discussion here, I'd like to suggest a change to the execution order for both "outer" functions (i.e. the
foo
function implementing@foo
) and "inner" functions ((target, name, descriptor) -> descriptor?
). There's an issue related to the former here, but that's focused on Babel's implementation of the spec for outer functions. I'd like to propose both being executed in top-down order.As mentioned in #20, it appears that TypeScript and Python execute the outer functions in top-down order. The execution order for annotations in Java (and Groovy) appears to be unspecified. Perl's attributes are executed in lexical order i.e. "top down".
I'm still not sure what the rationale for executing the inner functions bottom-up is. IMO, it violates the principle of least surprise and is painful (or potentially impossible in the case of inner functions with side-effects) to work around.
The text was updated successfully, but these errors were encountered: