On Sun, Dec 05, 2021 at 01:19:08PM +1100, Chris Angelico wrote:

> > And if you still think that we should care, we can come up with a more
> > complex trigger condition:
> >
> > - the parameter was flagged as using a late-default;
> > - AND the default is a LB function.
> >
> > Problem solved. Now you can use LB functions as early-bound defaults,
> > and all it costs is to record and check a flag for each parameter. Is it
> > worth it? Dunno.
> 
> Uhh.... so..... the parameter has to be flagged AND the value has to
> be flagged? My current proposal just flags the parameter.

*shrug* Is that a problem? Okay, then we can just flag the parameter, 
and use a plain ol' function with no special co_flag, although we do 
surely still want to give it an attribute `__expression__` to hold the 
source expression.


> So I ask again: what are you gaining by this change?

Separation of concerns. Testing. Cleaner design (the body of the 
function contains only the byte code from the body of the function). 
Testing. Introspection. Testing. You don't have to hack the byte-code of 
the function in order to monkey-patch defaults. Testing.

In case it wasn't obvious, I think that testing is important :-)

Other people might think of other uses.


[...]
> > What sort of "behave differently" do you think would prevent us from
> > introspecting the function object? "Differently" from what?
> 
> Wrapping it in a function means the walrus would assign in that
> function's context, not the outer function.

Unless the variable was a cell variable of the outer function. Which I 
think that they need to be. Didn't you already decide that walrus 
assignment has to be in the context of the function?

That's not a rhetorical question, I genuinely don't remember.


> The obvious solution is to say that, in this context, a is a nonlocal.

Right.


> But this raises a new problem: The function object, when created, MUST
> know its context. A code object says "this is a nonlocal", and a
> function object says "when I'm called, this is my context". Which
> means you can't have a function object that gets called externally,
> because it's the code, not the function, that is what you need here.
> And that means it's not directly executable, but it needs a context.

Sorry Chris, I don't understand what you are trying to say here. If I 
take what you are saying literally, I would take you as trying to say 
that closures can never be executed. But they clearly can be, and I know 
that you know that. So obviously I am misunderstanding you.

I don't understand why you think that we can't take one of those 
Late-Bound (LB) functions, which will be a closure, and call it like we 
can call any other closure.

By the time we have access to the LB functions, the owner function will 
exist, so there shouldn't be any problem with the context not existing.


> So, once again, we come right back around to what I have already: code
> that you can't lift out and call externally. The difference is that,
> by your proposal, there's a lot more overhead, for the benefit of
> maybe under some very specific circumstances being able to synthesize
> the result.

Surely it is the other way around? If you are correct, there are some 
extremely specific cicumstances involving the use of walrus operator in 
two different default expressions such that you cannot call one of the 
two functions, but the 99.99% of straight-forward non-walrus, non-tricky 
default expressions will work perfectly fine as independently callable 
functions.


> I'm still not convinced that it's as useful as you say. Compare these
> append-and-return functions:
>
> def build1(value, lst=None):
>     if lst is None: lst = []
[...]
> In which of them can you introspect the []?

"Here are lots of ways to solve a problem that don't let you test or 
introspect part of your code. Therefore we shouldn't add a feature that 
will let us more easily test and introspect that part of the code."

Yes Chris, I know that emulated late-bound defaults are currently 
effectively invisible at runtime (short of byte-code hacking). That 
weakness of the status quo is why you have written this PEP.

That invisibility is not a feature we should duplicate in late-bound 
defaults, but an argument for introducing defaults that overcome that 
weakness.

Right now, your PEP adds a new feature that gives us *zero* new 
functionality. There is nothing your PEP allows us to do that we cannot 
already do. It adds no new functionality. It's just syntactic sugar for 
"if arg is missing: return expression". You compile that code (or 
something very close to it) into the body of the function.

The only wins are (1) when people stumble into the "mutable default" 
gotcha, it is easy to tell them how to fix it (but not much easier than 
the status quo) and (2) a small increase in clarity, since we will be 
able to write the default expression directly in the signature instead 
of hiding behind a sentinel.

That's not nothing, but we've seen on this list a fair number of people 
who think that the increase in clarity is not enough to justify the 
feature. Do you think the Steering Council will consider those two small 
wins sufficient?

But with a different design, we have not just the increase in clarity, 
but also open the door to a ton of new possibilities that come about 
thanks to the separation of those default expressions into their own 
objects. I don't know whether that will be enough to sway the Steering 
Council. They might hate my idea even more. But feedback on this list 
suggests that your design's lack of introspectability is putting people 
off the idea.

It may be that this feature will never be used for anything more complex 
than `param=>[]`. In which case, okay, I concede, moving the default 
expression into its own code unit (a function? something else?) is 
overkill.

But I don't think that people will only use this for such trivial 
expressions. Maybe 60% of the cases will be just a literal list display 
or dict display, and maybe another 30% will be a simple call to an 
existing function, like `time.ctime()`.

But its the last 10% of non-trivial, interesting expressions where 
people will want to do more than just inspect the string. And having the 
expressions as first-class code units will open up those new 
opportunities that we currently lack.


-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JHS7W25ABYUAWEVYIY5V7GMAFYEWZM5Z/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to