
On Thu, Nov 4, 2021 at 4:25 AM Ethan Furman <ethan@stoneleaf.us> wrote:
On 11/3/21 9:07 AM, Chris Angelico wrote:
On Thu, Nov 4, 2021 at 2:29 AM Ethan Furman wrote:
One similarity that I don't think has been mentioned yet:
- decorator syntax says, "run me later, after this function is built"
- late-bound argument syntax says, "run me later, just before each function call"
Hmm, I more think of decorator syntax as "modify this function". It runs at the same time that the def statement does, although the effects may be felt at call time (including a lot of simple ones like lru_cache).
Well, if "at the same time" you mean "after the function is defined even though the decorator appears first", then sure. ;-)
Yes, I do mean that that's the same time. There are three very different points in the life of a function: 1) Compilation (converting source code to byte code) 2) Definition 3) Invocation Decorators happen at definition time. Yes, the decorator is called after the function is otherwise defined, but that's very little difference (the only way it would be visible is an early-bound default, which would be evaluated prior to decorators being applied - all the rest of the work happens at compilation time). In contrast, late-bound defaults happen at invocation, which is completely separate.
Because both mean "run me later" we can leverage the @ symbol to aid understanding; also, because "run me later" can completely change the workings of a function (mutable defaults, anyone?), it deserves more attention than being buried in the middle of the expression where it is easy to miss (which is why I originally proposed the ? -- it stood out better).
One of the reasons I want to keep the latebound vs earlybound indication at the equals sign is the presence of annotations. I want to associate the lateboundness of the default with the default itself;
I think that level of specificity is unnecessary, and counter-productive. When discussing a particular late-bound default, how are you (usually) going to reference it? By name: "the 'spam' parameter is late-bound" -- so decorate the variable name.
You use the name because you can't refer to it other than by name, and that's fine. But it's the *default* that is different. Not the parameter. If you provide a value when you call the function, it doesn't make any difference whether there's an early default, a late default, or no default at all; the name is bound identically regardless.
So if you want to make use of the at sign, it would end up looking like matrix multiplication:
def func(spam: list @= []) -> str: ... def func(spam: list =@ []) -> str: ...
rather than feeling like decorating the variable.
Which is horrible. Put the @ at the front:
- its relation to decorators, and delayed evaluation, is much more clear - it stands out better to the reader
I agree that both of those are horrible. That's why I'm not advocating either :) ChrisA