def make_money():
blockchain_pyramid_scheme()
into: @with_jazz_hands
def make_money():
blockchain_pyramid_scheme()
or equivalently: def make_money(*args, **kwargs):
with_jazz_hands(make_money_impl, *args, **kwargs)
def make_money_impl():
blockchain_pyramid_scheme()
Both ways wrap with_jazz_hands around make_money without altering the call sites of make_money.Please, please learn about what higher order functions are in a more general setting before invoking them.
This "please, please learn" bullshit comes off as so smug and patronizing, did you realize? And when you're misunderstanding something it's even worse.
Even languages with labeled effects allow for this sort of construction effect. If they can properly sequence and isolate it, they allow mutation as well!
If you dislike call-by-name, why is Python's practice of insisting all non-trivial functions be called by name is not distasteful to you?
No, I was trying to isolate the important part. "@f def a: return b" would be the Python syntax, and I think it's misleading as sugar for, hmm, you'd have to write it as "a = f(lambda: b)" (hmm, I'd forgotten how different defining a function "natively" or as a lambda value are in Python).
You seem to be using a different definition of call-by-name to the one I'm used to. What bothers me is that a decorator can make a function behave completely differently (e.g. its body might never even be executed) but the syntax doesn't look like it can make that big a change to the function.
I guess in Python land, blueprint's entire purpose is to selectively fire your handlers.
Litterally.
You can take any code with decorators and replace them with this syntax. If you have arguments you must call the factory first, that's the only exception.