On Sat, Nov 6, 2021 at 2:57 AM Stephen J. Turnbull
<stephenjturnb...@gmail.com> wrote:

> Still on the agenda as far as I can see:
>
> 1.  Syntax.  The proposals I can recall are
>     a.  x=>default
>     b.  *x=default
>     c.  x=@default
>     d.  maybe putting * or @ on the opposite component in b and c?
>     e.  a keyword before default such as "late" or "defer".  Others?
>     I believe Chris currently favors a.

Yes, I'm currently favouring "x=>default", though weakly; but I
strongly favour syntax options that change only the part around the
equals sign (no adornment before the variable name, no adornment after
the expression). There are a few syntaxes listed in the PEP, and
there's a plan in progress to strengthen one of those syntaxes
somewhat.

> 2.  The implementation.
>     a.  Keep an abstract representation of the default expression as a
>         string in a dunder, and prefix the compiled body with code to
>         evaluate it in the appropriate namespace.
>     b.  As in a, but the abstract representation is an AST or similar.
>     c.  Wrap the evaluation in a function (or function-like object)
>         and invoke it before the compiled body (this was suggested by
>         Steven d'Aprano as a compromise, I believe).
>     d.  Wrap the evalution in a general-purpose deferred object (this
>         is not in the scope of PEP 671, discussion below).
>     I believe Chris's current reference implementation is a (or if I
>     got that wrong, closer to a than any of the others).
>
> It would be helpful to the discussion if Chris starts by striking any
> of the above that he's unwilling to implement.

Sure. Let's see.

a. This is what's currently implemented, plus using Ellipsis in
__defaults__ as a marker that there needs to be a default expression.
It's a little bit complicated, but it does mean that the vast majority
of functions aren't significantly affected by this proposal.
b. Less preferred than a, due to the higher cost of retaining the AST,
but I'd be fine with this conceptually.
c. While this is philosophically interesting, I'm not sure how it
would be implemented, so I'd have to see someone else's implementation
before I can truly judge it.
d. Definitely not, and if someone else wants it, it can be a competing proposal.

So: a and b are yes, c is dubious, d is not.

> A question for Chris: In your proposal, as I understand it, an
> expensive default expression would always be evaluated, even if it's
> not always needed.  Eg, in this toy example:
>
>     def foo(x:int=>expensive()):
>         if delphic_oracle():
>             return x
>         else:
>             return 0
>
> expensive() is always evaluated.  In that (presumably quite rare)
> case, we'd just use a sentinel instead, of course.

It will be evaluated even if it's not referred to in the body, but
only if the argument is omitted. There is a guarantee that, once the
function body begins executing, all arguments (whether given values or
populated from defaults) have been assigned. So, yes, if you want
conditional evaluation, you do need to use a sentinel.

> I have further two comments, which are mostly addressed to Steve, I
> guess.  First, I don't really understand Steve's intended difference
> between 2c and 2d.  Second, as I understand them, both 2c and 2d
> encapsulate the expression in bytecode, so the nice property of
> introspectability of the expression is lost.  I guess you can
> decompile it more easily than if it's just interpolated into the
> function body, but if it's implemented as a closure, don't we lose the
> identity of the identifiers in the expression?  And if it's not (eg,
> the function-like thing encapsulates an abstract representation of the
> expression rather than bytecode that computes it), what's the point of
> 2c?  I don't see how it has any advantage over 2a or 2b.

I'm not entirely sure either. There are a few concepts that could be
described, but without getting some implementation going, it'll be
hard to judge them.

> Footnotes:
> [1]  Nobody's right, if everybody's wrong. -- Stephen Stills
>      You can never have too many Steves in a discussion!

We do have a good few. Not quite as many Chrises, although I'm more
likely to see Chris replying to Chris replying to Chris on a nerdy
mailing list than I am anywhere else!

My current implementation does have one somewhat annoying flaw: the
functionality of late-bound defaults is buried in the function's
bytecode, but the description of it is a function dunder, and can be
changed. I'd be open to suggestions that would make this a feature of
the code object instead, thus preventing desynchronization.

ChrisA
_______________________________________________
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/7D36SK5KYLT2RQZ77ZLLKKRMFNXPMOKS/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to