[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-23 Thread Dom Grigonis
It’s 2 options:

a) It is a special constant - the only one with such property. Then it would be 
used solely for this purpose. I don’t think you can prevent someone from using 
it for something else. But I don’t think this case of misusage is a big 
exception to the way things are. As this would be only such constant, it then 
should be used only for this purpose. Standard sentinels would be used for 
everything else and None could be left for cross-language cases, such as json 
null value and similar.

But as of now, it is not possible to do what I am referring to with either 
sentinels or None. The standard is to override default such as None with 
itself, witch means ‘NotProvided', but it actually is. Then that value is 
checked within the function’s body and if it is ’NotProvided’, then default is 
set. I appreciate that None value is singleton and technically it is the same 
one, but special value is useful if one was to have a more complex default 
argument and wanted to enforce it from outside, while retaining ability to 
specify it as well. It is simply cleaner than what is being done now. And 
without this PEP, I don’t think there would be a big case for it, but with this 
PEP, it seems more compelling as it seems to encourage more complex defaults.

So no, I don’t think it is likely that another special value would be needed. 
All the other “special values” can be handled with sentinels. If this case is 
not special enough, then (b) could work.

b) Property of a callable to specify an object which is treated in such manner 
as special constant in (a) or a decorator which emulates such behaviour. This 
might be even better approach as long as it is performant and reliable.

Decorator could be a good option, but that depends on how performant it is. If 
it’s the same as e.g. `getcallargs` then, at least to me, not a very attractive 
option.

But I think there might be case for special value as well.

But again, only my opinion, I don’t really have an issue with the way things 
currently are with function arguments. Just answered questionnaire regarding 
this PEP and this is my opinion.

——
I am more excited about deferred-eval, which if was implemented with neat 
syntax, would improve things for me in many different places in one go and from 
what I have seen would benefit many different areas and provide more neat 
solutions for several cases that came to this group & fairly elegant (although 
maybe not as pythonic) ones for several PEPs that were deferred or rejected.

DG

> On 23 Jul 2023, at 14:40, Richard Damon  wrote:
> 
> I think the question is, how is that fundamentally different than the value 
> "None". Once you create this "special value", some function will decide to 
> make it have a meaning as a passed in value, and then need a DIFFERENT 
> "special value" as a default.
> 
> On 7/23/23 1:13 AM, Dom Grigonis wrote:
>> Or maybe you are not listening to what I am saying.
>> 
>> It would only take effect for arguments, which have default value.
>> 
>> So.
>> dict().__setitem__(key, NotGiven)
>> type(NotGiven)
>> Exception(NotGiven)
>> getattr(NotGiven, name)
>> 
>> Ok, maybe there are some crucial functions, which have argument defaults. 
>> But again, there is another solution then, implement efficient decorator in 
>> standard library, maybe as part of sentinels, maybe as part of your PEP, 
>> maybe separately.
>> 
>> I never said that it isn’t hard to write low-level python code. I will do 
>> that when the time is right for me. And I am not claiming that it is 
>> possible. If you read my language, all of my doubts are clearly expressed. 
>> You just seem to read everything as black and white even when it is not so.
>> 
>> However, such statements are in no way valid arguments in such discussion. 
>> If my idea is not optimal, not necessary, no-one needs it or any other valid 
>> responses, why it is not a good one - I can accept it.
>> But commenting that “it makes no sense” without properly explaining to me 
>> why after giving it some thought - it’s not fair.
>> 
>> Also, if you looked at things from a bit more positive perspective, maybe 
>> you could come up with some nice new ways how it could be done. Maybe not 
>> exactly what I am proposing, but some alternative, which would make it work. 
>> Most likely something much better than I am proposing.
>> 
>> After all, I am trying to see how your PEP can be improved, because if it 
>> could be used in all cases, where None can be, then at least to me, it would 
>> be a no-brainer to use it instead and to adapt it as best practice.
>> 
>> DG
>> 
>>> On 23 Jul 2023, at 07:35, Chris Angelico  wrote:
>>> 
>>> On Sun, 23 Jul 2023 at 14:08, Dom Grigonis  wrote:
 IT IS AN OBJECT. Never said otherwise.
>>> One that you can't do any of the operations I described. There is no
>>> way to use it as an object.
>>> 
 `inspect.getcallargs` can seemingly be modified for such behaviour. I just 
 wrote a decorator, which does 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-23 Thread Richard Damon
I think the question is, how is that fundamentally different than the 
value "None". Once you create this "special value", some function will 
decide to make it have a meaning as a passed in value, and then need a 
DIFFERENT "special value" as a default.


On 7/23/23 1:13 AM, Dom Grigonis wrote:

Or maybe you are not listening to what I am saying.

It would only take effect for arguments, which have default value.

So.
dict().__setitem__(key, NotGiven)
type(NotGiven)
Exception(NotGiven)
getattr(NotGiven, name)

Ok, maybe there are some crucial functions, which have argument defaults. But 
again, there is another solution then, implement efficient decorator in 
standard library, maybe as part of sentinels, maybe as part of your PEP, maybe 
separately.

I never said that it isn’t hard to write low-level python code. I will do that 
when the time is right for me. And I am not claiming that it is possible. If 
you read my language, all of my doubts are clearly expressed. You just seem to 
read everything as black and white even when it is not so.

However, such statements are in no way valid arguments in such discussion. If 
my idea is not optimal, not necessary, no-one needs it or any other valid 
responses, why it is not a good one - I can accept it.
But commenting that “it makes no sense” without properly explaining to me why 
after giving it some thought - it’s not fair.

Also, if you looked at things from a bit more positive perspective, maybe you 
could come up with some nice new ways how it could be done. Maybe not exactly 
what I am proposing, but some alternative, which would make it work. Most 
likely something much better than I am proposing.

After all, I am trying to see how your PEP can be improved, because if it could 
be used in all cases, where None can be, then at least to me, it would be a 
no-brainer to use it instead and to adapt it as best practice.

DG


On 23 Jul 2023, at 07:35, Chris Angelico  wrote:

On Sun, 23 Jul 2023 at 14:08, Dom Grigonis  wrote:

IT IS AN OBJECT. Never said otherwise.

One that you can't do any of the operations I described. There is no
way to use it as an object.


`inspect.getcallargs` can seemingly be modified for such behaviour. I just 
wrote a decorator, which does what I proposed using `inspect` module for a 
chosen sentinel value. The issue is that it would be a bottleneck if used on 
any callable, which is continuously used. `inspect.getcallargs`, `signature`, 
`getfullargspec` are very expensive.

If that can be done, theoretically it should be able to be done at lower level 
as well. After all, behaviour of it should be modelled after what is happening 
at the function call.


Since you clearly are not listening to the discussion, I will leave
you with one final recommendation: Write some code. Don't just claim
that it's possible; write actual code that makes it happen. You will
discover exactly how hard it is. If I am wrong, you will be able to
PROVE that I am wrong, instead of merely claiming it.

ChrisA


--
Richard Damon

___
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/JEIZYDJGK3RDW77FNZX5TZUP47JJT4XW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Dom Grigonis
Or maybe you are not listening to what I am saying.

It would only take effect for arguments, which have default value.

So.
dict().__setitem__(key, NotGiven)
type(NotGiven)
Exception(NotGiven)
getattr(NotGiven, name)

Ok, maybe there are some crucial functions, which have argument defaults. But 
again, there is another solution then, implement efficient decorator in 
standard library, maybe as part of sentinels, maybe as part of your PEP, maybe 
separately.

I never said that it isn’t hard to write low-level python code. I will do that 
when the time is right for me. And I am not claiming that it is possible. If 
you read my language, all of my doubts are clearly expressed. You just seem to 
read everything as black and white even when it is not so.

However, such statements are in no way valid arguments in such discussion. If 
my idea is not optimal, not necessary, no-one needs it or any other valid 
responses, why it is not a good one - I can accept it.
But commenting that “it makes no sense” without properly explaining to me why 
after giving it some thought - it’s not fair.

Also, if you looked at things from a bit more positive perspective, maybe you 
could come up with some nice new ways how it could be done. Maybe not exactly 
what I am proposing, but some alternative, which would make it work. Most 
likely something much better than I am proposing.

After all, I am trying to see how your PEP can be improved, because if it could 
be used in all cases, where None can be, then at least to me, it would be a 
no-brainer to use it instead and to adapt it as best practice.

DG

> On 23 Jul 2023, at 07:35, Chris Angelico  wrote:
> 
> On Sun, 23 Jul 2023 at 14:08, Dom Grigonis  wrote:
>> 
>> IT IS AN OBJECT. Never said otherwise.
> 
> One that you can't do any of the operations I described. There is no
> way to use it as an object.
> 
>> `inspect.getcallargs` can seemingly be modified for such behaviour. I just 
>> wrote a decorator, which does what I proposed using `inspect` module for a 
>> chosen sentinel value. The issue is that it would be a bottleneck if used on 
>> any callable, which is continuously used. `inspect.getcallargs`, 
>> `signature`, `getfullargspec` are very expensive.
>> 
>> If that can be done, theoretically it should be able to be done at lower 
>> level as well. After all, behaviour of it should be modelled after what is 
>> happening at the function call.
>> 
> 
> Since you clearly are not listening to the discussion, I will leave
> you with one final recommendation: Write some code. Don't just claim
> that it's possible; write actual code that makes it happen. You will
> discover exactly how hard it is. If I am wrong, you will be able to
> PROVE that I am wrong, instead of merely claiming it.
> 
> 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/TPY2JHOBXUQIRNRYUUBUX46Y3HS4GQVK/
> Code of Conduct: http://python.org/psf/codeofconduct/

___
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/RTXRKZWWTRPGYHQTIRNGB57RMRFGWDQR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Chris Angelico
On Sun, 23 Jul 2023 at 14:08, Dom Grigonis  wrote:
>
> IT IS AN OBJECT. Never said otherwise.

One that you can't do any of the operations I described. There is no
way to use it as an object.

> `inspect.getcallargs` can seemingly be modified for such behaviour. I just 
> wrote a decorator, which does what I proposed using `inspect` module for a 
> chosen sentinel value. The issue is that it would be a bottleneck if used on 
> any callable, which is continuously used. `inspect.getcallargs`, `signature`, 
> `getfullargspec` are very expensive.
>
> If that can be done, theoretically it should be able to be done at lower 
> level as well. After all, behaviour of it should be modelled after what is 
> happening at the function call.
>

Since you clearly are not listening to the discussion, I will leave
you with one final recommendation: Write some code. Don't just claim
that it's possible; write actual code that makes it happen. You will
discover exactly how hard it is. If I am wrong, you will be able to
PROVE that I am wrong, instead of merely claiming it.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Dom Grigonis
IT IS AN OBJECT. Never said otherwise.

`inspect.getcallargs` can seemingly be modified for such behaviour. I just 
wrote a decorator, which does what I proposed using `inspect` module for a 
chosen sentinel value. The issue is that it would be a bottleneck if used on 
any callable, which is continuously used. `inspect.getcallargs`, `signature`, 
`getfullargspec` are very expensive.

If that can be done, theoretically it should be able to be done at lower level 
as well. After all, behaviour of it should be modelled after what is happening 
at the function call.

> On 23 Jul 2023, at 06:58, Chris Angelico  wrote:
> 
> On Sun, 23 Jul 2023 at 12:20, Dom Grigonis  wrote:
>> 
>> 
>>> There is no way to have a value that isn't a value, in Python. The
>>> concept doesn't make sense and would break all kinds of things.
>>> (That's why, when a special function like __getitem__ has to be able
>>> to return literally anything, it signals "nothing to return" by
>>> raising an exception.)
>> 
>> I accept that it might be difficult to implement.
>> I see that it would break things at cpython.
>> Will definitely break some of the stdlib. E.g. inspect stuff.
>> It wouldn’t break any of the existing python code.
>> So yes, might not be a minor change.
>> 
>> Could it be done nicely and easily by someone with relevant experience? I 
>> don’t know.
>> 
>> 
>> But I fail to see why it doesn’t make sense - that’s a strong statement.
>> 
>> It would be a value, just a value that is treated with exception in this 
>> particular case.
>> There is definitely code at that level - resolving args, kwargs, dealing 
>> with “/" and “*” in relation to arguments provided, etc.
>> 
>> It would take effect only on keyword arguments with defaults, if so then 
>> fairly contained matter.
>> It could be a default of a keyword argument itself, would have a type and 
>> everything as any other object.
>> 
> 
> Okay. You now have an object that you can't do anything with, because
> it can't be a function argument. So...
> 
> Show me how you would put this value into a dictionary.
> 
> Show me how you would find out the type of this value.
> 
> Show me how you would refer to this in an exception.
> 
> Show me how you would access an attribute of this object.
> 
> Show me how you would do ANYTHING WHATSOEVER with this object.
> 
> It does not make sense to have an object that isn't an object. And in
> Python, every value *is* an object.
> 
> 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/CFFEGHQNQRDA7EDS4ZJBWAWDPU64OYHH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Chris Angelico
On Sun, 23 Jul 2023 at 12:20, Dom Grigonis  wrote:
>
>
> > There is no way to have a value that isn't a value, in Python. The
> > concept doesn't make sense and would break all kinds of things.
> > (That's why, when a special function like __getitem__ has to be able
> > to return literally anything, it signals "nothing to return" by
> > raising an exception.)
>
> I accept that it might be difficult to implement.
> I see that it would break things at cpython.
> Will definitely break some of the stdlib. E.g. inspect stuff.
> It wouldn’t break any of the existing python code.
> So yes, might not be a minor change.
>
> Could it be done nicely and easily by someone with relevant experience? I 
> don’t know.
>
>
> But I fail to see why it doesn’t make sense - that’s a strong statement.
>
> It would be a value, just a value that is treated with exception in this 
> particular case.
> There is definitely code at that level - resolving args, kwargs, dealing with 
> “/" and “*” in relation to arguments provided, etc.
>
> It would take effect only on keyword arguments with defaults, if so then 
> fairly contained matter.
> It could be a default of a keyword argument itself, would have a type and 
> everything as any other object.
>

Okay. You now have an object that you can't do anything with, because
it can't be a function argument. So...

Show me how you would put this value into a dictionary.

Show me how you would find out the type of this value.

Show me how you would refer to this in an exception.

Show me how you would access an attribute of this object.

Show me how you would do ANYTHING WHATSOEVER with this object.

It does not make sense to have an object that isn't an object. And in
Python, every value *is* an object.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Dom Grigonis

> There is no way to have a value that isn't a value, in Python. The
> concept doesn't make sense and would break all kinds of things.
> (That's why, when a special function like __getitem__ has to be able
> to return literally anything, it signals "nothing to return" by
> raising an exception.)

I accept that it might be difficult to implement.
I see that it would break things at cpython.
Will definitely break some of the stdlib. E.g. inspect stuff.
It wouldn’t break any of the existing python code.
So yes, might not be a minor change.

Could it be done nicely and easily by someone with relevant experience? I don’t 
know.


But I fail to see why it doesn’t make sense - that’s a strong statement.

It would be a value, just a value that is treated with exception in this 
particular case.
There is definitely code at that level - resolving args, kwargs, dealing with 
“/" and “*” in relation to arguments provided, etc.

It would take effect only on keyword arguments with defaults, if so then fairly 
contained matter.
It could be a default of a keyword argument itself, would have a type and 
everything as any other object.

___
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/YN3QPKPCN2HSTARQNXXHXZWJTH3AA5RI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Chris Angelico
On Sun, 23 Jul 2023 at 09:15, Dom Grigonis  wrote:
> This works ok:
>
> ```
> def foo(bar=None):
> if bar is None:
> bar = A()
>
> class A:
> pass
> ```
>
> If PEP is aiming to replace the latter example, then it would be great if it 
> kept all of its advantages. I.e. not having to change the definition order in 
> the module, which could be preferred as it is for other reasons.
>

Well, yes, it would work, but I still wouldn't recommend it. This is
confusing to read. But since the default would be evaluated at call
time, it would behave exactly as you describe.

> And also to come back to my previous notice that there is no way to enforce 
> the default in case of function chain with cascading arguments. You said it 
> is a known limitation. Is there no easy & sensible approach to not have it? 
> E.g.:
>
> a) Any object which has certain dunder attribute, which evaluates to True?
> b) NotGiven sentinel value which does exactly that.
> c) A special constant, which, if present, at lower level makes things behave 
> the same way as the argument wasn’t provided at all. Such constant could be 
> very useful outside the scope of this PEP as well. Could be a great place to 
> introduce such constant? And to me it seems it could be a well justified one, 
> given it actually is special and does not fall under umbrella of generic 
> sentinel values.
>
> It would be great if it was to retain all the benefits of the latter example. 
> Then (at least from my POV) this PEP would be an excellent addition, and I am 
> most likely be using it now if it existed.
>

There is no way to have a value that isn't a value, in Python. The
concept doesn't make sense and would break all kinds of things.
(That's why, when a special function like __getitem__ has to be able
to return literally anything, it signals "nothing to return" by
raising an exception.)

The only way to not pass an argument in Python is to not pass it. That
means, at best, something like *a or **kw, where the sequence/dict
either has something or doesn't, depending on whether you want to pass
the argument. None of this is changed by PEP 671 and I don't think
there's a lot of point trying to, as it would only cause more problems
elsewhere.

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/34HFL6N6FMEIEHB5A22BBBXBAUIXXUBP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-07-22 Thread Dom Grigonis
1. Not if it is exactly as described in PEP.
2. No.
3. -
4. Couple of points here. One check and one orthogonal idea, which would make 
this PEP very attractive to me.

I would definitely like use this functionality if both of below points were 
satisfied/achievable. If any of those weren't satisfied I might just default to 
current syntax as I like to have a default pattern, which I know is flexible 
enough to cover most if not all the cases that I encounter. Currently, I manage 
this particular area (which your PEP is concerned with) with `None` and 
`unittest.Sentinel` defaults and deal with them in function's body.

A.
Currently, if I write:
```
def foo(bar=A()):
pass

class A:
pass
```
I get an error. That is why having `bar=None` is advantageous. This works ok:

```
def foo(bar=None):
if bar is None:
bar = A()

class A:
pass
```

If PEP is aiming to replace the latter example, then it would be great if it 
kept all of its advantages. I.e. not having to change the definition order in 
the module, which could be preferred as it is for other reasons.

My best guess is that it works the same as the latter example, (given the 
expression can contain other arguments, which are not there yet) but just 
wanted to double check.

B.

And also to come back to my previous notice that there is no way to enforce the 
default in case of function chain with cascading arguments. You said it is a 
known limitation. Is there no easy & sensible approach to not have it? E.g.:

a) Any object which has certain dunder attribute, which evaluates to True?
b) NotGiven sentinel value which does exactly that.
c) A special constant, which, if present, at lower level makes things behave 
the same way as the argument wasn’t provided at all. Such constant could be 
very useful outside the scope of this PEP as well. Could be a great place to 
introduce such constant? And to me it seems it could be a well justified one, 
given it actually is special and does not fall under umbrella of generic 
sentinel values.

It would be great if it was to retain all the benefits of the latter example. 
Then (at least from my POV) this PEP would be an excellent addition, and I am 
most likely be using it now if it existed.

Regards,
DG
___
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/7DCPF624EEATZ5IRCSCHDIXDTCT2WYB3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-04-29 Thread Chris Angelico
On Sat, 29 Apr 2023 at 23:01,  wrote:
>
> Ad 4) Wouldn't "<=" be a little more logical than "=>"? The perceived 
> direction of the "flow" of the default value is exactly opposite, i.e., the 
> default value is always evaluated and then put *into* the argument.
>

Using arrows to represent information flow has been done, for example
in APL and R, but it's generally not been a significant benefit. C++
uses flow operators in a delightfully cute way that gets old after
about the second time you actually use it. (Python has done similarly
cute things with certain operators, with mixed results. I think
Pathlib has been quite successful, but there are others that are less
so.) Flow direction simply isn't a valuable-enough piece of
information to be worth reusing an existing operator and thus risking
ambiguity.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2023-04-29 Thread petr
Ad 4) Wouldn't "<=" be a little more logical than "=>"? The perceived direction 
of the "flow" of the default value is exactly opposite, i.e., the default value 
is always evaluated and then put *into* the argument.

For example:
def bisect_right(a, x, lo=0, hi<=len(a), *, key=None):
___
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/WBRQJB6YCNEFGOKBXGGL6WX6M66LCRAE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-12-25 Thread Chris Angelico
On Mon, 26 Dec 2022 at 10:02,  wrote:
>
> I didn't realize def foo(x, y=[]) had this strange artifact but it totally 
> makes sense, TIL. I did not get the right idea reading the PEP though, since 
> currently the motivation reads:
>
> > Optional function arguments, if omitted, often have some sort of logical 
> > default value. When this value depends on other arguments, or needs to be 
> > reevaluated each function call, there is currently no clean way to state 
> > this in the function header.
>
> and I kinda glossed over the second use-case. I feel like more emphasis can 
> be added since that part is what necessitates the new syntax.
>
> I do think that being able to reference other arguments is very useful in 
> it's own right and would go a long way in helping to solve the None check 
> problem brought up in PEP 505 even more cleanly.

Yeah, they're both useful features, and both handled by the simple
rule of "evaluate late-bound defaults in the context of the function
body".

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/5A5UGJDLHW66VJXWUE4S6TSFLMFZIIDC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-12-25 Thread shironeko . python
I didn't realize def foo(x, y=[]) had this strange artifact but it totally 
makes sense, TIL. I did not get the right idea reading the PEP though, since 
currently the motivation reads:

> Optional function arguments, if omitted, often have some sort of logical 
> default value. When this value depends on other arguments, or needs to be 
> reevaluated each function call, there is currently no clean way to state this 
> in the function header.

and I kinda glossed over the second use-case. I feel like more emphasis can be 
added since that part is what necessitates the new syntax.

I do think that being able to reference other arguments is very useful in it's 
own right and would go a long way in helping to solve the None check problem 
brought up in PEP 505 even more cleanly.
___
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/D4DP4UB7LPYPBNPTXIZDRVD6NOPMGPQP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-12-25 Thread Chris Angelico
On Mon, 26 Dec 2022 at 04:53, Steven D'Aprano  wrote:
>
> On Sat, Dec 24, 2022 at 11:34:19AM -0500, Shironeko wrote:
> >
> > Is the => syntax needed? as far as I can think of, the only time where
> > late evaluation is needed is when the expression references the other
> > arguments.
>
> You are missing the most common case, the motivating case, for
> late-bound defaults: mutable defaults.
>
> def spam(x, y=>[]):
> pass

Exactly - this is the most important reason. So the true reason for
the => syntax is: in order to gain late-bound defaults, we have to
distinguish them from early-bound defaults (because changing ALL
function default arguments to late-bound would be a massive breaking
change). There's no particular reason for it to be "=>" specifically,
and other syntax options have been considered, but it does need to be
something other than "=".

> The ability for default values to refer to other parameters is a Nice To
> Have, not a Must Have. It has been a very long time since I have read
> the PEP, and I don't remember whether it reviews other languages to see
> what functionality they provide for defaults, but I don't think many
> other languages allow you to set the default of one parameter to be
> another parameter.

JavaScript does, by nature of its extremely simplistic definition of
argument defaults.

function f(x=1, y=x) {console.log("--> x = ", x, ", y = ", y);}
f(5)
--> x =  5 , y =  5
f()
--> x =  1 , y =  1
f(42, undefined)
--> x =  42 , y =  42
f(undefined, 123)
--> x =  1 , y =  123

Ruby does:

$ irb
irb(main):001:1* def f(x=1, y=x)
irb(main):002:1*   puts "x = #{x}, y = #{y}"
irb(main):003:0> end
=> :f
irb(main):004:0> f()
x = 1, y = 1
=> nil
irb(main):005:0> f(123)
x = 123, y = 123
=> nil

I suspect that, in each case, the rule is quite simple: the argument
default is evaluated in the context of the function's body. Exactly
the same as PEP 671 proposes.

Any other languages to test?

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-12-25 Thread Steven D'Aprano
On Sat, Dec 24, 2022 at 11:34:19AM -0500, Shironeko wrote:
> 
> Is the => syntax needed? as far as I can think of, the only time where 
> late evaluation is needed is when the expression references the other 
> arguments.

You are missing the most common case, the motivating case, for 
late-bound defaults: mutable defaults.

def spam(x, y=>[]):
pass

Here the intention is to have y's default be a *different* list each 
time you call spam(x), instead of the same list each time.

The ability for default values to refer to other parameters is a Nice To 
Have, not a Must Have. It has been a very long time since I have read 
the PEP, and I don't remember whether it reviews other languages to see 
what functionality they provide for defaults, but I don't think many 
other languages allow you to set the default of one parameter to be 
another parameter.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-12-25 Thread Shironeko

Is the => syntax needed? as far as I can think of, the only time where late 
evaluation is needed is when the expression references the other arguments. So 
the rule “if the expression reference other arguments it will get evaluated at 
function call time” should suffice right?

In effect:
def foo(a, b=len(a), c=max(b, d), d=15):
gets translated into
def foo(a, b=None, c=None, d=15):
if b is None:
b = len(a)
if c is None:
c = max(b, d)

I’m not sure if this is already brought up in previous emails, I tried my best 
to search for it but can’t find any reference.

Also, I think the sepc should not leave any ambiguous behavior otherwise it 
creates subtle incompatibilities when people use different implementations. 
This goes for whether all other argument can be referenced or only some 
argument can be. Or if the use of outer scope variables should get evaluated at 
def time, something like foo(a, b=max(a, outer.length())) should length() be 
ran once or on every function call. Stuff like these create an functional 
effect to the user so they ought to be well defined and not implementation 
specific.
___
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/ENILUNXZUIAI4OOH6XLHLFYHXOAHO4JY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-09-21 Thread Chris Angelico
On Wed, 21 Sept 2022 at 11:27, Michael Scott Cuthbert  wrote:
>
> [Michael Cuthbert:]
> > > I'm rather surprised though that the typing advantages of the pep have 
> > > not been emphasized enough.
>
> [Chris Angelico]
> > That would be because I personally don't use that kind of strict
> > typing, so it's not something I'm really qualified to talk about.
> > Would you like to write up a paragraph or two about it? I could
> > incorporate it verbatim, if you like.
>
> Sure!

Cool, thanks for writing that up.

> When the editor moves to a typed version, something like this would seem 
> reasonable:

"Editor" could mean a person or a program. Which do you mean? I want
to guess you mean the person making the edit, but it's not quite
clear.

Otherwise, looks good.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-09-20 Thread Michael Scott Cuthbert
[Michael Cuthbert:]
> > I'm rather surprised though that the typing advantages of the pep have not 
> > been emphasized enough.

[Chris Angelico]
> That would be because I personally don't use that kind of strict
> typing, so it's not something I'm really qualified to talk about.
> Would you like to write up a paragraph or two about it? I could
> incorporate it verbatim, if you like.

Sure!

* * *
Late-bound arg defaults also help with proper typing, especially for 
established code-bases that are incrementally adding typing to their code.  For 
instance, take this untyped example that might take a list of musical pitches 
and put them in a particular order:

def order_pitches(pitches=None):
 if pitches is None:
 pitches = []
 ...  # do reordering referencing "pitches" a lot
 pitches.sort(key=lambda p: (p.octave, p.name))
 return pitches

When the editor moves to a typed version, something like this would seem 
reasonable:

def order_pitches(pitches: list[Pitch]|None = None) -> list[Pitch]:
  ...  # same code as above.

However, some type checkers (for instance, that of PyCharm 2022) will continue 
to reveal the type as "list[Pitch]|None" even after type narrowing.  (Mypy will 
correctly type narrow in this example but not in code that checks for `if not 
hasattr(pitches, '__iter__')` and in many other more complex examples).

In this case, authors sometimes need to resort to rewriting code with a new 
variable name:

def order_pitches(pitches: list[Pitch]|None = None) -> list[Pitch]:
  non_none_pitches: list[Pitch]
  if pitches is None:
  non_none_pitches = []
 else:
  non_none_pitches = cast(list[Pitch], pitches)
 ...  # rest of code must be rewritten to use "non_none_pitches"

The typed definition also seems to imply that "None" is an acceptable calling 
type for the function rather than just being a stand-in for an omitted call.  A 
type-checker will allow `order_pitches(None)` to pass, perhaps preventing later 
refactoring to use a sentinel such as:

def order_pitches(pitches: list[Pitch]|MISSING = MISSING) -> list[Pitch]:
if pitches is MISSING:
pitches = []
...

With the PEP, the process of adding typing does not impact the code, nor imply 
that "None" is a fine calling signature.

def order_pitches(pitches: list[Pitch] => []) -> list[Pitch]:
...  
# pitches is always list[Pitch] and needs no narrowing
pitches.sort(...)
return pitches
 

*   *   *
It is true that the tools for automatic type-narrowing continue to get better 
(in looking up code that broke the type-narrowing with a "no_none..." variable, 
I found that 2 of 4 places I found where I had done this workaround two years 
ago no longer needed it for either mypy or PyCharm), but there are still 
numerous cases where the process of typing around a sentinel type that will be 
replaced by the correct type for computing still unnecessarily exist.
___
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/3MCSLWZUQQTK6FQWTBTCQPUUTGIFKND4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-09-16 Thread Chris Angelico
On Sat, 17 Sept 2022 at 09:40, Michael Scott Cuthbert  wrote:
>
> Very late addition to these long threads -- I'm loving the proposal.  I'm 
> rather surprised though that the typing advantages of the pep have not been 
> emphasized enough.

That would be because I personally don't use that kind of strict
typing, so it's not something I'm really qualified to talk about.
Would you like to write up a paragraph or two about it? I could
incorporate it verbatim, if you like.

>  I have a lot of code that in order to get correct typing in a strict mode 
> does something like this:
>
> ```
> def move_pitches(pitches: list[Pitch]|None = None):
> non_none_pitches: list[Pitch]
> if pitches is None:
>  non_none_pitches = []
> else:
>  non_none_pitches = pitches
> ```
>
> with the PEP, the typing becomes:
>
> ```
> def move_pitches(pitches: list[Pitch] => []):
>  ...
> ```
>
> and not only is the variable typed properly and more simply from the start, 
> but I get to use my preferred variable name throughout.
>

Yeah, that is definitely an advantage, without a doubt!

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-09-16 Thread Michael Scott Cuthbert
Very late addition to these long threads -- I'm loving the proposal.  I'm 
rather surprised though that the typing advantages of the pep have not been 
emphasized enough.  I have a lot of code that in order to get correct typing in 
a strict mode does something like this:

```
def move_pitches(pitches: list[Pitch]|None = None):
non_none_pitches: list[Pitch]
if pitches is None:
 non_none_pitches = []
else:
 non_none_pitches = pitches
```

with the PEP, the typing becomes:

```
def move_pitches(pitches: list[Pitch] => []):
 ...
```

and not only is the variable typed properly and more simply from the start, but 
I get to use my preferred variable name throughout.

Since I do about 30% of my work in TypeScript, the idea that `=>` implies that 
the right side will be evaluated in some way and returned is a cognitive 
lightening not burden.  

I do think that the PEP should be stricter in defining whether if an 
implementation chooses to do the evaluating in two passes whether normal '=' 
arguments to the right can or cannot be referenced by late-bound arguments.  I 
initially read the PEP as saying that you might or might not be able to 
reference rightward normal arguments depending on the implementation.

 - Michael Scott Asato Cuthbert (music21)
___
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/HL6U6YGJAZQGCXXB3PSFIKEU3CPHE6F2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-07-26 Thread Chris Angelico
On Wed, 27 Jul 2022 at 08:39, Stanislav Zmiev  wrote:
> 4) If "no" to question 1, is there some other spelling or other small
> change that WOULD mean you would use it? (Some examples in the PEP.)
> defer keyword that Andre proposed is a better option, in my opinion. However, 
> I don't like the entire idea so I would argue against that as well. Don't 
> take it as something bad -- it's a good idea in general but I believe that 
> it's a step in the wrong direction specifically for python as it is.
>

Except that the defer keyword *simply doesn't work* for this use-case.
In my opinion, that's a bit of a downside.

I posted examples of the problems in the other thread, but there were
no replies.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-07-26 Thread Stanislav Zmiev
1) If this feature existed in Python 3.11 exactly as described, would
you use it?
Definitely not. It significantly increases cognitive burden on the reader. If 
python didn't have pattern matching, walrus, ternary expressions, etc -- then 
maybe I would consider this as something harmless. But right now we are at risk 
of slowly turning a great language into a monstrosity. We already have a tool 
(an if statement) that solves this problem just as well, is a widely known 
pattern, and is a lot easier to read.

2) Independently: Is the syntactic distinction between "=" and "=>" a
cognitive burden?
Yes, but a slight one.

4) If "no" to question 1, is there some other spelling or other small
change that WOULD mean you would use it? (Some examples in the PEP.)
defer keyword that Andre proposed is a better option, in my opinion. However, I 
don't like the entire idea so I would argue against that as well. Don't take it 
as something bad -- it's a good idea in general but I believe that it's a step 
in the wrong direction specifically for python as it is.

5) Do you know how to compile CPython from source, and would you be
willing to try this out?
I do know how to compile it but I believe that the examples from your pep are 
great and paint a realistic enough picture of how it's going to feel so I'm 
afraid I have to refuse to test it. Sorry :)
___
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/5EAE2GP7SZ6M5MWKVFRQFIJ3PFUCZ6ML/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread Brendan Barnwell

On 2022-06-20 22:54, Chris Angelico wrote:

You are welcome to dislike the PEP on the basis that the existing
language is better than it would be with this feature. I personally
disagree, but that's what opinions are. But to object on the mere
basis that something MIGHT, despite demonstrated evidence, be better?
That is unfair and unhelpful.


	Again, I disagree, and I think that stance is unreasonable.  There is 
nothing wrong with saying "Let's not do this.  Instead let's wait and 
explore other ideas and see if we come up with something better."  There 
is no requirement to provide any alternative proposal whatsoever --- 
whether vague or specific, real or potential, conceptual or concrete --- 
merely to justify opposing this PEP.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
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/6OKKZLXQLWMN4VGGS2W53FMCZ76NFSA7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread David Mertz, Ph.D.
I will post to a different thread for my actual semi-proposal.  But to
answer the claim that late-bound arg defaults and late-bound
everything-else are unrelated, and to start with an early version of what
I'd actually want, I wrote this:

https://github.com/DavidMertz/peps/blob/master/pep-.rst

I could definitely use help making it better from anyone who is sympathetic
with the idea of generalized deferred computation in Python.

On Tue, Jun 21, 2022 at 5:12 AM Paul Moore  wrote:

> On Tue, 21 Jun 2022 at 10:01, Paul Moore  wrote:
>
> > PS To be clear, my objections to the PEP aren't based on deferred
> > evaluation. So I'm an impartial 3rd party on this matter. I *do* have
> > problems with the PEP, so I have an interest in seeing the PEP fairly
> > reflect the lack of consensus, and accurately represent the concerns
> > people are raising, but I don't have a preference for any specific
> > outcome in the matter of deferred evaluation.
>
> Thinking some more about this, my comments are pretty much what I'd be
> saying if I were a sponsor for this PEP. I don't think a PEP sponsor
> should be someone who doesn't agree with the PEP, otherwise I'd offer
> to take on the role (assuming you need a sponsor). But please take my
> comments in that vein. (And if you do ever manage to convert me to
> support of the PEP, remind me of this comment and I'll be the sponsor
> ;-))
>
> Paul
> ___
> 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/LLEEOLPQTM5INNXRIIT6UVN3TEJLQIZD/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
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/BV4MAZPIZA33NMDH7B5W2UFXZ22ZX7AH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread Paul Moore
On Tue, 21 Jun 2022 at 10:01, Paul Moore  wrote:

> PS To be clear, my objections to the PEP aren't based on deferred
> evaluation. So I'm an impartial 3rd party on this matter. I *do* have
> problems with the PEP, so I have an interest in seeing the PEP fairly
> reflect the lack of consensus, and accurately represent the concerns
> people are raising, but I don't have a preference for any specific
> outcome in the matter of deferred evaluation.

Thinking some more about this, my comments are pretty much what I'd be
saying if I were a sponsor for this PEP. I don't think a PEP sponsor
should be someone who doesn't agree with the PEP, otherwise I'd offer
to take on the role (assuming you need a sponsor). But please take my
comments in that vein. (And if you do ever manage to convert me to
support of the PEP, remind me of this comment and I'll be the sponsor
;-))

Paul
___
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/LLEEOLPQTM5INNXRIIT6UVN3TEJLQIZD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread Paul Moore
On Tue, 21 Jun 2022 at 09:20, Chris Angelico  wrote:
>
> On Tue, 21 Jun 2022 at 18:15, Paul Moore  wrote:
> > I'm not talking about a "full and detailed specification". That's
> > *still* more than is needed for a valid debate (at this point). But
> > what *is* needed is a more complete explanation of how deferred
> > evaluation would work, and some plausible (not set in stone, just
> > plausible) syntax. With that, it would be possible to write down two
> > versions of the same code and judge between them. We've not yet had a
> > sufficiently clear (IMO) definition of the semantics of deferred
> > evaluation yet (or if we have, it's been lost in the arguments), and
> > it would help a lot if someone could provide one. I'm thinking
> > specifically about the rules for variable capture, scoping,
> > interaction with assignment expressions in terms of introducing names,
> > etc., as well as how evaluation is "triggered" and what ability there
> > is to explicitly say "evaluate this now".
> >
>
> That's what I mean by a full specification. Even without code, that
> would be enough to start talking about it. But those arguing "don't go
> for lazy evaluation, go for deferreds" don't seem to want to actually
> push that proposal forward.
>
> That's why I call it vapourware.

OK, so maybe if you were a little less aggressive in your replies, we
could see if anyone wants to respond. But frankly, I imagine it's hard
to muster up any enthusiasm for writing up the semantics unless you're
willing to show some sign that you might modify the PEP as a result.
I'm not talking about rewriting your PEP to be a "deferred evaluation"
PEP, but simply to modify it to make it more compatible with the
future that the "deferred evaluation" people imagine.

On the other hand, if the "deferred evaluation" supporters genuinely
have nothing to offer other than "we don't want this PEP *at all*
because what we have right now is sufficient in the short term, and
longer term maybe something else (deferred evaluation being the
possibility we can think of right now) will provide a different
solution" then that's also OK. It's just a -1 vote, and should be
recorded in the PEP as such - "A number of contributors on
python-ideas were against this proposal because they didn't believe it
offered enough benefit over the status quo, and they preferred to wait
for a more general solution such as deferred evaluation (on the basis
of the Zen "never is often better than right now")". That can still go
in the "rejected ideas" section, under a heading of "Do Nothing".

But unless we can reduce the level of conflict here, we're never going
to know which alternative the deferred evaluation supporters want, and
it won't be possible to accurately represent their views in the PEP.
Which is bad for them (as they'll feel ignored) and for you (as your
PEP won't fairly represent the views of the people who contributed to
the discussion).

Paul

PS To be clear, my objections to the PEP aren't based on deferred
evaluation. So I'm an impartial 3rd party on this matter. I *do* have
problems with the PEP, so I have an interest in seeing the PEP fairly
reflect the lack of consensus, and accurately represent the concerns
people are raising, but I don't have a preference for any specific
outcome in the matter of deferred evaluation.
___
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/PLQRTPEVRNU5VGVCRXDUV3ERSFX37RLF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread Chris Angelico
On Tue, 21 Jun 2022 at 18:15, Paul Moore  wrote:
> I'm not talking about a "full and detailed specification". That's
> *still* more than is needed for a valid debate (at this point). But
> what *is* needed is a more complete explanation of how deferred
> evaluation would work, and some plausible (not set in stone, just
> plausible) syntax. With that, it would be possible to write down two
> versions of the same code and judge between them. We've not yet had a
> sufficiently clear (IMO) definition of the semantics of deferred
> evaluation yet (or if we have, it's been lost in the arguments), and
> it would help a lot if someone could provide one. I'm thinking
> specifically about the rules for variable capture, scoping,
> interaction with assignment expressions in terms of introducing names,
> etc., as well as how evaluation is "triggered" and what ability there
> is to explicitly say "evaluate this now".
>

That's what I mean by a full specification. Even without code, that
would be enough to start talking about it. But those arguing "don't go
for lazy evaluation, go for deferreds" don't seem to want to actually
push that proposal forward.

That's why I call it vapourware.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-21 Thread Paul Moore
On Tue, 21 Jun 2022 at 06:27, Chris Angelico  wrote:
>
> Okay, here's a compromise.
>
> Go and write a full and detailed specification of the Python-visible
> semantics of deferred evaluation objects, including how they would be
> used to implement late-bound argument defaults.

I'm going to ignore all the rhetoric here, as it's not helpful. I
understand that you're frustrated, and that you feel like you're not
getting your point across. Part of that (IMO) is *because* you're
getting too frustrated, and so not explaining your point well. This is
a case in point.

Deferred evaluation doesn't need to be implemented to be a valid
counter-proposal. Your repeated demands that someone produce an
implementation are a distraction, allowing people to argue that you're
wrong on that point, while ignoring the more important point. Which is
that we don't really have a definition of how deferred evaluation
would work.

I'm not talking about a "full and detailed specification". That's
*still* more than is needed for a valid debate (at this point). But
what *is* needed is a more complete explanation of how deferred
evaluation would work, and some plausible (not set in stone, just
plausible) syntax. With that, it would be possible to write down two
versions of the same code and judge between them. We've not yet had a
sufficiently clear (IMO) definition of the semantics of deferred
evaluation yet (or if we have, it's been lost in the arguments), and
it would help a lot if someone could provide one. I'm thinking
specifically about the rules for variable capture, scoping,
interaction with assignment expressions in terms of introducing names,
etc., as well as how evaluation is "triggered" and what ability there
is to explicitly say "evaluate this now".

> Go and actually do some real work on your pet feature, instead of
> using the vapourware to try to shut down the one I've been working on.

This is rhetoric again. Asking for more concrete examples of the
proposed alternative is reasonable. Getting frustrated when they are
not provided is understandable, but doesn't help. Calling the proposed
alternative "vapourware" just doubles down on the uncompromising
"implement it or I'll ignore you" stance. And replying with
increasingly frustrated posts that end up at a point where people like
me can't even work out how we'd go looking to see whether anyone *had*
provided concrete examples of deferred evaluation just makes things
worse. All of which could have been avoided by simply including an
early argument posted here in the PEP, under rejected alternatives,
with a link to the post and a statement that "this was proposed as an
alternative, but there's not enough detail provided to confirm how it
would replace the existing proposal". Then anyone who disagrees has a
clear understanding of what you want, and how to provide it.

> Once again, you're getting very very close to being killfiled.

This whole discussion is close to that point for me. But believe it or
not, I still have a vague hope that the proposal can be strengthened
by people working together, rather than just ending up with a "this is
what I think, take it or leave it" PEP.

Paul
___
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/LZJF4P77YCTX5TM7JJ4VW64JD4DDTBN2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Chris Angelico
On Tue, 21 Jun 2022 at 15:48, Brendan Barnwell  wrote:
>
> On 2022-06-20 22:26, Chris Angelico wrote:
> > Okay, here's a compromise.
> >
> > Go and write a full and detailed specification of the Python-visible
> > semantics of deferred evaluation objects, including how they would be
> > used to implement late-bound argument defaults.
> >
> > Go and actually do some real work on your pet feature, instead of
> > using the vapourware to try to shut down the one I've been working on.
> >
> > Go and actually do something useful instead of just arguing that "it
> > must be possible".
>
> I'm not the person you're replying to, but just a reminder here: there
> is one alternative proposal that already has a fully functioning
> implementation, namely the current behavior.  Your arguments against the
> deferred-evaluation proposal seem to constantly be reiterating that
> there is no concrete deferred-evaluation proposal.  You are right.  But
> your arguments also seem to be insinuating that if there is no such
> proposal, then opposition to the PEP is somehow misguided, and that is
> incorrect.  There doesn't need to be any concrete alternative proposal
> other than "leave everything as it is and wait until we think of
> something better".
>
> It is perfectly valid to oppose your PEP even on the basis that maybe 
> a
> deferred-evaluation proposal has a remote possibility of being better in
> the future --- because it is perfectly valid to oppose your PEP even if
> such a proposal has NO possibility of being better in the future.  There
> is no urgency or need for the behavior described in your PEP.  I am fine
> with the current behavior of Python in this regard.  It is not necessary
> to provide any alternative proposal, concrete or handwavy, to argue that
> the PEP is a bad idea.  I believe the PEP is a bad idea because the
> current behavior of Python is actually better than what it would be if
> the PEP were adopted.  I believe it is better to wait until we think of
> a better idea than to implement this PEP, and, if we never think of a
> better idea, then never change the existing argument-default behavior of
> Python.

I have laid out, multiple times, how a deferred evaluation feature is
completely distinct from late-bound argument defaults. So have others.
Steven continues to assert that, just because it MIGHT be possible to
use them in the implementation, we should stop working on this and
start working on that. He would, of course, be very welcome to work on
deferred evaluation himself, but he chooses to hide behind his own
ignorance of C to avoid doing any such work, and then still argues
that we should stop working on this because, in his opinion solely, it
would be more useful to have deferred evaluation.

And then he calls me a liar for saying in the PEP the same thing that
I've been saying here, yet he won't even write up a full specification
for deferred evaluation.

You are welcome to dislike the PEP on the basis that the existing
language is better than it would be with this feature. I personally
disagree, but that's what opinions are. But to object on the mere
basis that something MIGHT, despite demonstrated evidence, be better?
That is unfair and unhelpful.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Brendan Barnwell

On 2022-06-20 22:26, Chris Angelico wrote:

Okay, here's a compromise.

Go and write a full and detailed specification of the Python-visible
semantics of deferred evaluation objects, including how they would be
used to implement late-bound argument defaults.

Go and actually do some real work on your pet feature, instead of
using the vapourware to try to shut down the one I've been working on.

Go and actually do something useful instead of just arguing that "it
must be possible".


	I'm not the person you're replying to, but just a reminder here: there 
is one alternative proposal that already has a fully functioning 
implementation, namely the current behavior.  Your arguments against the 
deferred-evaluation proposal seem to constantly be reiterating that 
there is no concrete deferred-evaluation proposal.  You are right.  But 
your arguments also seem to be insinuating that if there is no such 
proposal, then opposition to the PEP is somehow misguided, and that is 
incorrect.  There doesn't need to be any concrete alternative proposal 
other than "leave everything as it is and wait until we think of 
something better".


	It is perfectly valid to oppose your PEP even on the basis that maybe a 
deferred-evaluation proposal has a remote possibility of being better in 
the future --- because it is perfectly valid to oppose your PEP even if 
such a proposal has NO possibility of being better in the future.  There 
is no urgency or need for the behavior described in your PEP.  I am fine 
with the current behavior of Python in this regard.  It is not necessary 
to provide any alternative proposal, concrete or handwavy, to argue that 
the PEP is a bad idea.  I believe the PEP is a bad idea because the 
current behavior of Python is actually better than what it would be if 
the PEP were adopted.  I believe it is better to wait until we think of 
a better idea than to implement this PEP, and, if we never think of a 
better idea, then never change the existing argument-default behavior of 
Python.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
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/FTC2N3APMR3YUBJYAOEIWTHRL4HXNTWX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Piotr Duda
wt., 21 cze 2022 o 05:20 Steven D'Aprano  napisał(a):

> The point is, Rob thought (and possibly still does, for all I know) that
> lazy evaluation is completely orthogonal to late-bound defaults. The PEP
> makes that claim too, even though it is not correct. With a couple of
> tweaks that we have to do anyway, and perhaps a change of syntax (and
> maybe not even that!) we can get late-bound defaults *almost* for free
> if we had lazy evaluation.

That depends of lazy evaluation spec, if lazy expression would ever
become a thing in python, it may be defined to have syntax like `lazy
` which would be rough equivalent off `LazyObject(lambda:
)` that would evaluate that lambda at most once, plus some
interpreter tweaks to make LazyObject transparent to python code.

so for this code (`??` replaced with different combination of
early/late and not lazy/lazy)

```
x = []

def f(x, y, z ?? len(x)):
  x.append(y)
  print(z, end = ' ')

x.append(0)
f([1, 2, 3], 4)
x.append(0)
f([1, 2, 3, 4], 4)
```

I expect that
for `??` = `=` I get `0 0 `
for `??` = `=>` I get `3 4 `
for `??` = `= lazy` I get `1 1`
for '??' = `=> lazy` I get `4 5 `

That would be completely orthogonal.
___
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/GZ2OCWGI67FTZGTCNHHYAXB7Y54LBTPY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Chris Angelico
On Tue, 21 Jun 2022 at 13:17, Steven D'Aprano  wrote:
>
> On Tue, Jun 21, 2022 at 12:13:08AM +1000, Chris Angelico wrote:
>
> > Nice analogy. It doesn't hold up.
> >
> > Consider this function:
> >
> > def f(stuff, max=>len(stuff)):
> > stuff.append(1)
> > print(max)
> >
> > f([1,2,3])
> >
> > How would you use lazy evaluation to *guarantee* the behaviour here?
>
> By "the behaviour" I presume you want `max` evaluated before the body of
> the function is entered, rather than at its point of use.
>
> Same way your implementation does: ensure that the interpreter
> fully evaluates `max` before entering the body of the function.

YES! Which means that guess what! It's NOT the same as having a
default which is a deferred evaluation object! It would be *buggy
behaviour* if you set the default to be a deferred evaluation object,
and the interpreter evaluated it on entering the body.

> > The only way I can imagine doing it is basically the same as I'm
> > doing: that late-bound argument defaults *have special syntax and
> > meaning to the compiler*. If they were implemented with some sort of
> > lazy evaluation object, they would need (a) access to the execution
> > context, so you can't just use a function;
>
> Obviously you can't just compile the default expression as a function
> *and do nothing else* and have late bound defaults magically appear from
> nowhere.
>
> Comprehensions are implemented as functions. Inside comprehensions, the
> walrus operator binds to the caller's scope, not the comprehension scope.
>
> >>> def frob(items):
> ... thunk = ((w:=len(items)) for x in (None,))
> ... next(thunk)
> ... return ('w' in locals(), w)
> ...
> >>> frob([1, 2, 3, 4, 5])
> (True, 5)
>
> That seems to be exactly the behaviour needed for lazy evaluation
> thunks, except of course we don't need all the other goodies that
> generators provide (e.g. send and throw methods).

GO AND IMPLEMENT IT. I'm done arguing this. Write the code. You'll
find it's a LOT more problematic than you claim.

> One obvious difference is that currently if we moved that comprehension
> into the function signature, it would use the `items` from the
> surrounding scope (because of early binding). It has to be set up in
> such a way that items comes from the correct scope too.
>
> If we were willing to give up fast locals, I think that the normal LEGB
> lookup will do the trick. That works for locals inside classes, so I
> expect it should work here too.

I wouldn't want to give up fast locals.

> > (b) guaranteed evaluation on function entry,
>
> If that's the behaviour that people prefer, sure. Functions would need
> to know which parameters were:
>
> 1. defined with a lazy default;
> 2. and not passed an argument by the caller (i.e. actually using
>the default)
>
> and for that subset of parameters, evaluate them, before entering the
> body of the function. That's kinda what you already do, isn't it?

But what if you wanted the default to actually be a deferred
evaluation object? BAM, buggy behaviour, according to your spec.

> > (c) the ability to put it in the function header.
>
> Well sure. But if we have syntax for a lazily evaluated expression it
> would be an expression, right? So we can put it anywhere an expression
> can go. Like parameter defaults in a function header.

Yes. See? You could do it as a completely separate proposal, like
we've been saying.

> The point is, Rob thought (and possibly still does, for all I know) that
> lazy evaluation is completely orthogonal to late-bound defaults. The PEP
> makes that claim too, even though it is not correct. With a couple of
> tweaks that we have to do anyway, and perhaps a change of syntax (and
> maybe not even that!) we can get late-bound defaults *almost* for free
> if we had lazy evaluation.

GO AND WRITE THE CODE.

> That suggests that the amount of work to get *both* is not that much
> more than the work needed to get just one. Why have a car that only
> drives to the mall on Thursdays when you can get a car that can drive
> anywhere, anytime, and use it to drive to the mall on Thursday as well?

GO AND WRITE THE CODE.

> > Please stop arguing this point. It is a false analogy and until you
> > can demonstrate *with code* that there is value in doing it, it is a
> > massive red herring.
>
> You can make further debate moot at any point by asking Python-Dev for a
> sponsor for your PEP as it stands right now. If you think your PEP is
> as strong as it can possibly be, you should do that.
>
> (You probably want to fix the broken ReST first.)
>
> Chris, you have been involved in the PEP process for long enough, as
> both a participant of discussions and writer of PEPs, that you know damn
> well that there is no requirement that all PEPs must have a working
> implementation before being accepted, let alone being *considered* by
> the community.
>
> Yes, we're all very impressed that you are a competent C programmer who
> can 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Chris Angelico
On Tue, 21 Jun 2022 at 13:07, Steven D'Aprano  wrote:
>
> On Tue, Jun 21, 2022 at 03:15:32AM +0100, Rob Cliffe wrote:
>
> > Why do people keep obscuring the discussion of a PEP which addresses
> > Problem A by throwing in discussion of the (unrelated) Problem B?
> > (Chris, and I, have stated, ad nauseam, that these *are* unrelated
> > problems.
>
> Chris says:
>
> "Even if Python does later on grow a generalized lazy evaluation
> feature, it will only change the *implementation* of late-bound
> argument defaults, not their specification."
>
> So you are mistaken that they are unrelated.
>

*facepalm*

I'm not offering you a way to put C code in your Python function defaults.

However, there is a large amount of C code in the implementation of
them, at least in my reference implementation.

So I guess the features of late-bound defaults and C code in function
defaults aren't unrelated either, and I should stop working on this
and start working on that.

Seriously? Are you unable to distinguish implementation from
specification? What are you even doing on this mailing list?

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Steven D'Aprano
On Tue, Jun 21, 2022 at 12:13:08AM +1000, Chris Angelico wrote:

> Nice analogy. It doesn't hold up.
> 
> Consider this function:
> 
> def f(stuff, max=>len(stuff)):
> stuff.append(1)
> print(max)
> 
> f([1,2,3])
> 
> How would you use lazy evaluation to *guarantee* the behaviour here?

By "the behaviour" I presume you want `max` evaluated before the body of 
the function is entered, rather than at its point of use.

Same way your implementation does: ensure that the interpreter 
fully evaluates `max` before entering the body of the function.


> The only way I can imagine doing it is basically the same as I'm
> doing: that late-bound argument defaults *have special syntax and
> meaning to the compiler*. If they were implemented with some sort of
> lazy evaluation object, they would need (a) access to the execution
> context, so you can't just use a function; 

Obviously you can't just compile the default expression as a function 
*and do nothing else* and have late bound defaults magically appear from 
nowhere.

Comprehensions are implemented as functions. Inside comprehensions, the 
walrus operator binds to the caller's scope, not the comprehension scope.

>>> def frob(items):
... thunk = ((w:=len(items)) for x in (None,))
... next(thunk)
... return ('w' in locals(), w)
... 
>>> frob([1, 2, 3, 4, 5])
(True, 5)

That seems to be exactly the behaviour needed for lazy evaluation 
thunks, except of course we don't need all the other goodies that 
generators provide (e.g. send and throw methods).

One obvious difference is that currently if we moved that comprehension 
into the function signature, it would use the `items` from the 
surrounding scope (because of early binding). It has to be set up in 
such a way that items comes from the correct scope too.

If we were willing to give up fast locals, I think that the normal LEGB 
lookup will do the trick. That works for locals inside classes, so I 
expect it should work here too.


> (b) guaranteed evaluation on function entry,

If that's the behaviour that people prefer, sure. Functions would need 
to know which parameters were:

1. defined with a lazy default;
2. and not passed an argument by the caller (i.e. actually using 
   the default)

and for that subset of parameters, evaluate them, before entering the 
body of the function. That's kinda what you already do, isn't it?

One interesting feature here is that you don't have to compile the 
default expressions into the body of the function. You can stick them in 
the code object, as distinct, introspectable thunks with a useful repr. 
Potentially, the only extra code that needs go inside the function body 
is a single byte-code to instantiate the late-bound defaults.

Even that might not need to go in the function body, it could be part of 
the CALL_FUNCTION and CALL_FUNCTION_KW op codes (or whatever we use).


> (c) the ability to put it in the function header.

Well sure. But if we have syntax for a lazily evaluated expression it 
would be an expression, right? So we can put it anywhere an expression 
can go. Like parameter defaults in a function header.

The point is, Rob thought (and possibly still does, for all I know) that 
lazy evaluation is completely orthogonal to late-bound defaults. The PEP 
makes that claim too, even though it is not correct. With a couple of 
tweaks that we have to do anyway, and perhaps a change of syntax (and 
maybe not even that!) we can get late-bound defaults *almost* for free 
if we had lazy evaluation.

That suggests that the amount of work to get *both* is not that much 
more than the work needed to get just one. Why have a car that only 
drives to the mall on Thursdays when you can get a car that can drive 
anywhere, anytime, and use it to drive to the mall on Thursday as well?

> Please stop arguing this point. It is a false analogy and until you
> can demonstrate *with code* that there is value in doing it, it is a
> massive red herring.

You can make further debate moot at any point by asking Python-Dev for a 
sponsor for your PEP as it stands right now. If you think your PEP is 
as strong as it can possibly be, you should do that.

(You probably want to fix the broken ReST first.)

Chris, you have been involved in the PEP process for long enough, as 
both a participant of discussions and writer of PEPs, that you know damn 
well that there is no requirement that all PEPs must have a working 
implementation before being accepted, let alone being *considered* by 
the community.

Yes, we're all very impressed that you are a competent C programmer who 
can write an initial implementation of your preferred design. But your 
repeated gate-keeping efforts to shut down debate by wrongly insisting 
that only a working implementation may be discussed is completely out of 
line, and I think you know it.

Being a C programmer with a working knowledge of the CPython internals 
is not, and never has been, a prerequisite for 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Steven D'Aprano
On Tue, Jun 21, 2022 at 03:15:32AM +0100, Rob Cliffe wrote:

> Why do people keep obscuring the discussion of a PEP which addresses 
> Problem A by throwing in discussion of the (unrelated) Problem B?
> (Chris, and I, have stated, ad nauseam, that these *are* unrelated 
> problems.

Chris says:

"Even if Python does later on grow a generalized lazy evaluation
feature, it will only change the *implementation* of late-bound
argument defaults, not their specification."

So you are mistaken that they are unrelated.

Chris could end this debate (and start a whole new one!) by going to the 
Python-Dev mailing list and asking for a sponsor, and if he gets one, 
for the Steering Council to make a ruling on the PEP. He doesn't *need* 
consensus on Python-Ideas. (Truth is, we should not expect 100% 
agreement on any new feature.)

But any arguments, questions and criticisms here which aren't resolved 
will just have to be re-hashed when the core devs and the Steering 
Council read the PEP. They can't be swept under the carpet.


-- 
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/2NAYYR4YX33KRFH5NH3RNHXXTNX2OVSS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Rob Cliffe via Python-ideas

On 18/06/2022 15:51, Stephen J. Turnbull wrote:

  > This raises another choice: should lazy defaults be evaluated before
  > entering the body of the function, or at the point where the parameter
  > is used? Which would be more useful?



Both are potentially useful.
Yes, both *ARE* potentially useful. *ABSOLUTELY*.  I don't think anyone 
would deny that.  Certainly not I.
Let's call "I want late-bound defaults and Python doesn't have them" 
Problem A.
Let's call "I want my default value not to be evaluated until needed" 
Problem B.
(Of course, you may not consider either to be a problem, but let's 
assume that you think that at least one of them is.)

Chris is offering a PEP and an implementation which addresses Problem A.
If Problem B is a problem for you, you can (currently) use a sentinel 
value, and explicitly evaluate the default when you want it.  Not so 
terrible.  In fact arguably, more often than not, better, because it's 
explicit.  And more flexible (you can evaluate a different expression, 
or in a different scope, in different places in the function body).  
Chris/PEP 671 is not attempting to provide a better way of doing that.  
He is not offering Deferred Evaluation Objects (DEOs).  Maybe in 5 years 
or so someone will  offer an implementation of that, and everyone can be 
happy. 
Meanwhile, *Chris is offering a solution of Problem A*.  He is *NOT 
addressing Problem B* - someone else is welcome to try that.
Let's be honest: PEP 671 does not allow you to do anything you can't 
already.  What is adds is some more convenience, some more concision, 
and arguably (and I *would* argue, in appropriate cases) some more 
readability.


Why do people keep obscuring the discussion of a PEP which addresses 
Problem A by throwing in discussion of the (unrelated) Problem B?
(Chris, and I, have stated, ad nauseam, that these *are* unrelated 
problems.  If you don't agree, I can only ask you to consider the 
implementations necessary to solve each.  If that doesn't change your 
mind, I have to throw my hands in the air and say "We'll have to agree 
to differ".)


*Surely solving one "problem" is better than dithering about which 
"problem" to solve.*


I've been accused of trying to censor this thread, but really - I'm just 
frustrated when people are invited to comment on PEP 671, and they don't 
comment on PEP 671, but on something else.


BTW Thank you Stephen Turnbull, for your measured comments to this thread.
Best wishes
Rob Cliffe___
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/GOI65D2YBUYIYOXX2QK3MTRLI2VOBG3R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Chris Angelico
On Tue, 21 Jun 2022 at 10:13, Rob Cliffe via Python-ideas
 wrote:
>
> On 19/06/2022 04:42, David Mertz, Ph.D. wrote:
>
> On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe
>>
>> Sorry again, but IMO discussing any model except one where late-bound 
>> defaults are evaluated at function call time is just adding FUD.
>
>
> It's definitely rude to repeatedly state that anyone who's opinion is 
> different from yours is "adding FUD" and doesn't belong in the thread.
>
> I was not talking about people whose opinion was different from mine.  I was 
> talking about people who obscured the discussion of a proposal by talking 
> about a different proposal.  And that, IMO, would be rude if it were done 
> deliberately, though I accept that it wasn't.
>
>
> The topic of "late binding in function signatures"  simply isn't *orthogonal* 
> to "late binding in the general sense." Yes, they are distinct, but very 
> closely adjacent.
>
> We disagree about that.  Please consider the *IMPLEMENTATIONS* of each.  I 
> respectfully suggest that you may conclude that they are not so close after 
> all.
>
> PS  In my support may I quote from a post from Chris:
>
> [Steven D'Aprano] Chris may choose to reject this generalised lazy evaluation 
> idea, but if
> so it needs to go into a Rejected Ideas section. Or he may decide that
> actually having a generalised lazy evaluation idea is *brilliant* and
> much nicer than making defaults a special case.
>
> [Chris] It's an almost completely orthogonal proposal. I used to have a
> reference to it in the PEP but removed it because it was unhelpful.
>

Since it appears to matter to people, I've readded a mention of it.
It's just freshly pushed so you might not see it instantly, but within
a few minutes (or browse the source code on GitHub), you should see
deferred evaluation mentioned in PEP 671.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Rob Cliffe via Python-ideas

On 19/06/2022 04:42, David Mertz, Ph.D. wrote:

On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe

Sorry again, but IMO discussing any model except one where
late-bound defaults are evaluated at function call time is just
adding FUD.


It's definitely rude to repeatedly state that anyone who's opinion is 
different from yours is "adding FUD" and doesn't belong in the thread.
I was not talking about people whose opinion was different from mine.  I 
was talking about people who obscured the discussion of a proposal by 
talking about a different proposal.  And that, IMO, would be rude if it 
were done deliberately, though I accept that it wasn't.



The topic of "late binding in function signatures"  simply isn't 
*orthogonal* to "late binding in the general sense." Yes, they are 
distinct, but very closely adjacent.
We disagree about that. *Please consider the */_**IMPLEMENTATIONS**_/*of 
each.  I respectfully suggest that you may conclude that they are not so 
close after all.


*PS  In my support may I quote from a post from Chris:

[Steven D'Aprano] Chris may choose to reject this generalised lazy 
evaluation idea, but if

so it needs to go into a Rejected Ideas section. Or he may decide that
actually having a generalised lazy evaluation idea is *brilliant* and
much nicer than making defaults a special case.

[Chris] It's an almost completely orthogonal proposal. I used to have a
reference to it in the PEP but removed it because it was unhelpful.


Rob Cliffe___
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/LZVHCT42ISSJSOHTC6KAENAZJD33C4ZT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Rob Cliffe via Python-ideas

On 19/06/2022 04:42, David Mertz, Ph.D. wrote:

On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe

Sorry again, but IMO discussing any model except one where
late-bound defaults are evaluated at function call time is just
adding FUD.


It's definitely rude to repeatedly state that anyone who's opinion is 
different from yours is "adding FUD" and doesn't belong in the thread.
I was not talking about people whose opinion was different from mine.  I 
was talking about people who obscured the discussion of a proposal by 
talking about a different proposal.  And that, IMO, would be rude if it 
were done deliberately, though I accept that it wasn't.


Stephen, and Steven, and Paul, and I all perfectly well understand 
what "evaluated at function call time" means.
I should jolly well hope so too.  I certainly did not intend to suggest 
that any of you or anyone else do not understand it.  And I can't see 
anything in any of my posts that suggests that I did intend that.  Do 
you think that I did?  If so, why?  (Please quote where appropriate.)  
If I did somehow suggest that, I sincerely apologise.


It's a way to spell `if arg is sentinel: arg = ...` using slightly 
fewer characters, and moving an expression from the body to the signature.
Yes, if you want to simplify a bit, basically it is.  But it avoids the 
trap of the sentinel value being a possible parameter value. And it 
would answer a number of Stack Overflow posts on the lines of "Why 
doesn't this work [as I expected]?"  I don't think that anyone, 
including Chris, would say that it allows you to do something that you 
can't do already (though I might be wrong, but I believe Python is 
already Turing-complete ).  The virtue of the PEP is that it adds some 
convenience and some clarity and some concision. (Concision *is* a 
virtue, ceteribus paribus - which often they are not.)


I'm still -1 because I don't think the purpose alone is close to worth 
the cost of new syntax... And especially not using sigils that are 
confusing to read in code.
You complain about sigils.  Do you accept my point that more **words** 
(and words that can, perhaps a trifle unkindly, be classed as 
boilerplate rather than genuine content) can also make stuff harder to read?


The topic of "late binding in function signatures"  simply isn't 
*orthogonal* to "late binding in the general sense." Yes, they are 
distinct, but very closely adjacent.
We disagree about that. *Please consider the */_**IMPLEMENTATIONS**_/*of 
each.  I respectfully suggest that you may conclude that they are not so 
close after all.*

Best wishes
Rob Cliffe___
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/G734UNUDJLGFV362LDE4WIUI7AL4DWEA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Chris Angelico
On Mon, 20 Jun 2022 at 21:19, Steven D'Aprano  wrote:
> > (4) The guarantee that a late-bound default WILL be executed at
> > function call time, can be useful, even essential (it could be
> > time-dependent or it could depend on the values - default or otherwise -
> > of other parameters whose values might be changed in the function
> > body).
>
> Okay. But a generalised lazy evaluation mechanism can be used to
> implement PEP 671 style evaluation.
>
> Let me see if I can give a good analogy... generalised lazy evaluation
> is like having a car that can drive anywhere there is a road, at any
> time of the day or night. Late-bound defaults is like having a car that
> can only drive to the local mall and back, and only on Thursdays.
>
> That's okay if you want to drive to the local mall on Thursdays, but if
> you could only have one option, which would be more useful?
>

Nice analogy. It doesn't hold up.

Consider this function:

def f(stuff, max=>len(stuff)):
stuff.append(1)
print(max)

f([1,2,3])

How would you use lazy evaluation to *guarantee* the behaviour here?

The only way I can imagine doing it is basically the same as I'm
doing: that late-bound argument defaults *have special syntax and
meaning to the compiler*. If they were implemented with some sort of
lazy evaluation object, they would need (a) access to the execution
context, so you can't just use a function; (b) guaranteed evaluation
on function entry, regardless of when - if ever - it gets referred to;
and (c) the ability to put it in the function header. The only one of
those that overlaps with lazy evaluation is (c).

Please stop arguing this point. It is a false analogy and until you
can demonstrate *with code* that there is value in doing it, it is a
massive red herring.

Even if Python does later on grow a generalized lazy evaluation
feature, it will only change the *implementation* of late-bound
argument defaults, not their specification.

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/2KA7SZAEWNH55HNEMK6H3UHWC5TZTS2Y/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Steven D'Aprano
On Sun, Jun 19, 2022 at 02:21:16AM +0100, Rob Cliffe via Python-ideas wrote:

> Sorry, but I think all this talk about lazy evaluation is a big red herring:
>     (1) Python is not Haskell or Dask.

Python is not Haskell, but we stole list comprehensions and pattern 
matching from it. Python steals concepts from many languages.

And Python might not be Dask, but Dask is Python.

https://www.dask.org/


>     (2) Lazy evaluation is something Python doesn't have,

Python has lazily evaluated sequences (potentially infinite sequences) 
via generators and iterators. We also have short-circuit evaluation, 
which is a form of lazy evaluation. There may be other examples as well.

We may also get lazy importing soon:

https://peps.python.org/pep-0690/

At last one of Python's direct competitors in the scientific community, 
R, has lazy evaluation built in.


> and would be 
> a HUGE amount of work for Chris (or anyone) to implement

I don't know how hard it is to implement lazy evaluation, but speaking 
with the confidence of the ignorant, I expect not that hard if you don't 
care too much about making it super efficient. A lazy expression, or 
thunk, is basically just a zero-argument function that the interpreter 
knows to call.

If you don't care about getting Haskell levels of efficiency, that's 
probably pretty simple to implement.

Rewriting Python from the ground up to be completely lazy like Haskell 
would be a huge amount of work. Adding some sort of optional and 
explicit laziness, like R and F# and other languages use, would possibly 
be little more work than just adding late-bound defaults.

Maybe.


> And in the unlikely event 
> that Chris (or someone) DID implement it, I expect there would be a 
> chorus of "No, no, that's not how (I think) it should work at all".

The idea is that you plan your feature's semantics before writing an 
implementation. Even if you plan to "write one to throw away", and do 
exploratory coding, you should still have at least a vague idea of the 
desired semantics before you write a single line of code.


>     (3)  Late-bound defaults that are evaluated at function call time, 
> as per PEP 671, give you an easy way of doing something that at present 
> needs one of a number of workarounds (such as using sentinel values) all 
> of which have their drawbacks or awkward points.

Yes, we've read the PEP thank you :-)

Late-bound defaults also have their own drawbacks. It is not a question 
of whether this PEP has any advantages. It clearly does! The question is 
where the balance of pros versus cons falls.


>     (4) The guarantee that a late-bound default WILL be executed at 
> function call time, can be useful, even essential (it could be 
> time-dependent or it could depend on the values - default or otherwise - 
> of other parameters whose values might be changed in the function 
> body).

Okay. But a generalised lazy evaluation mechanism can be used to 
implement PEP 671 style evaluation.

Let me see if I can give a good analogy... generalised lazy evaluation 
is like having a car that can drive anywhere there is a road, at any 
time of the day or night. Late-bound defaults is like having a car that 
can only drive to the local mall and back, and only on Thursdays.

That's okay if you want to drive to the local mall on Thursdays, but if 
you could only have one option, which would be more useful?

> Sure, I appreciate that there are times when you might want to 
> defer the evaluation because it is expensive and might not be needed, but:
>     (5) If you really want deferred evaluation of a parameter default, 
> you can achieve that by explicitly evaluating it, *at the point you want 
> it*, in the function body.  Explicit is better than implicit.

That's not really how lazy evaluation works or why people want it.

The point of lazy evaluation is that computations are transparently and 
automatically delayed until you actually need them. Lazy evaluation is 
kind of doing the same thing for CPUs as garbage collection does for 
memory. GC kinda sorta lets you pretend you have infinite memory (so 
long as you don't actually try to use it all at once...). Lazy 
evaluation kinda sorta lets you pretend your CPU is infinitely fast (so 
long as you don't try to actually do too much all at once).

If you think about the differences between generators and lists, that 
might help. A generator isn't really like a list that you just evaluate 
a few lines later. Its a completely different way of thinking about 
code, and often (but not always) better.


> IMO lazy evaluation IS a different, orthogonal proposal.

Late-bound defaults is a very small subset of lazy evaluation.

But yes, lazy evaluation is a different, bigger concept.


-- 
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 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-20 Thread Stephen J. Turnbull
@Chris

My bottom line, as I wrote before, is that even if this were
introduced, I probably will continue to default to

def foo(arg=None):
if arg is None:
arg = default

in my own code until I start seeing "def foo(arg=>default)" in a lot
of code I read.  Since Mailman generally supports about 4 Python
versions, that means I won't see it in Mailman until 2027 or so.

But I'm not George Bush to say "Read my lips: no new (syn)taxes!"

Unless somebody comes up with some new really interesting use case, I
think the suggestion somebody (sorry to somebody!) made earlier to
"Just Do It" and submit to the SC is the right one.  Both David and I
are convinced that there is value-added in late binding for new
mutables and defaults that are computed from actual arguments, even if
we're not convinced it's enough.  The proposal has plenty of fans, who
*are* convinced and *will* use it.  I don't see a prospect for that
new really interesting use case, at least not here on Python-Ideas,
the discussion is just variations on the same themes.  On the other
hand, a PEP under consideration may get a little more interest from
the Python-Dev crowd, and obviously the SC itself.  They may have use
cases or other improvements to offer.

"Now is better than never."  The SC will let you know if the companion
koan is applicable. ;-)

@Chris You may or may not want to read my variations on the themes. ;-)

Chris Angelico writes:

 > > In the numeric stuff, if I have:
 > >
 > > newarray = (A @ B) | (C / D) + (E - F)
 > >
 > >
 > > That's @, |, /, +, and -.  So 5 operators, and 25 "complexity
 > > points".  If I added one more operator, 36 "complexity points"
 > > seems reasonable.  And if I removed one of those operators, 16
 > > "complexity points" feels about right.
 > 
 > For my part, I would say that it's quite the opposite. This is three
 > parenthesized tokens, each of which contains two things combined in a
 > particular way. That's six 'things' combined in particular ways.
 > Cognitive load is very close to this version:
 > 
 > newarray = (A * B) + (C * D) + (E * F)

I don't have the studies offhand, but "7 plus or minus 2" is famous
enough, google that and you'll find plenty.  I'll bet you even find
"cognitive complexity of mathematical formulae" in the education
literature.  (And if not, we should sue all the Departments of
Education in the world for fraud. ;-)

I do have the words: "this is a sum of binary products".  This
basically reduces the cognitive complexity to two concepts plus a scan
of the list of variables.  Given that they're actually in alphabetical
order, "first variable is A" is enough to reproduce the expression.

That's much simpler than trying to describe David's 5-operator case
with any degree of specificity.  Or even just try to reproduce his
formula without a lot of effort to memorize it!  Also, just from the
regularity of the form and its expression as an algebraic formula, I
can deduce that almost certainly A, C, and E have the same type, and
B, D, and F have the same type, and very likely those two types are
the same.  Not so for the five-operator case, where I would be
surprised if less than 3 types were involved.

Of course, this type information is probably redundant.  I probably
remember not only the types, but lots of other attributes of A
through F.  But this kind of redundancy is good!  It reinforces my
understanding of the expression and the program that surrounds it.

 > even though this uses a mere two operators. It's slightly more, but
 > not multiplicatively so. (The exact number of "complexity points" will
 > depend on what A through F represent, but the difference between "all
 > multiplying and adding" and "five distinct operators" is only about
 > three points.)

That may be true for you, but it's definitely not true for my
economics graduate students.

 > > Sure, knowing what `hi` defaults to *could be useful*.  I'm sure
 > > if I used that function I would often want to know... and also
 > > often just assume the default is "something sensible."  I just
 > > don't think that "could be useful" as a benefit is nearly as
 > > valuable as the cost of a new sigil and a new semantics adding to
 > > the cognitive load of Python.
 > 
 > Yes, but "something sensible" could be "len(stuff)", "len(stuff)-1",
 > or various other things. Knowing exactly which of those will tell you
 > exactly how to use the function.

@David:  I find the "hi=len(stuff)" along with the "lst=[]" examples
fairly persuasive (maybe moves me to +/- 0).

@Chris:  It would be a lot more persuasive if you had a plausible
explicit list of "various other things".  Even "len(stuff) - 1" is
kind of implausible, given Python's consistent 0-based indexing
and closed-open ranges (yeah, I know some people like to use the
largest value in the range rather than the least upper bound not
in the range, but I consider that bad style in Python, and they
denote the same semantics).  

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread Chris Angelico
On Mon, 20 Jun 2022 at 05:02, David Mertz, Ph.D.  wrote:
>
> On Sun, Jun 19, 2022 at 2:24 PM Chris Angelico  wrote:
>>
>> > def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG): 
>> > ...
>>
>> Is there any value in not putting that into a global constant?
>
>
> Probably not.  I was just inventing an ad hoc example to show what I meant.  
> I didn't search any actual repos I work on for real-life examples.

Ah okay. Well, if that WERE a real example, I would recommend giving
it a name. (Also, it's probably going to end up using >= rather than
==, so that the verbosity of any function can be set to a minimum
level, so there'd be more complexity, thus making it even more useful
to make it some sort of constant.)

>>
>> Regardless, the @ operator is now available *everywhere* in Python. Does it 
>> quadratically increase cognitive load?
>
>
> Yeah, probably about that much.  Other than NumPy or closely related array 
> libraries, I don't know that many other uses. I think I saw something on PyPI 
> that used it as an email thing, where obviously it has some familiarity.  But 
> in that case, the lines it occurs on probably have no more than one or two 
> other sigils.
>
> In the numeric stuff, if I have:
>
> newarray = (A @ B) | (C / D) + (E - F)
>
>
> That's @, |, /, +, and -.  So 5 operators, and 25 "complexity points".  If I 
> added one more operator, 36 "complexity points" seems reasonable.  And if I 
> removed one of those operators, 16 "complexity points" feels about right.

For my part, I would say that it's quite the opposite. This is three
parenthesized tokens, each of which contains two things combined in a
particular way. That's six 'things' combined in particular ways.
Cognitive load is very close to this version:

newarray = (A * B) + (C * D) + (E * F)

even though this uses a mere two operators. It's slightly more, but
not multiplicatively so. (The exact number of "complexity points" will
depend on what A through F represent, but the difference between "all
multiplying and adding" and "five distinct operators" is only about
three points.)

So unless you have a study showing this, I would say we each have a
single data point - ourselves - and it's basically useless data.

>> In a function signature "def bisect(stuff, lo=0, hi=None)", you don't
>> know what the hi value actually defaults to. Even if it's obvious that
>> it is late-bound
>
>
> Sure, knowing what `hi` defaults to *could be useful*.  I'm sure if I used 
> that function I would often want to know... and also often just assume the 
> default is "something sensible."  I just don't think that "could be useful" 
> as a benefit is nearly as valuable as the cost of a new sigil and a new 
> semantics adding to the cognitive load of Python.
>

Yes, but "something sensible" could be "len(stuff)", "len(stuff)-1",
or various other things. Knowing exactly which of those will tell you
exactly how to use the function.

Would you say that knowing that lo defaults to 0 is useful
information? You could just have a function signature that merely says
which arguments are mandatory and which are optional, and force people
to use the documentation to determine the behaviour of omitted
arguments. If you accept that showing "lo=0" gives useful information
beyond simply that lo is optional, then is it so hard to accept that
"hi=>len(stuff)" is also immensely valuable?

> For example, it also "could be useful" to have syntax that indicated the 
> (expected) big-O complexity of that function.  But whatever that syntax was, 
> I really doubt it would be worth the extra complexity in the language vs. 
> just putting that info in the docstring.
>

That's true; there's always a lot more that could go into a function's
docstring than can fit into its signature. Perhaps, if it's of value
to your project, it would be useful to use a function decorator and
then redefine the return value annotation to (also or instead) inform
you of the complexity. But for information about a single argument,
the only useful place to put it is on the argument itself - either in
the signature, or in a duplicated block in the docstring. And function
defaults are a lot broader in value than algorithmic complexity, which
is irrelevant to a huge number of functions.

> Let's look at a function that has a lot of late-bound default arguments:
>
> pd.read_csv(
> filepath_or_buffer: 'FilePath | ReadCsvBuffer[bytes] | 
> ReadCsvBuffer[str]',
> sep=,
> delimiter=None,
> header='infer',
> names=,
> index_col=None,
> usecols=None,
> squeeze=None,
> prefix=,
> mangle_dupe_cols=True,
> dtype: 'DtypeArg | None' = None,
> engine: 'CSVEngine | None' = None,
> converters=None,
> true_values=None,
> false_values=None,
> skipinitialspace=False,
> skiprows=None,
> skipfooter=0,
> nrows=None,
> na_values=None,
> keep_default_na=True,
> na_filter=True,
> verbose=False,
> 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread David Mertz, Ph.D.
On Sun, Jun 19, 2022 at 2:24 PM Chris Angelico  wrote:

> > def frobnicate(data,
> verbose=os.environ.get('LEVEL')==loglevel.DEBUG): ...
>
> Is there any value in not putting that into a global constant?
>

Probably not.  I was just inventing an ad hoc example to show what I
meant.  I didn't search any actual repos I work on for real-life examples.


> Regardless, the @ operator is now available *everywhere* in Python. Does
> it quadratically increase cognitive load?
>

Yeah, probably about that much.  Other than NumPy or closely related array
libraries, I don't know that many other uses. I think I saw something on
PyPI that used it as an email thing, where obviously it has some
familiarity.  But in that case, the lines it occurs on probably have no
more than one or two other sigils.

In the numeric stuff, if I have:

newarray = (A @ B) | (C / D) + (E - F)


That's @, |, /, +, and -.  So 5 operators, and 25 "complexity points".  If
I added one more operator, 36 "complexity points" seems reasonable.  And if
I removed one of those operators, 16 "complexity points" feels about right.

In a function signature "def bisect(stuff, lo=0, hi=None)", you don't
> know what the hi value actually defaults to. Even if it's obvious that
> it is late-bound


Sure, knowing what `hi` defaults to *could be useful*.  I'm sure if I used
that function I would often want to know... and also often just assume the
default is "something sensible."  I just don't think that "could be useful"
as a benefit is nearly as valuable as the cost of a new sigil and a new
semantics adding to the cognitive load of Python.

For example, it also "could be useful" to have syntax that indicated the
(expected) big-O complexity of that function.  But whatever that syntax
was, I really doubt it would be worth the extra complexity in the language
vs. just putting that info in the docstring.

Let's look at a function that has a lot of late-bound default arguments:

pd.read_csv(
filepath_or_buffer: 'FilePath | ReadCsvBuffer[bytes] |
ReadCsvBuffer[str]',
sep=,
delimiter=None,
header='infer',
names=,
index_col=None,
usecols=None,
squeeze=None,
prefix=,
mangle_dupe_cols=True,
dtype: 'DtypeArg | None' = None,
engine: 'CSVEngine | None' = None,
converters=None,
true_values=None,
false_values=None,
skipinitialspace=False,
skiprows=None,
skipfooter=0,
nrows=None,
na_values=None,
keep_default_na=True,
na_filter=True,
verbose=False,
skip_blank_lines=True,
parse_dates=None,
infer_datetime_format=False,
keep_date_col=False,
date_parser=None,
dayfirst=False,
cache_dates=True,
iterator=False,
chunksize=None,
compression: 'CompressionOptions' = 'infer',
thousands=None,
decimal: 'str' = '.',
lineterminator=None,
quotechar='"',
quoting=0,
doublequote=True,
escapechar=None,
comment=None,
encoding=None,
encoding_errors: 'str | None' = 'strict',
dialect=None,
error_bad_lines=None,
warn_bad_lines=None,
on_bad_lines=None,
delim_whitespace=False,
low_memory=True,
memory_map=False,
float_precision=None,
storage_options: 'StorageOptions' = None,


I'd have to look through the implementation, but my guess is that quite a
few of the 25 late-bound defaults require calculations to set that take
more than one line of code.  I really don't WANT to know more than "this
parameter is calculated according to some logic, perhaps complex logic" ...
well, unless I think it pertains to something I genuinely want to
configure, in which case I'll read the docs.

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
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/MPDHT2IF5O32AECZKQSYW7AKV6QWGV3X/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread Chris Angelico
On Mon, 20 Jun 2022 at 03:06, David Mertz, Ph.D.  wrote:
>>
>> > I guess '>=' also looks "confusable", but it's far less common in 
>> > signatures, and the meaning is further away.
>>
>> It's no less valid than your other examples, nor less common (why
>> would you have "==" in a function signature, for instance?).
>
>
> I guess I probably use `==` more often in function calls and signatures, on 
> reflection.  In call, I use `==` quite often to pass some boolean switch 
> value, and `>=` much less often.  Obviously, I am aware that `>=` also 
> produces a boolean result, and YMMV on how often comparing for equality and 
> inequality expresses the flag you want.
>
> In signature, I'd really only use it, I reckon, as a "default default." E.g.
>
> def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG): ...
>
> This supposes I have an environmental setting for verbosity that I usually 
> want to use, but might override that on a particular call.

Okay. When it comes to finding causes for the difficulty of reading
your function signatures, I think this is a far greater one *in a
vacuum* than having support for late-bound defaults. Maybe it's not a
problem *for you* because you're accustomed to reading that as a
single token, but that can be true of any sequence.

Is there any value in not putting that into a global constant?

>>
>> > I think the cognitive complexity of a line with sigils is somewhere around 
>> > quadratic or cubic on the number of distinct sigils. But when several look 
>> > similar, it quickly tends toward the higher end. And when several have 
>> > related meanings, it's harder still to read.
>>
>> It shouldn't need to be. Once you know how expressions are built up, it 
>> should give linear complexity.
>
>
> I'm not talking about the big-O running time of some particular engine that 
> parses a BNF grammar here.  I'm talking about actual human brains, which work 
> differently.

Yes, and human brains are fine with adding more options, as long as
they work the same way that other options do.

> I don't have data for my quadratic and cubic guesses.  Just 40 years of my 
> own programming experience, and about the same amount of time watching other 
> programmers.
>
> It would be relatively easy to measure if one wanted to.  But it's a 
> cognitive psychology experiment.  You need to get a bunch of people in rooms, 
> and show them lots of code lines.  Then measure error rates and response 
> times in their answers.  That sort of thing.  The protocol for this 
> experiment would need to be specified more carefully, of course.  But it *is* 
> the kind of thing that can be measured in human beings.
>
> So my (very strong) belief is that a human being parsing a line with 5 sigils 
> in it will require MUCH MORE than 25% more effort than parsing a line with 4 
> sigils in it.  As in, going from 4 to 5 distinct sigils in the same line 
> roughly DOUBLES cognitive load.  Here the distinctness is important; it's not 
> at all hard to read:
>
> a + b + c + d + e + f + g + h + i

Okay. You run a test, and let's see how it goes. At the moment, all
you have is a single data point: yourself. Specifically, yourself with
all your current knowledge. I think it's a little biased. :)

>> Did the introduction of the @ (matrix multiplication) operator to
>> Python increase the language's complexity multiplicatively, or
>> additively? Be honest now: are your programs more confusing to read
>> because @ could have been *, because @ could have been +, because @
>> could have been ==, etc etc etc, or is it only that @ is one new
>> operator, additively with the other operators?
>
>
> I'm not sure how much you know about the background of this in the NumPy 
> world.  While other libraries have also now used that operator, NumPy was the 
> driving force.
>
> In the old days, if I wanted to do a matrix multiply, I would either do:
>
> A_matrix = np.matrix(A)
> B_matrix = np.matrix(B)
>
> result = A_matrix * B_matrix
>
> Or alternately:
>
> result = np.dot(A, B)
>
>
> Neither of those approaches are terrible, but in more complex expressions 
> where the dot product is only part of the expression, indeed `A @ B` reads 
> better.

Regardless, the @ operator is now available *everywhere* in Python.
Does it quadratically increase cognitive load?

>> > When I write an expression like 'a - b * c / d**e + f' that also has a 
>> > bunch of symbols. But they are symbols that:
>> >
>> > - look strongly distinct
>> > - have meanings familiar from childhood
>> > - have strongly different meanings (albeit all related to arithmetic)
>>
>> The double asterisk wasn't one that I used in my childhood, yet in
>> programming, I simply learned it and started using it. What happens is
>> that known concepts are made use of to teach others.
>
>
> I  didn't learn the double asterisk in school either.  That I had to learn in 
> programming languages.  I actually prefer those programming languages that 
> use `^` for 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread David Mertz, Ph.D.
>
> > I guess '>=' also looks "confusable", but it's far less common in
> signatures, and the meaning is further away.
>
> It's no less valid than your other examples, nor less common (why
> would you have "==" in a function signature, for instance?).
>

I guess I probably use `==` more often in function calls and signatures, on
reflection.  In call, I use `==` quite often to pass some boolean switch
value, and `>=` much less often.  Obviously, I am aware that `>=` also
produces a boolean result, and YMMV on how often comparing for equality and
inequality expresses the flag you want.

In signature, I'd really only use it, I reckon, as a "default default." E.g.

def frobnicate(data, verbose=os.environ.get('LEVEL')==loglevel.DEBUG):
...

This supposes I have an environmental setting for verbosity that I usually
want to use, but might override that on a particular call.


> > I think the cognitive complexity of a line with sigils is somewhere
> around quadratic or cubic on the number of distinct sigils. But when
> several look similar, it quickly tends toward the higher end. And when
> several have related meanings, it's harder still to read.
>
> It shouldn't need to be. Once you know how expressions are built up, it
> should give linear complexity.
>

I'm not talking about the big-O running time of some particular engine that
parses a BNF grammar here.  I'm talking about actual human brains, which
work differently.

I don't have data for my quadratic and cubic guesses.  Just 40 years of my
own programming experience, and about the same amount of time watching
other programmers.

It would be relatively easy to measure if one wanted to.  But it's a
cognitive psychology experiment.  You need to get a bunch of people in
rooms, and show them lots of code lines.  Then measure error rates and
response times in their answers.  That sort of thing.  The protocol for
this experiment would need to be specified more carefully, of course.  But
it *is* the kind of thing that can be measured in human beings.

So my (very strong) belief is that a human being parsing a line with 5
sigils in it will require MUCH MORE than 25% more effort than parsing a
line with 4 sigils in it.  As in, going from 4 to 5 distinct sigils in the
same line roughly DOUBLES cognitive load.  Here the distinctness is
important; it's not at all hard to read:

a + b + c + d + e + f + g + h + i


And in the weeds, the particular sigils involved (and even the font they're
rendered in) will make a difference too. As well it matters the "semantic
proximity" of the various operators. And other factors too I'm sure.

Did the introduction of the @ (matrix multiplication) operator to
> Python increase the language's complexity multiplicatively, or
> additively? Be honest now: are your programs more confusing to read
> because @ could have been *, because @ could have been +, because @
> could have been ==, etc etc etc, or is it only that @ is one new
> operator, additively with the other operators?
>

I'm not sure how much you know about the background of this in the NumPy
world.  While other libraries have also now used that operator, NumPy was
the driving force.

In the old days, if I wanted to do a matrix multiply, I would either do:

A_matrix = np.matrix(A)
B_matrix = np.matrix(B)

result = A_matrix * B_matrix

Or alternately:

result = np.dot(A, B)


Neither of those approaches are terrible, but in more complex expressions
where the dot product is only part of the expression, indeed `A @ B` reads
better.

And yes, expressions on NumPy arrays will often use a number of those
arithmetic operators I learned in grade school as well as `@`.  But
generally, the mathematics expressed in NumPy code is irreducible
complexity.  It's not necessarily easy to parse visually, but it *IS* the
underlying mathematics.


> > When I write an expression like 'a - b * c / d**e + f' that also has a
> bunch of symbols. But they are symbols that:
> >
> > - look strongly distinct
> > - have meanings familiar from childhood
> > - have strongly different meanings (albeit all related to arithmetic)
>
> The double asterisk wasn't one that I used in my childhood, yet in
> programming, I simply learned it and started using it. What happens is
> that known concepts are made use of to teach others.


I  didn't learn the double asterisk in school either.  That I had to learn
in programming languages.  I actually prefer those programming languages
that use `^` for exponentiation (in that one aspect, not overall more than
Python), because it's more reminiscent of superscript.

Is that simply because you already are familiar with those operators,
> or is there something inherently different about them? Would it really
> be any different?
>

It's a mixture of familiarity and actual visual distinctness.  `/` and `+`
really do just *look different*.  In contrast `:=` and `=` just really look
similar.

Then don't use it in a signature. That's fine. Personally, I've never
> used the "def 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread David Mertz, Ph.D.
On Sun, Jun 19, 2022, 12:02 PM Chris Angelico

> I've no idea what you mean by "sophistical" here. Please explain?
>

1.  of or characteristic of sophists or sophistry
2.  clever and plausible, but unsound and tending to mislead
a sophistical argument
3.  using sophistry

Plato's dialog _The Sophist_ is good background.
___
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/GH3TETOF4YHWGJ66FTJFNPLFKCUDCQR2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread Chris Angelico
On Mon, 20 Jun 2022 at 01:37, David Mertz, Ph.D.  wrote:
>
> Unfortunately,  in relation to this PEP, I find your arguments tend to be 
> sophistical. They ate not generally so in other threads,  but for whatever 
> reason your attachment to this has a different quality.
>

I've no idea what you mean by "sophistical" here. Please explain?

> There's an interesting point you raise though. You seem to feel that closely 
> related meanings should have similar looking sigils. I'm not sure my opinion 
> is *opposite *, but it's definitely more that subtly different semantics 
> should not be marked by easily visually confusable sigils.
>
> Under PEP 671, a single line of a function signature might contain '=', ':=', 
> '=>', '->', ':', and '=='. Obviously it can have other symbols as well. But 
> those are the ones the most blur into each other visually. 4 of them have 
> closely related meanings. You don't even need to be contrived to have such 
> examples.
>

Yes, but only some of those are actually part of the signature itself.
I mean, if you put a lambda function into the default value, you could
have even more colons:

def f(x:int=lambda x: x+1, y:object=(_default:=object())): ...

But that's just what happens when syntax is nestable. We almost never
restrict code to using an arbitrary subset of Python syntax just
because otherwise there'd be similar symbols in the same vicinity.
Even when it's a problem for the parser, the solution is often just
parentheses.

> I guess '>=' also looks "confusable", but it's far less common in signatures, 
> and the meaning is further away.
>

It's no less valid than your other examples, nor less common (why
would you have "==" in a function signature, for instance?).

> Below you seem to try another unconvincing reductio ad absurdum to suggest 
> that I must either want a language with no symbols or support this PEP.
>
> I think the cognitive complexity of a line with sigils is somewhere around 
> quadratic or cubic on the number of distinct sigils. But when several look 
> similar, it quickly tends toward the higher end. And when several have 
> related meanings, it's harder still to read.
>

It shouldn't need to be. Once you know how expressions are built up,
it should give linear complexity.

Did the introduction of the @ (matrix multiplication) operator to
Python increase the language's complexity multiplicatively, or
additively? Be honest now: are your programs more confusing to read
because @ could have been *, because @ could have been +, because @
could have been ==, etc etc etc, or is it only that @ is one new
operator, additively with the other operators?

Even when syntactically it's multiplicative, it's often possible to be
merely additive in cognitive burden. Augmented assignment broadly
functions as a single feature - "x #= y" parallels "x = x # y" for any
operator where that's legal.

> When I write an expression like 'a - b * c / d**e + f' that also has a bunch 
> of symbols. But they are symbols that:
>
> - look strongly distinct
> - have meanings familiar from childhood
> - have strongly different meanings (albeit all related to arithmetic)
>

The double asterisk wasn't one that I used in my childhood, yet in
programming, I simply learned it and started using it. What happens is
that known concepts are made use of to teach others. It's the same
with every feature, and this one is no different: if you already
understand "def f(x=1)", it is only a small step to "def f(x=>[])",
and everything you already know is still valid.

> Yes, I probably have to think for a while about operator precedence to make 
> sure I understand it.  Probably I'll add some redundant parens if I can edit 
> the code. But the cognitive burden of the sigils remains FAR lower than what 
> would occur with regularity under PEP 671.
>

Is that simply because you already are familiar with those operators,
or is there something inherently different about them? Would it really
be any different?

> I already dislike the walrus operator in signature context for that reason... 
> although I think it's great for e.g. 'while a := getdata() > 0: ...'
>

Then don't use it in a signature. That's fine. Personally, I've never
used the "def f(x=_sentinel:=object())" trick, because it has very
little value - it makes the function header carry information that
actually isn't part of the function signature (that the object is also
in the surrounding context as "_sentinel" - the function's caller
can't use that information), and doesn't have any real advantages over
just putting it a line above.

But that's because of what the feature does, not how it's spelled. An
expression is an expression. Any competent programmer should be able
to read them as such.

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 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread David Mertz, Ph.D.
Unfortunately,  in relation to this PEP, I find your arguments tend to be
sophistical. They ate not generally so in other threads,  but for whatever
reason your attachment to this has a different quality.

There's an interesting point you raise though. You seem to feel that
closely related meanings should have similar looking sigils. I'm not sure
my opinion is *opposite *, but it's definitely more that subtly different
semantics should not be marked by easily visually confusable sigils.

Under PEP 671, a single line of a function signature might contain '=',
':=', '=>', '->', ':', and '=='. Obviously it can have other symbols as
well. But those are the ones the most blur into each other visually. 4 of
them have closely related meanings. You don't even need to be contrived to
have such examples.

I guess '>=' also looks "confusable", but it's far less common in
signatures, and the meaning is further away.

Below you seem to try another unconvincing reductio ad absurdum to suggest
that I must either want a language with no symbols or support this PEP.

I think the cognitive complexity of a line with sigils is somewhere around
quadratic or cubic on the number of distinct sigils. But when several look
similar, it quickly tends toward the higher end. And when several have
related meanings, it's harder still to read.

When I write an expression like 'a - b * c / d**e + f' that also has a
bunch of symbols. But they are symbols that:

- look strongly distinct
- have meanings familiar from childhood
- have strongly different meanings (albeit all related to arithmetic)

Yes, I probably have to think for a while about operator precedence to make
sure I understand it.  Probably I'll add some redundant parens if I can
edit the code. But the cognitive burden of the sigils remains FAR lower
than what would occur with regularity under PEP 671.

I already dislike the walrus operator in signature context for that
reason... although I think it's great for e.g. 'while a := getdata() > 0:
...'

On Sun, Jun 19, 2022, 10:31 AM Chris Angelico  wrote:

> On Mon, 20 Jun 2022 at 00:06, David Mertz, Ph.D. 
> wrote:
> >
> > On Sun, Jun 19, 2022, 3:27 AM Chris Angelico
> >>
> >> > I'm still -1 because I don't think the purpose alone is close to
> worth the cost of new syntax... And especially not using sigils that are
> confusing to read in code.
> >> >
> >> > The topic of "late binding in function signatures"  simply isn't
> *orthogonal* to "late binding in the general sense." Yes, they are
> distinct, but very closely adjacent.
> >>
> >> Every argument you've just made is ALSO an argument against function
> defaults in general. Do you think that they aren't worth syntax either?
> >
> >
> > I honestly can find no connection between what I've argued and "function
> defaults in general." It feels like a non sequitur, but I accept that they
> somehow connect in your mind.
> >
>
> Let's go through the arguments you laid out.
>
> > It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer
> characters, and moving an expression from the body to the signature.
> >
>
> That's what ALL argument defaults do. Some languages evaluate them
> early, some evaluate them late.
>
> > I'm still -1 because I don't think the purpose alone is close to worth
> the cost of new syntax...
> >
>
> What purpose? Being able to define the function's signature in its
> signature, including the meaning of omitted arguments? That's
> definitely the purpose of ALL default arguments, not just late-bound.
>
> > And especially not using sigils that are confusing to read in code.
>
> The sigils used are very similar here: "a=b" and "a=>b". Are you
> really trying to tell me that "=" is not confusing to read in code,
> but "=>" is, or are all such sigils equally confusing? Function
> signatures already have several symbols other than those used for
> defaults, including *, /, and :, not to mention ( ) and -> which
> aren't inside the argument list, but are still part of the function
> signature. Programmers are accustomed to working with symbols (with
> the possible exception of COBOL and DeScribe Macro Language
> programmers), and your argument would work just as well against any
> sort of argument defaults.
>
> > The topic of "late binding in function signatures"  simply isn't
> *orthogonal* to "late binding in the general sense." Yes, they are
> distinct, but very closely adjacent.
>
> This one, you specifically mention late binding, so that's the one
> exception.
>
> Other than that, every one of your arguments could be used to show
> that we shouldn't have ANY function argument defaults. Not one of them
> justifies having default values without default expressions.
>
> > Way back last Oct when this discussion had it's first round, someone
> (probably Steven, but maybe it was someone else) did a survey of a numerous
> programming languages, and whether they use early binding or late binding
> of default function arguments.
> >
> > The result was that 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread Chris Angelico
On Mon, 20 Jun 2022 at 00:06, David Mertz, Ph.D.  wrote:
>
> On Sun, Jun 19, 2022, 3:27 AM Chris Angelico
>>
>> > I'm still -1 because I don't think the purpose alone is close to worth the 
>> > cost of new syntax... And especially not using sigils that are confusing 
>> > to read in code.
>> >
>> > The topic of "late binding in function signatures"  simply isn't 
>> > *orthogonal* to "late binding in the general sense." Yes, they are 
>> > distinct, but very closely adjacent.
>>
>> Every argument you've just made is ALSO an argument against function 
>> defaults in general. Do you think that they aren't worth syntax either?
>
>
> I honestly can find no connection between what I've argued and "function 
> defaults in general." It feels like a non sequitur, but I accept that they 
> somehow connect in your mind.
>

Let's go through the arguments you laid out.

> It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer 
> characters, and moving an expression from the body to the signature.
>

That's what ALL argument defaults do. Some languages evaluate them
early, some evaluate them late.

> I'm still -1 because I don't think the purpose alone is close to worth the 
> cost of new syntax...
>

What purpose? Being able to define the function's signature in its
signature, including the meaning of omitted arguments? That's
definitely the purpose of ALL default arguments, not just late-bound.

> And especially not using sigils that are confusing to read in code.

The sigils used are very similar here: "a=b" and "a=>b". Are you
really trying to tell me that "=" is not confusing to read in code,
but "=>" is, or are all such sigils equally confusing? Function
signatures already have several symbols other than those used for
defaults, including *, /, and :, not to mention ( ) and -> which
aren't inside the argument list, but are still part of the function
signature. Programmers are accustomed to working with symbols (with
the possible exception of COBOL and DeScribe Macro Language
programmers), and your argument would work just as well against any
sort of argument defaults.

> The topic of "late binding in function signatures"  simply isn't *orthogonal* 
> to "late binding in the general sense." Yes, they are distinct, but very 
> closely adjacent.

This one, you specifically mention late binding, so that's the one exception.

Other than that, every one of your arguments could be used to show
that we shouldn't have ANY function argument defaults. Not one of them
justifies having default values without default expressions.

> Way back last Oct when this discussion had it's first round, someone 
> (probably Steven, but maybe it was someone else) did a survey of a numerous 
> programming languages, and whether they use early binding or late binding of 
> default function arguments.
>
> The result was that MOST languages do late (call time) binding, albeit many 
> of those are compiled languages where early binding doesn't really make 
> sense. Some, like JavaScript don't have defaults at all, so the approach is 
> actually similar to Python:
>
> const myfunc = (a, b, c) => {
> if (typeof c === 'undefined') { c = ... }
> }

Actually JavaScript does have argument defaults. (Also, I would write
this as simply "if (c === undefined)", since there's no situation in
which that would fail here.) The obvious syntax is equivalent to what
you wrote:

const myfunc = (a, b, c=...) => ...

> That's a sentinel, but worse than Python in several ways.

Not sure what you mean by "several", but it is indeed a simple
sentinel, which has the downside that you can pass the special value
undefined to the function. So I would say it's exactly equivalent to
Python and the use of None, except that it's late-bound.

> Others like Perl don't really have named arguments at all, but that weird 
> implicit list you can pop from.
>

JavaScript, being JavaScript, has that too - which is actually good,
because it lets you distinguish between omitted arguments and those
passed as undefined.

I want to do *better* than those languages, not to use them as a pass mark.

> The one thing that there were ZERO examples of elsewhere was what you 
> propose: slightly different syntax to allow both early-bound and late-bound. 
> Admittedly, if Python had done late-bound from 1.0, probably no one would now 
> have a PEP to add an early-bound spelling variant.
>

And yet early-bound argument defaults ARE of value. Maybe they
wouldn't have been worth adding syntax for, but I would be highly
confident that someone would have made a decorator for it:

@freeze_defaults(x=1)
def foo(x): ...

And, since it's hard for a decorator to remap arguments perfectly, it
would have done an imperfect job, but it might have been good enough
to not ask for the feature.

> If Python had always been late-bound, I'm sure I'd be perfectly happy with it 
> today. But sentinels are really easy, and obscure sigils are really hard. So 
> adding the new spelling just 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread David Mertz, Ph.D.
On Sun, Jun 19, 2022, 3:27 AM Chris Angelico

> > I'm still -1 because I don't think the purpose alone is close to worth
> the cost of new syntax... And especially not using sigils that are
> confusing to read in code.
> >
> > The topic of "late binding in function signatures"  simply isn't
> *orthogonal* to "late binding in the general sense." Yes, they are
> distinct, but very closely adjacent.
>
> Every argument you've just made is ALSO an argument against function
> defaults in general. Do you think that they aren't worth syntax either?
>

I honestly can find no connection between what I've argued and "function
defaults in general." It feels like a non sequitur, but I accept that they
somehow connect in your mind.

Way back last Oct when this discussion had it's first round, someone
(probably Steven, but maybe it was someone else) did a survey of a numerous
programming languages, and whether they use early binding or late binding
of default function arguments.

The result was that MOST languages do late (call time) binding, albeit many
of those are compiled languages where early binding doesn't really make
sense. Some, like JavaScript don't have defaults at all, so the approach is
actually similar to Python:

const myfunc = (a, b, c) => {
if (typeof c === 'undefined') { c = ... }
}

That's a sentinel, but worse than Python in several ways. Others like Perl
don't really have named arguments at all, but that weird implicit list you
can pop from.

The one thing that there were ZERO examples of elsewhere was what you
propose: slightly different syntax to allow both early-bound and
late-bound. Admittedly, if Python had done late-bound from 1.0, probably no
one would now have a PEP to add an early-bound spelling variant.

If Python had always been late-bound, I'm sure I'd be perfectly happy with
it today. But sentinels are really easy, and obscure sigils are really
hard. So adding the new spelling just makes Python worse. Beginners have
something needless to learn, and experienced developers have just a little
more cognitive burden all the time.

>
___
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/4TMLNYHBLQEY3TBWLH3S3DEDCFWN2Q2M/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-19 Thread Chris Angelico
On Sun, 19 Jun 2022 at 13:44, David Mertz, Ph.D.  wrote:
>
> On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe
>>
>> Sorry again, but IMO discussing any model except one where late-bound 
>> defaults are evaluated at function call time is just adding FUD.
>
>
> It's definitely rude to repeatedly state that anyone who's opinion is 
> different from yours is "adding FUD" and doesn't belong in the thread.
>
> Stephen, and Steven, and Paul, and I all perfectly well understand what 
> "evaluated at function call time" means.
>
> It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer 
> characters, and moving an expression from the body to the signature.
>
> I won't stoop to saying that advocating what you do is FUD. I can even 
> understand why someone would want that in Python.
>
> I'm still -1 because I don't think the purpose alone is close to worth the 
> cost of new syntax... And especially not using sigils that are confusing to 
> read in code.
>
> The topic of "late binding in function signatures"  simply isn't *orthogonal* 
> to "late binding in the general sense." Yes, they are distinct, but very 
> closely adjacent.

Every argument you've just made is ALSO an argument against function
defaults in general. Do you think that they aren't worth syntax
either?

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread David Mertz, Ph.D.
On Sat, Jun 18, 2022, 9:21 PM Rob Cliffe

> Sorry again, but IMO discussing any model except one where late-bound
> defaults are evaluated at function call time is just adding FUD.
>

It's definitely rude to repeatedly state that anyone who's opinion is
different from yours is "adding FUD" and doesn't belong in the thread.

Stephen, and Steven, and Paul, and I all perfectly well understand what
"evaluated at function call time" means.

It's a way to spell `if arg is sentinel: arg = ...` using slightly fewer
characters, and moving an expression from the body to the signature.

I won't stoop to saying that advocating what you do is FUD. I can even
understand why someone would want that in Python.

I'm still -1 because I don't think the purpose alone is close to worth the
cost of new syntax... And especially not using sigils that are confusing to
read in code.

The topic of "late binding in function signatures"  simply isn't
*orthogonal* to "late binding in the general sense." Yes, they are
distinct, but very closely adjacent.
___
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/INJ6O2MIJUU7ZML2P6SF47FRD7HOMMP6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Rob Cliffe via Python-ideas

Sorry, but I think all this talk about lazy evaluation is a big red herring:
    (1) Python is not Haskell or Dask.
    (2) Lazy evaluation is something Python doesn't have, and would be 
a HUGE amount of work for Chris (or anyone) to implement (much more, I 
would think, than he has already put into his reference implementation 
of PEP 671).  It's effectively asking for an implementation of that 
deferred evaluation vapourware that people keep talking about.  It's not 
going to happen in a foreseeable time frame.  And in the unlikely event 
that Chris (or someone) DID implement it, I expect there would be a 
chorus of "No, no, that's not how (I think) it should work at all".
    (3)  Late-bound defaults that are evaluated at function call time, 
as per PEP 671, give you an easy way of doing something that at present 
needs one of a number of workarounds (such as using sentinel values) all 
of which have their drawbacks or awkward points.
    (4) The guarantee that a late-bound default WILL be executed at 
function call time, can be useful, even essential (it could be 
time-dependent or it could depend on the values - default or otherwise - 
of other parameters whose values might be changed in the function 
body).  Sure, I appreciate that there are times when you might want to 
defer the evaluation because it is expensive and might not be needed, but:
    (5) If you really want deferred evaluation of a parameter default, 
you can achieve that by explicitly evaluating it, *at the point you want 
it*, in the function body.  Explicit is better than implicit.


Sorry again, but IMO discussing any model except one where late-bound 
defaults are evaluated at function call time is just adding FUD.
I suppose I'll be accused again of trying to censor this thread for 
saying that.  Well, as Chris said (as far as I recall ATM) there is a 
difference between discussing variants of a proposal and discussing 
orthogonal proposals (which could be raised in a separate thread).  And 
IMO lazy evaluation IS a different, orthogonal proposal.  There's 
nothing in the PEP about it.

Best wishes
Rob Cliffe



On 18/06/2022 16:42, David Mertz, Ph.D. wrote:
I think the example that Steven gave, and Stephen approximately 
repeats is good.


    def func(items=[], n=later len(items)):
        items.append("Hello")
        print(n)

    func()

> I guess Chris will say 0 and David will say 1, but I might be wrong 
about either of them.


This is correct. And even though using a (soft) keyword like this gets 
me to -0, the semantics I want indeed are different. I only want the 
binding to be evaluated when it is referenced. If it never gets 
referenced, the compassion time asked side effects are skipped.


Of course, the first line of the function body could be `n = n`. But 
adding that line isn't so much different from starting with `if n is 
None: n = ... `


As to Stephen's comments on not having used the "evaluate on 
reference" pattern, that's pretty much not having used dask.deferred.


The difference is that with Dask (or Haskell) everything stays lazy 
until you explicitly call `.compute()` on something in the DAG of 
operations. I'd prefer not to need that.


But then my not-a-proposal would need a way to have "a reference that 
isn't a reference". I think the same keywords works.


def func(items=[], n=later len(items)):
        items.append("Hello")
        n = later n**3 # n remains lazy
        # ... more stuff
        print(n) # actually evaluate the cube of length

On Sat, Jun 18, 2022, 10:52 AM Stephen J. Turnbull 
 wrote:


Chris wants syntax for the common pattern

    def foo(arg_with_new_empty_list_default=None):
        if arg_with_new_empty_list_default is None:
            arg_with_new_empty_list_default = []
        # do stuff

I can't really guess how useful the "use point" version would be.
It's not a pattern I've used, I use a zero-argument function very
occasionally but I can't recall a case where I used a lambda


___
Python-ideas mailing list --python-ideas@python.org
To unsubscribe send an email topython-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-ideas@python.org/message/RLFYYFG7T53F7XGFGWMTV3NWHWVP3LCU/
Code of Conduct:http://python.org/psf/codeofconduct/
___
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/RIVWFMBG47ILJNEVNMACCTE7YS7RWGGL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Rob Cliffe via Python-ideas



On 18/06/2022 03:28, Steven D'Aprano wrote:

On Fri, Jun 17, 2022 at 06:32:36AM +0100, Rob Cliffe wrote:


The bar for adding a new hard keyword to Python is very high.

Likewise for new syntax.
I would suggest less so, provided that it was previously illegal, 
because it's backward-compatible, unlike a new keyword.




The suggestion is to add a new keyword to a PEP which absolutely doesn't
need it,

*shrug*
Well, I have heard many times how high the bar is, so I'm surprised that 
suggesting a completely unnecessary one gets no more from you than a shrug.


The match...case statement didn't "need" keywords either, we could have
picked symbols instead if we wanted to look like APL. Remember that
keywords have advantages as well as disadvantages. Given the existence
of community support for keywords, the PEP should make the case that
symbols are better in this case.

Even if that's only "a majority prefer symbols".

I did mention the readability issue towards the end of my post.




on the grounds that it **might** (**not** would - we can't know
without a spec) give compatibility with some fictional vapourware which
- for all people keep talking about it - hasn't happened in years, isn't
happening (AFAIK nobody is working on it), doesn't have anything
remotely close to even an outline specification (people disagree as to
what it should do), very likely never will happen, and at best won't
happen for years.

I think that is broadly accurate. Harsh but fair: nobody has a concrete
plan for generalising "defer" keyword would do. It is still vapourware.

Thank you.


[...]

     def f(x = later -y):
Is that a late-bound default of -y?  Bad luck; it's already legal syntax
for an early-bound default of `later` minus `y`.

Good catch.

Thank you.




         Late-bound defaults are meant to be evaluated at function
call time (and in particular, not some way down in the function body when
the parameter gets used).

Not necessarily.

I don't recall if this has been raised in this thread before, but it is
possible to delay the evaluation of the default value until it is
actually needed. I believe that this is how Haskell operates pretty much
everywhere. (Haskell experts: do I have that correct?)

Sorry, but what on earth is the relevance of this?  Python is not Haskell.
And it can be vital that the evaluation of late-default values is *not* 
delayed (it should be guaranteed if PEP 671 is accepted).

Example 1:
    def f(startTime => timeNow()):
        < 10-minute calculation >
        endTime = timeNow()
        print('Elapsed time:', endTime-startTime) # Help, why is this 
printing "Elapsed time: -0.001"?

Example 2:
    def g(x, y=>x**2):
        x = x+1
        print(y)

Best wishes
Rob Cliffe
___
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/RLQVS3Z26A7NTFNTC2EZA7C2FE42ZURH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread David Mertz, Ph.D.
I think the example that Steven gave, and Stephen approximately repeats is
good.

def func(items=[], n=later len(items)):
items.append("Hello")
print(n)

func()

> I guess Chris will say 0 and David will say 1, but I might be wrong about
either of them.

This is correct. And even though using a (soft) keyword like this gets me
to -0, the semantics I want indeed are different. I only want the binding
to be evaluated when it is referenced. If it never gets referenced, the
compassion time asked side effects are skipped.

Of course, the first line of the function body could be `n = n`. But adding
that line isn't so much different from starting with `if n is None: n = ...
`

As to Stephen's comments on not having used the "evaluate on reference"
pattern, that's pretty much not having used dask.deferred.

The difference is that with Dask (or Haskell) everything stays lazy until
you explicitly call `.compute()` on something in the DAG of operations. I'd
prefer not to need that.

But then my not-a-proposal would need a way to have "a reference that isn't
a reference". I think the same keywords works.

def func(items=[], n=later len(items)):
items.append("Hello")
n = later n**3 # n remains lazy
# ... more stuff
print(n) # actually evaluate the cube of length

On Sat, Jun 18, 2022, 10:52 AM Stephen J. Turnbull <
stephenjturnb...@gmail.com> wrote:

> Chris wants syntax for the common pattern
>
> def foo(arg_with_new_empty_list_default=None):
> if arg_with_new_empty_list_default is None:
> arg_with_new_empty_list_default = []
> # do stuff
>
> I can't really guess how useful the "use point" version would be. It's not
> a pattern I've used, I use a zero-argument function very occasionally but I
> can't recall a case where I used a lambda
___
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/RLFYYFG7T53F7XGFGWMTV3NWHWVP3LCU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Paul Moore
On Sat, 18 Jun 2022 at 15:53, Stephen J. Turnbull
 wrote:
> I don't find that burdensome enough to want syntax, and I can't guess
> how quickly I'd start using it if available, that probably depends on
> how often the community seems to be using it (ie, in the code I'm
> reading).

To be honest, I think this is the real flaw with the proposal. It's
somewhat attractive in theory, adding
a short form for something which people do tend to write out
"longhand" at the moment. But the saving is
relatively small, and there are a number of vaguely annoying edge
cases that probably don't come
up often, but overall just push the proposal into the "annoyingly
complicated" area. The net result is that
we get something that *might* help with a minor annoyance, but the
cost in (theoretical, but necessary)
complexity is just a bit too high.

Paul
___
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/7WX3AAR7T3MR2NI7JFY3SJKWK4QIFGN5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > The match...case statement didn't "need" keywords either, we could have 
 > picked symbols instead if we wanted to look like APL. Remember that 
 > keywords have advantages as well as disadvantages. Given the existence 
 > of community support for keywords, the PEP should make the case that 
 > symbols are better in this case.

The argument I would make is that in the presence of type annotations
a keyword adds a lot of verbosity, and is possibly confusable (ie,
ignorable) as a type component, and that that is sufficient argument
for a symbol rather than a keyword.

 > This raises another choice: should lazy defaults be evaluated before 
 > entering the body of the function, or at the point where the parameter 
 > is used? Which would be more useful?



Chris makes the point that we've been through this before so I won't
belabor that point.  Both are potentially useful.  Chris wants syntax
for the common pattern

def foo(arg_with_new_empty_list_default=None):
if arg_with_new_empty_list_default is None:
arg_with_new_empty_list_default = []
# do stuff

and variants (eg, where the default is a computation expensive enough
that you don't want to do it if the argument is never defaulted).  I
don't find that burdensome enough to want syntax, and I can't guess
how quickly I'd start using it if available, that probably depends on
how often the community seems to be using it (ie, in the code I'm
reading).

I can't really guess how useful the "use point" version would be.
It's not a pattern I've used, I use a zero-argument function very
occasionally but I can't recall a case where I used a lambda (lambdas
are kinda annoying).  Adding the parens at the call is easy to forget,
but not that huge a burden either.  The only use case I can think of
offhand is where the default is such an expensive computation that you
don't want it done unless its result is actually used, and it might
not be:

def foo(flag, arg=None, *otherargs):
if flag:
if arg is None:
arg = expensive_function
return arg(*other_args)
else:
return a_constant

On the one hand, it seems likely that a very expensive function is
expensive enough to avoid at the cost of an obscure default and an if
in the definition of foo.  On the other the whole scenario seems
rather contrived and not worth syntax.
___
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/6Z7GD6STJQP7ABKINIMBNCVBS4BOSLOG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Stephen J. Turnbull
Chris Angelico writes:

 > And there we have it. People are complaining loudly, but then ALSO
 > saying that they don't support the proposal anyway. Why are you
 > bothering to debate this if you've already made your decision?

I can't speak for Brendan, but I have two reasons for discussing
despite being broadly in sympathy with David Mertz's reasons for
opposing the proposal:

1.  Often enough I've disagreed with a proposal, only to see it
implemented.  Of course, I want the least bad version from my
point of view.

2.  More altruistically, even though I disagree with a proposal, I
would be ashamed if I thought there was a way to improve a
proposal, and didn't mention it in the hope of sabotaging the
proposal's chances by leaving it less than it could be.

That doesn't mean in either case I'm right, of course, but at least I
can *try*. :-)

Regards,
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/P7K2HAH3UM2OOONOOV45FSB3EUNDDA4C/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-18 Thread Paul Moore
On Sat, 18 Jun 2022 at 03:45, Chris Angelico  wrote:
> > This raises another choice: should lazy defaults be evaluated before
> > entering the body of the function, or at the point where the parameter
> > is used? Which would be more useful?
> >
> > # `defer n=len(items)`
> > def func(items=[], n=>len(items)):
> > items.append("Hello")
> > print(n)
> >
> > func()
>
> That's one of the problems. Generic lazy evaluation should be
> processed at some point where the parameter is used, but late-bound
> defaults are evaluated as the function begins. They are orthogonal.

That sounds like an *extremely* good statement to make in the
"Rejected suggestions" section of the PEP, explaining why the PEP's
proposal and a "lazy evaluation" proposal are different.

> At what point is an unrelated proposal a "rejected idea"? How
> different does it have to be before it doesn't help to have it in that
> section?

At the point where people repeatedly offer it as an alternative to the
PEP. If it's so unrelated as to make no sense at all, just add it as
"XXX: rejected as it solves a different problem" or similar. But your
response above is better for the lazy evaluation suggestion, and
explains why you think it's unrelated.

> You're welcome to keep on arguing for the sake of arguing, but you're
> not actually accomplishing anything by it. Especially since you're
> rehashing the exact same complaints that you raised previously, and
> which I responded, exactly the same way, at the time.

*Everyone* is just rehashing the same comments by this point. People
are piling in because of a fear that if they don't, someone will claim
that we now have consensus, not because they have anything new to add.
IIRC, someone early in this thread even said something along the lines
of "we seem to be reaching a consensus", but I can't find the
reference now.

I'd suggest that Chris either mark the PEP as withdrawn, to make it
explicit that he has no plans to submit it, or submit it to the SC
(ideally with a note for transparency saying that there was no
consensus on python-ideas). Nobody is really benefiting from repeating
this discussion over and over.

Paul
___
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/VJ26QUYGPOB6NED4NYGCKTOHAWZ7YPS3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Sat, 18 Jun 2022 at 13:13, Brendan Barnwell  wrote:
>
> On 2022-06-17 14:23, Chris Angelico wrote:
> > I've just pushed a change to the wording. Let's see if it makes a 
> > difference.
> >
> >> I think the PEP would benefit from a fully explicit definition of
> >> exactly when and how the late-bound defaults would be evaluated.  For
> >> instance, by demonstrating an "unrolling" into something paralleling
> >> existing Python code.  Like:
> >>
> >> def f(a=>items[0], items=[]):
> >> # body
> >>
> >> is equivalent to:
> >>
> >> def f(a=FakeDefault, items=[]):
> >> a = items[0]
> >> # body
> >
> > That IS in the PEP. Have you read it?
>
> I read it before your update.  Is the version up now the updated one?
> I'm guessing it is, because of the remark about "implementations may
> choose to do this in two separate passes".
>
> But I don't see where something like what I showed there is given as a
> specification.  I do see the "How to Teach This" section, which has an
> example similar to mine.  But that pretty clearly isn't specifying the
> behavior.  It still talks about "broadly equivalent" and a "rule of
> thumb", which are more ways of saying things other than a fully explicit
> and normative specification of the behavior.

"Broadly equivalent" is the best you're going to get, though. The
entire point of this proposal is that it isn't possible to do a
perfect job without language support. So the best you'll get is
something with a lot of caveats, or something that is just "basically
like this".

And your example has the exact same limitations. There's no
"FakeDefault" that can behave like that. Is "broadly equivalent" such
a bad thing?

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/627P6LIESQ6LJ3M6S5FY7B73FB5DWPY2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Brendan Barnwell

On 2022-06-17 14:23, Chris Angelico wrote:

I've just pushed a change to the wording. Let's see if it makes a difference.


I think the PEP would benefit from a fully explicit definition of
exactly when and how the late-bound defaults would be evaluated.  For
instance, by demonstrating an "unrolling" into something paralleling
existing Python code.  Like:

def f(a=>items[0], items=[]):
# body

is equivalent to:

def f(a=FakeDefault, items=[]):
a = items[0]
# body


That IS in the PEP. Have you read it?


	I read it before your update.  Is the version up now the updated one? 
I'm guessing it is, because of the remark about "implementations may 
choose to do this in two separate passes".


	But I don't see where something like what I showed there is given as a 
specification.  I do see the "How to Teach This" section, which has an 
example similar to mine.  But that pretty clearly isn't specifying the 
behavior.  It still talks about "broadly equivalent" and a "rule of 
thumb", which are more ways of saying things other than a fully explicit 
and normative specification of the behavior.


>> This is all academic to me, however, since even if you did 
that I still

>> wouldn't support the PEP for various more basic reasons that I've
>> mentioned in the earlier iteration of this thread.
>
> And there we have it. People are complaining loudly, but then ALSO
> saying that they don't support the proposal anyway. Why are you
> bothering to debate this if you've already made your decision?

	I didn't intend to initially, but as the discussion continued I figured 
since everyone else was restating their opinions there's no reason I 
can't do so as well.  :-)  Also, to avoid people coming back later and 
saying that some kind of consensus emerged in the second round because 
no one objected, etc.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
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/4RALCIBZXTW4GDRM6H5Y6UJNKXTHKJCA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Sat, 18 Jun 2022 at 12:36, Steven D'Aprano  wrote:
> I expect Chris will be annoyed at me raising this, but one way of
> implementing this would be to introduce a generalised "lazy evaluation"
> mechanism, similar to what Haskell does, rather than special-casing
> late-bound defaults. Then late-bound defaults just use the same
> mechanism, and syntax, as lazily evaluated values anywhere else.

Go ahead. Implement it. It actually is NOT sufficient, for a number of
reasons, which I have laid out in previous posts.

Generic "lazy evaluation" is sufficient to do *some* of what can be
done with late-bound argument defaults, but it is not sufficient for
everything, unless it is a nightmare that basically involves eval'ing
a text string in the surrounding context, with full ability to create
and reference any name bindings. Python does not support this concept.

> Chris may choose to reject this generalised lazy evaluation idea, but if
> so it needs to go into a Rejected Ideas section. Or he may decide that
> actually having a generalised lazy evaluation idea is *brilliant* and
> much nicer than making defaults a special case.

It's an almost completely orthogonal proposal. I used to have a
reference to it in the PEP but removed it because it was unhelpful.

> This raises another choice: should lazy defaults be evaluated before
> entering the body of the function, or at the point where the parameter
> is used? Which would be more useful?
>
> # `defer n=len(items)`
> def func(items=[], n=>len(items)):
> items.append("Hello")
> print(n)
>
> func()

That's one of the problems. Generic lazy evaluation should be
processed at some point where the parameter is used, but late-bound
defaults are evaluated as the function begins. They are orthogonal.

> Printing 1 would require a generalised lazy mechanism, but printing 0
> is independent of the mechanism. As it stands, the PEP requires 0. Which
> would be better or more useful?

Probably both. If someone wants to propose a generic deferred
evaluation feature, I would be happy to discuss it, but it's not a
replacement for PEP 671, nor is PEP 671 a replacement for it.

> Chris is welcome to push for a particular proposal. That is the purpose
> of the PEP process. He is also supposed to give dissenting arguments and
> alternatives fair airing in the PEP itself, even if only in a Rejected
> Ideas section.
>

At what point is an unrelated proposal a "rejected idea"? How
different does it have to be before it doesn't help to have it in that
section?

You're welcome to keep on arguing for the sake of arguing, but you're
not actually accomplishing anything by it. Especially since you're
rehashing the exact same complaints that you raised previously, and
which I responded, exactly the same way, at the time.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Steven D'Aprano
On Fri, Jun 17, 2022 at 06:32:36AM +0100, Rob Cliffe wrote:

> The bar for adding a new hard keyword to Python is very high.

Likewise for new syntax.


> The suggestion is to add a new keyword to a PEP which absolutely doesn't 
> need it, 

*shrug*

The match...case statement didn't "need" keywords either, we could have 
picked symbols instead if we wanted to look like APL. Remember that 
keywords have advantages as well as disadvantages. Given the existence 
of community support for keywords, the PEP should make the case that 
symbols are better in this case.

Even if that's only "a majority prefer symbols".


> on the grounds that it **might** (**not** would - we can't know 
> without a spec) give compatibility with some fictional vapourware which 
> - for all people keep talking about it - hasn't happened in years, isn't 
> happening (AFAIK nobody is working on it), doesn't have anything 
> remotely close to even an outline specification (people disagree as to 
> what it should do), very likely never will happen, and at best won't 
> happen for years.

I think that is broadly accurate. Harsh but fair: nobody has a concrete 
plan for generalising "defer" keyword would do. It is still vapourware.


[...]
>     def f(x = later -y):
> Is that a late-bound default of -y?  Bad luck; it's already legal syntax 
> for an early-bound default of `later` minus `y`.

Good catch.


>         Late-bound defaults are meant to be evaluated at function 
> call time (and in particular, not some way down in the function body when 
> the parameter gets used).

Not necessarily.

I don't recall if this has been raised in this thread before, but it is 
possible to delay the evaluation of the default value until it is 
actually needed. I believe that this is how Haskell operates pretty much 
everywhere. (Haskell experts: do I have that correct?)

I expect Chris will be annoyed at me raising this, but one way of 
implementing this would be to introduce a generalised "lazy evaluation" 
mechanism, similar to what Haskell does, rather than special-casing 
late-bound defaults. Then late-bound defaults just use the same 
mechanism, and syntax, as lazily evaluated values anywhere else.

I expect that this is the point that David is making: don't introduce 
syntax for a special case that will be obsolete in (mumble mumble...) 
releases.

David's point would be stronger if he could point to a concrete plan to 
introduce lazy evaluation in Python. The Zen of Python gives us some 
hints:

Now is better than never.
Although never is often better than *right* now.

which possibly suggests that the Zen was written by elves:

"I hear it is unwise to seek the council of elves, for they will answer 
with yes and no."

Chris may choose to reject this generalised lazy evaluation idea, but if 
so it needs to go into a Rejected Ideas section. Or he may decide that 
actually having a generalised lazy evaluation idea is *brilliant* and 
much nicer than making defaults a special case.

(I think that the Zen has something to say about special cases too.)

This raises another choice: should lazy defaults be evaluated before 
entering the body of the function, or at the point where the parameter 
is used? Which would be more useful?

# `defer n=len(items)`
def func(items=[], n=>len(items)):
items.append("Hello")
print(n)

func()

Printing 1 would require a generalised lazy mechanism, but printing 0 
is independent of the mechanism. As it stands, the PEP requires 0. Which 
would be better or more useful?

I guess Chris will say 0 and David will say 1, but I might be wrong 
about either of them.

One way or the other, these are the sorts of questions that the 
discussion is supposed to work out, and the PEP is supposed to 
reference. There are well over 600 emails in this thread and the 
Steering Council should not be expected to read the whole thing, the PEP 
is supposed to be an honest and fair summary of alternatives and 
rejected ideas.

Chris is welcome to push for a particular proposal. That is the purpose 
of the PEP process. He is also supposed to give dissenting arguments and 
alternatives fair airing in the PEP itself, even if only in a Rejected 
Ideas section.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Sat, 18 Jun 2022 at 06:17, Brendan Barnwell  wrote:
>
> On 2022-06-17 07:53, Chris Angelico wrote:
> > On Sat, 18 Jun 2022 at 00:21, Paul Moore  wrote:
> >>
> >> On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
> >> >
> >> > There are several ways to make this clearly sane.
> >> >
> >> > # Clearly UnboundLocalError
> >> > def frob(n=>len(items), items=>[]):
> >>
> >> Um, I didn't see that as any more obvious than the original example. I
> >> guess I can see it's UnboundLocalError, but honestly that's not
> >> obvious to me.
> >
> > Question: Is this obvious?
> >
> > def f():
> >  x, x[0] = [2], 3
> >  print(x)
> >
> > def boom():
> >  x[0], x = 3, [2]
> >  # raises UnboundLocalError
>
> Personally, I don't care so much whether the behavior is "obvious" or
> even "confusing" as about whether it's defined.  Both of those examples
> have defined behavior in Python.  That's better than having undefined
> behavior where either of them might do different things depending on the
> implementation.
>
> > It's unfair to say that I "refuse to assign semantics" as if I'm
> > permitting literally any behaviour. All I'm doing is saying that the
> > UnboundLocalError is optional, *at this stage*. There have been far
> > less-defined semantics that have remained in the language for a long
> > time, or cases where something has changed in behaviour over time
> > despite not being explicitly stated as implementation-defined. Is this
> > legal?
> >
> > def f():
> >  x = 1
> >  global x
> >
> > Does Python mandate whether this is legal or not? If so, how far back
> > in Python's history has it been defined?
>
> If it doesn't mandate it, then it would be better if it did.  In my
> view, none of your arguments about "some things are undefined" are
> actually providing any positive support for the idea that the behavior
> in question should remained undefined in the PEP.

I've just pushed a change to the wording. Let's see if it makes a difference.

> I think the PEP would benefit from a fully explicit definition of
> exactly when and how the late-bound defaults would be evaluated.  For
> instance, by demonstrating an "unrolling" into something paralleling
> existing Python code.  Like:
>
> def f(a=>items[0], items=[]):
> # body
>
> is equivalent to:
>
> def f(a=FakeDefault, items=[]):
> a = items[0]
> # body

That IS in the PEP. Have you read it?

> . . . or whatever.  I mean, it's up to you as the PEP author to decide
> what semantics you want.  But I think the PEP should be fully explicit
> about the order of evaluation of everything.  I don't see any benefit to
> leaving it ambiguous.

Read the latest version and tell me if it still sounds ambiguous.

> This is all academic to me, however, since even if you did that I 
> still
> wouldn't support the PEP for various more basic reasons that I've
> mentioned in the earlier iteration of this thread.

And there we have it. People are complaining loudly, but then ALSO
saying that they don't support the proposal anyway. Why are you
bothering to debate this if you've already made your decision?

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Brendan Barnwell

On 2022-06-17 07:53, Chris Angelico wrote:

On Sat, 18 Jun 2022 at 00:21, Paul Moore  wrote:


On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
>
> There are several ways to make this clearly sane.
>
> # Clearly UnboundLocalError
> def frob(n=>len(items), items=>[]):

Um, I didn't see that as any more obvious than the original example. I
guess I can see it's UnboundLocalError, but honestly that's not
obvious to me.


Question: Is this obvious?

def f():
 x, x[0] = [2], 3
 print(x)

def boom():
 x[0], x = 3, [2]
 # raises UnboundLocalError


	Personally, I don't care so much whether the behavior is "obvious" or 
even "confusing" as about whether it's defined.  Both of those examples 
have defined behavior in Python.  That's better than having undefined 
behavior where either of them might do different things depending on the 
implementation.



It's unfair to say that I "refuse to assign semantics" as if I'm
permitting literally any behaviour. All I'm doing is saying that the
UnboundLocalError is optional, *at this stage*. There have been far
less-defined semantics that have remained in the language for a long
time, or cases where something has changed in behaviour over time
despite not being explicitly stated as implementation-defined. Is this
legal?

def f():
 x = 1
 global x

Does Python mandate whether this is legal or not? If so, how far back
in Python's history has it been defined?


	If it doesn't mandate it, then it would be better if it did.  In my 
view, none of your arguments about "some things are undefined" are 
actually providing any positive support for the idea that the behavior 
in question should remained undefined in the PEP.


	I think the PEP would benefit from a fully explicit definition of 
exactly when and how the late-bound defaults would be evaluated.  For 
instance, by demonstrating an "unrolling" into something paralleling 
existing Python code.  Like:


def f(a=>items[0], items=[]):
# body

is equivalent to:

def f(a=FakeDefault, items=[]):
a = items[0]
# body

. . . or whatever.  I mean, it's up to you as the PEP author to decide 
what semantics you want.  But I think the PEP should be fully explicit 
about the order of evaluation of everything.  I don't see any benefit to 
leaving it ambiguous.


	This is all academic to me, however, since even if you did that I still 
wouldn't support the PEP for various more basic reasons that I've 
mentioned in the earlier iteration of this thread.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
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/M36WS6REGOKCUXRLIN2WV2LBU35TAJYR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Eric V. Smith via Python-ideas

On 6/17/2022 10:53 AM, Chris Angelico wrote:

The only two possible behaviours are:

1) It does the single obvious thing: n defaults to the length of
items, and items defaults to an empty tuple.
2) It raises UnboundLocalError if you omit n.

...

Would you prefer that I simply mandate that it be permitted, and then
a future version of Python changes it to be an exception? Or the other
way around? Because I could do that. Maybe it would reduce the
arguments. Pun intended, and I am not apologizing for it.


A third option would be that it's a syntax error for you to define such 
a function. This would be my preferred approach. This way, you can 
always assign semantics in the future. Sure, there are some cases you 
might want to support with the as-specified undefined behavior, but I 
don't think that's a good design.


If CPython 3.x works a certain way (especially if there's a test for 
it), you can be sure that other implementations will work the same way, 
and you can be sure that you can never change the behavior in the 
future. No amount of "but we said it was undefined" will allow us to 
change such behavior.


It would be like 3.7 saying "yeah, we said dicts are ordered in 3.6 but 
you shouldn't count on it, so we're going to make them unordered in 
3.7". It would just never happen.


That all said, I'm still -1 on this PEP, for reasons I won't rehash.

Eric



___
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/XLG4Q2YSKAB5FKEX6EXPTGWOUYQFO3SU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Sat, 18 Jun 2022 at 02:14, Paul Moore  wrote:
>
> On Fri, 17 Jun 2022 at 15:55, Chris Angelico  wrote:
> >
> > On Sat, 18 Jun 2022 at 00:21, Paul Moore  wrote:
> > >
> > > On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
> > > >
> > > > There are several ways to make this clearly sane.
> > > >
> > > > # Clearly UnboundLocalError
> > > > def frob(n=>len(items), items=>[]):
> > >
> > > Um, I didn't see that as any more obvious than the original example. I
> > > guess I can see it's UnboundLocalError, but honestly that's not
> > > obvious to me.
> >
> > Question: Is this obvious?
> >
> > def f():
> > x, x[0] = [2], 3
> > print(x)
> >
> > def boom():
> > x[0], x = 3, [2]
> > # raises UnboundLocalError
>
> No. I'm not sure what point you're trying to make here?

The point is that many things can be unobvious, including aspects of
important features that we make good use of all the time. But they are
consistent, which means that, once you try it and run into a problem,
you should be able to see *why* it's a problem.

(This particular example is another case of LTR evaluation - or to be
more precise, LTR assignment - and while I wouldn't do it in a simple
statement like this, I certainly have made use of it in a 'for' loop.)

> > I understand that left-to-right evaluation is something that has to be
> > learned (and isn't 100% true - operator precedence is a thing too),
> > but at very least, if it isn't *obvious*, it should at least be
> > *unsurprising* if you then get UnboundLocalError.
>
> Why? Are you saying I can't be surprised by the details of rules that
> I don't often have a need to understand in detail?

My point is that "unsurprising", while a much weaker criterion than
"obvious", should be quite attainable. If you try the above two pieces
of code, you'll quickly find that one of them works and one doesn't,
and from the exceptions you get, the rule should be fairly clear.

> In case you are, consider that as written, the PEP says
> that the *defaults* are evaluated left to right in the function's
> runtime scope, but it doesn't say when the parameter names are
> introduced in that scope - prior to this PEP there was no need to
> define that detail, as nothing could happen before the names were
> introduced at the start of the scope. If you accept that
> clarification, can you accept that the current text isn't as clear as
> it might be?

I actually don't accept that clarification, because nothing has
changed. At what point in this function do the names get introduced to
the scope?

def spam(x, y=1, *, z=2):
ham = [x, y, z]

They are all "introduced", if that term even has meaning, at the very
instant that the scope begins to exist. The name 'ham' isn't
introduced to the scope at a subsequent point. There are languages
that work this way (and it can be very convenient when used
correctly), but Python is not one of them.

Late-bound defaults do not affect this in any way. A function
parameter, like any other local, is local for the entire scope of the
function. It doesn't "become local" part way through.

Do I need to state this in the PEP? Are there other parts of Python's
semantics which need to be restated in the PEP too? Which parts,
despite not changing, are now going to be brought into question?

> I meant the walrus operator, and that's my point. There's a lot of
> not-immediately-obvious interactions here. Even if we don't include
> default expressions, I'd argue that the behaviour is non-obvious:
>
> >>> def f(a=(b:=12)):
> ...   print(a, b)
> ...
> >>> f()
> 12 12
> >>> b
> 12
>
> I assume (possibly naïvely) that this is defined in the language spec,
> though, as it's existing behaviour. But when you add in default
> expressions, you need to be sure that the various interactions are
> well-defined.

They absolutely are well-defined. Almost certainly not useful, but
well-defined. The right hand side of either "a=EXPR" or "a=>EXPR" is
simply evaluated as an ordinary expression; the only difference is
whether it's evaluated at function definition time and in function
definition context, or at function invocation time and in the context
of the function itself.

> Agreed. Although consider the following:
>
> >>> def f(a=(b:=12), b=9):
> ...   print(a, b)
> ...
> >>> f()
> 12 9
> >>> b
> 12

Since this is an early-bound default, it can be considered like this:

_default = (b:=12)
def f(a=None, b=9):
if a is None: a = _default
print(a, b)

And then it should be unsurprising that b becomes 12 in the
surrounding scope, paralleling a's default value, and b defaults to 9
in the function's context.

> Would
>
> def frob(n=>len(items:=[]), items=>[1,2]):
> ...
>
> reassign items if n is omitted? Or would it assign the *global* items
> and then shadow it with a local for the parameter? Can you point to
> the explanation in the PEP that covers this? And even if you can, are
> you trying to claim that the behaviour is "obvious"?

Since these are both late-bound 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Paul Moore
On Fri, 17 Jun 2022 at 15:55, Chris Angelico  wrote:
>
> On Sat, 18 Jun 2022 at 00:21, Paul Moore  wrote:
> >
> > On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
> > >
> > > There are several ways to make this clearly sane.
> > >
> > > # Clearly UnboundLocalError
> > > def frob(n=>len(items), items=>[]):
> >
> > Um, I didn't see that as any more obvious than the original example. I
> > guess I can see it's UnboundLocalError, but honestly that's not
> > obvious to me.
>
> Question: Is this obvious?
>
> def f():
> x, x[0] = [2], 3
> print(x)
>
> def boom():
> x[0], x = 3, [2]
> # raises UnboundLocalError

No. I'm not sure what point you're trying to make here?

> I understand that left-to-right evaluation is something that has to be
> learned (and isn't 100% true - operator precedence is a thing too),
> but at very least, if it isn't *obvious*, it should at least be
> *unsurprising* if you then get UnboundLocalError.

Why? Are you saying I can't be surprised by the details of rules that
I don't often have a need to understand in detail?

I fear we're getting off-topic here, though. I'm not arguing that
anything here isn't well-defined, just that it's not obvious *to me*.
And I'm not even "arguing" that, I'm simply stating it as an observed
fact about how I initially reacted to the quoted example. It's you who
is stating that the frob case is "clearly" UnboundLocalError, and all
I'm saying is that's not "clear" to me, even if it is a consequence of
the rules in the PEP. And actually, I could argue that the PEP would
benefit from some clarification to make that consequence clearer - but
I don't feel that you're likely to be particularly receptive to that
statement. In case you are, consider that as written, the PEP says
that the *defaults* are evaluated left to right in the function's
runtime scope, but it doesn't say when the parameter names are
introduced in that scope - prior to this PEP there was no need to
define that detail, as nothing could happen before the names were
introduced at the start of the scope. If you accept that
clarification, can you accept that the current text isn't as clear as
it might be?

> > > # Clearly correct behaviour
> > > def frob(items=[], n=>len(items)):
> > > def frob(items=>[], n=>len(items)):
> >
> > Maybe... I'm not sure I see this as *that* much more obvious, although
> > I concede that the left-to-right evaluation rule implies it (it feels
> > like a mathematician's use of "obvious" - which quite often isn't ;-))
> > Using assignment expressions in argument defaults is well-defined but
> > not necessarily obvious in a similar way (to me, at least).
>
> When you say "assignment expressions", do you mean "default
> expressions", or are you referring to the walrus operator? There's a
> lot of other potentially-surprising behaviour if you mix assignment
> expressions in with this, because of the difference of scope. It's the
> sort of thing that can definitely be figured out, but I would advise
> against it.

I meant the walrus operator, and that's my point. There's a lot of
not-immediately-obvious interactions here. Even if we don't include
default expressions, I'd argue that the behaviour is non-obvious:

>>> def f(a=(b:=12)):
...   print(a, b)
...
>>> f()
12 12
>>> b
12

I assume (possibly naïvely) that this is defined in the language spec,
though, as it's existing behaviour. But when you add in default
expressions, you need to be sure that the various interactions are
well-defined. Note that at this point, I'm not even talking about
"obvious", simply the bare minimum of "if I write this supposedly
legal code, does the PEP explain what it does?"

> def frob(items=>[], n=>len(items:=[])):
>
> This will reassign items to be an empty list if n is omitted.
> Obviously that's bad code, but in general, I think assignment
> expressions inside default expressions are likely to be very
> surprising :)

Agreed. Although consider the following:

>>> def f(a=(b:=12), b=9):
...   print(a, b)
...
>>> f()
12 9
>>> b
12

Would

def frob(n=>len(items:=[]), items=>[1,2]):
...

reassign items if n is omitted? Or would it assign the *global* items
and then shadow it with a local for the parameter? Can you point to
the explanation in the PEP that covers this? And even if you can, are
you trying to claim that the behaviour is "obvious"?

> Then let's leave aside the term "obvious" and just go for
> "unsurprising". If you write code and get UnboundLocalError, will you
> be surprised that it doesn't work? If you write code and it works,
> will you be surprised with the result you got?

As I noted above, "surprising" is no different. I can easily be
surprised by well-defined behaviour. I'm not arguing that there's no
explanation for why a particular construct works the way that it does,
just that the behaviour may not be intuitive to people even if it is a
consequence of the rules. I'm arguing that the behaviour fails an "is
this easy to teach" criterion, not "is this 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Stephen J. Turnbull
Chris Angelico writes:

 > but at very least, if it isn't *obvious*, it should at least be
 > *unsurprising* if you then get UnboundLocalError.

+1 I think this (== "obvious in hindsight") is probably a better
criterion than "obvious" (from the definition) when an error *will* be
raised.  (That's as a general principle.  Ie, it doesn't need to be
obvious that you will *get* feedback from the system when you do
something, but it should be obvious what the feedback means when you
*do* get it.)

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Sat, 18 Jun 2022 at 00:21, Paul Moore  wrote:
>
> On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
> >
> > There are several ways to make this clearly sane.
> >
> > # Clearly UnboundLocalError
> > def frob(n=>len(items), items=>[]):
>
> Um, I didn't see that as any more obvious than the original example. I
> guess I can see it's UnboundLocalError, but honestly that's not
> obvious to me.

Question: Is this obvious?

def f():
x, x[0] = [2], 3
print(x)

def boom():
x[0], x = 3, [2]
# raises UnboundLocalError

I understand that left-to-right evaluation is something that has to be
learned (and isn't 100% true - operator precedence is a thing too),
but at very least, if it isn't *obvious*, it should at least be
*unsurprising* if you then get UnboundLocalError.

> > # Clearly correct behaviour
> > def frob(items=[], n=>len(items)):
> > def frob(items=>[], n=>len(items)):
>
> Maybe... I'm not sure I see this as *that* much more obvious, although
> I concede that the left-to-right evaluation rule implies it (it feels
> like a mathematician's use of "obvious" - which quite often isn't ;-))
> Using assignment expressions in argument defaults is well-defined but
> not necessarily obvious in a similar way (to me, at least).

When you say "assignment expressions", do you mean "default
expressions", or are you referring to the walrus operator? There's a
lot of other potentially-surprising behaviour if you mix assignment
expressions in with this, because of the difference of scope. It's the
sort of thing that can definitely be figured out, but I would advise
against it.

def frob(items=>[], n=>len(items:=[])):

This will reassign items to be an empty list if n is omitted.
Obviously that's bad code, but in general, I think assignment
expressions inside default expressions are likely to be very
surprising :)

> > The only way for it to be confusing is to have => on one argument and
> > then = on a subsequent argument, *and* to have the earlier one refer
> > to the later one.
>
> For you, maybe. I assert that the forms above *are* confusing for me.
> You're welcome to explain them to me, like you have, and maybe I'll
> now remember the logic for the future, but as a data point, I stand by
> my statement that these were confusing to me when I encountered them
> fresh.

Then let's leave aside the term "obvious" and just go for
"unsurprising". If you write code and get UnboundLocalError, will you
be surprised that it doesn't work? If you write code and it works,
will you be surprised with the result you got?

Once you learn the basic idea of left-to-right evaluation, it should
be possible to try things out and get unsurprising results. That's
what I'm hoping for.

> Feel free to state that there's not *enough* cases of people
> being confused by the semantics to outweigh the benefits, but it feels
> to me that there are a few people claiming confusion here, and simply
> saying "you shouldn't be confused, it's obvious" isn't really
> addressing the point.

Part of the problem is that one person seems to think that Python will
completely change its behaviour, and he's spreading misinformation.
Ignore him, look just at the proposal itself, and tell me if it's
still confusing.

> > > Even if someone *can* provide an answer, I'd be reluctant to accept
> > > that any answer could be described as "intuitive". And "well, don't do
> > > that" is just ducking the question - in essentially the same way as
> > > "it's implementation defined" does...
> >
> > But "don't do that" is a perfectly reasonable response to other kinds
> > of bad code, like messing up your spacing:
> >
> > x = 1+2 * 3+4
> >
> > Is this intuitive? Some people will think that x should be 21, but the
> > actual answer is 11. Python won't stop you from doing this, but style
> > guides absolutely should.
>
> But that's not the same as you leaving the behaviour implementation
> defined. In the case of operator precedence, there *is* a well-defined
> answer, but the spacing doesn't match that interpretation.

That IS the concern when people are talking about what's "intuitive" though.

> But in the case of
>
> frob(n=>len(items), items=())
>
> you're refusing to give a well-defined semantics, and then saying that
> people shouldn't do that. But unlike spacing of expressions, the order
> of arguments is *important* - it is part of the API of frob that the
> first positional argument is n, so "just swap the arguments" is a
> semantic change. So how should people get the ("obvious") intended
> behaviour? Abandon the new syntax and go back to using None as a
> default? That seems a shame, given that (as I understand it) your
> reference implementation works exactly as I'd want.

The only two possible behaviours are:

1) It does the single obvious thing: n defaults to the length of
items, and items defaults to an empty tuple.
2) It raises UnboundLocalError if you omit n.

To be quite honest, I can't think of any non-toy examples where the
defaults would 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Paul Moore
On Fri, 17 Jun 2022 at 14:15, Chris Angelico  wrote:
>
> There are several ways to make this clearly sane.
>
> # Clearly UnboundLocalError
> def frob(n=>len(items), items=>[]):

Um, I didn't see that as any more obvious than the original example. I
guess I can see it's UnboundLocalError, but honestly that's not
obvious to me.

> # Clearly correct behaviour
> def frob(items=[], n=>len(items)):
> def frob(items=>[], n=>len(items)):

Maybe... I'm not sure I see this as *that* much more obvious, although
I concede that the left-to-right evaluation rule implies it (it feels
like a mathematician's use of "obvious" - which quite often isn't ;-))
Using assignment expressions in argument defaults is well-defined but
not necessarily obvious in a similar way (to me, at least).

> The only way for it to be confusing is to have => on one argument and
> then = on a subsequent argument, *and* to have the earlier one refer
> to the later one.

For you, maybe. I assert that the forms above *are* confusing for me.
You're welcome to explain them to me, like you have, and maybe I'll
now remember the logic for the future, but as a data point, I stand by
my statement that these were confusing to me when I encountered them
fresh. Feel free to state that there's not *enough* cases of people
being confused by the semantics to outweigh the benefits, but it feels
to me that there are a few people claiming confusion here, and simply
saying "you shouldn't be confused, it's obvious" isn't really
addressing the point.

> > Even if someone *can* provide an answer, I'd be reluctant to accept
> > that any answer could be described as "intuitive". And "well, don't do
> > that" is just ducking the question - in essentially the same way as
> > "it's implementation defined" does...
>
> But "don't do that" is a perfectly reasonable response to other kinds
> of bad code, like messing up your spacing:
>
> x = 1+2 * 3+4
>
> Is this intuitive? Some people will think that x should be 21, but the
> actual answer is 11. Python won't stop you from doing this, but style
> guides absolutely should.

But that's not the same as you leaving the behaviour implementation
defined. In the case of operator precedence, there *is* a well-defined
answer, but the spacing doesn't match that interpretation. But in the
case of

frob(n=>len(items), items=())

you're refusing to give a well-defined semantics, and then saying that
people shouldn't do that. But unlike spacing of expressions, the order
of arguments is *important* - it is part of the API of frob that the
first positional argument is n, so "just swap the arguments" is a
semantic change. So how should people get the ("obvious") intended
behaviour? Abandon the new syntax and go back to using None as a
default? That seems a shame, given that (as I understand it) your
reference implementation works exactly as I'd want.

> In the same way, I would strongly recommend that style guides frown
> upon referring to arguments later in the parameter list, even if it
> happens to be legal. I'm just not mandating that the language check
> for this and artificially block it.

You're not *just* recommending this for style guides, you're also
explicitly stating that you refuse to assign semantics to it.

Anyway, all of this is just my opinion. I'm not trying to persuade you
that you're wrong, just to point out that others see things
differently. It's up to you what you do with that information. Change
the PEP or don't, put it back into deferred status or submit it. I'm
not the decision maker here, just a community member whose feedback
will (hopefully) be considered by the SC when making the decision if
the PEP comes to them.

Paul
___
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/VGXSX6GDV46J7JUVOWHZPL2CO6SZYUER/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Jonathan Fine
Steve D'Aprano wrote of an incompleteness in this PEP

This is not just some minor, trivial implementation issue, it cuts right
> to the core of this feature's semantics [...]


For comparison, please look at the PEP for the statistics module. Steve
wrote both PEP and the standard library module. In my opinion the PEP is
deficient in its description of core semantics, and I don't see a reference
implementation prior to acceptance.
https://peps.python.org/pep-0450/

Of course, that was nearly 10 years ago. The recently discussed  problems
with type conversion in the statistics module together with what's missing
in PEP 450 together support Steve's request that the PEP discussed in this
thread be improved, so that we better avoid future problems.

-- 
Jonathan
___
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/Z435E4ZW3GFPNKH5JQFELVWX3J27IG7I/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Fri, 17 Jun 2022 at 23:05, Paul Moore  wrote:
>
> On Fri, 17 Jun 2022 at 13:54, Andrew Jaffe  wrote:
> >
> > Is there a *reason* why you are leaving this unspecified? To put it more
> > baldly, is there any reason (e.g., difficulty of parsing?) why allowing
> > these "forward" references should *not* be allowed? It seems that
> > "n=>len(items), items=[]" might be an important use case.
>
> Am I right in thinking the key issue here is that => is *not* used for
> "items"? So
>
> def frob(n=>len(items), items=[]):
> print(n)
> items.append(1)
>
> gets very complicated to reason about. What does this print?

There are several ways to make this clearly sane.

# Clearly UnboundLocalError
def frob(n=>len(items), items=>[]):

# Clearly correct behaviour
def frob(items=[], n=>len(items)):
def frob(items=>[], n=>len(items)):

The only way for it to be confusing is to have => on one argument and
then = on a subsequent argument, *and* to have the earlier one refer
to the later one.

> Even if someone *can* provide an answer, I'd be reluctant to accept
> that any answer could be described as "intuitive". And "well, don't do
> that" is just ducking the question - in essentially the same way as
> "it's implementation defined" does...

But "don't do that" is a perfectly reasonable response to other kinds
of bad code, like messing up your spacing:

x = 1+2 * 3+4

Is this intuitive? Some people will think that x should be 21, but the
actual answer is 11. Python won't stop you from doing this, but style
guides absolutely should.

In the same way, I would strongly recommend that style guides frown
upon referring to arguments later in the parameter list, even if it
happens to be legal. I'm just not mandating that the language check
for this and artificially block it.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Fri, 17 Jun 2022 at 22:55, Andrew Jaffe  wrote:
>
> First, let me state that I am in favour of the proposal (although still
> mildle prefer the ":=" spelling).
>
> On 17/06/2022 13:33, Chris Angelico wrote:
> > On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano  wrote:
> >>
> >> If we have:
> >> ```
> >> items = ['spam', 'eggs']
> >> def frob(n=>len(items), items=[]):
> >>  print(n)
> >> ```
> >> we cannot even tell whether `frob()` will print 0 or 2 or raise an
> >> exception.
> >
> > It will either print 0 or raise UnboundLocalError. There is no
> > circumstance in which it will legally print 2.
> >
> >> Under the PEP though, this behaviour is underspecified. The PEP
> >> describes this case as implementation dependent. Any of the following
> >> behaviours would be legal when `frob()` is called:
> >>
> >> * n=>len(items) evaluates the parameter `items`, *after* it gets
> >>bound to the default of [], and so n=0 (that is, it has the same
> >>semantics as the status quo);
> >
> > Yes, this is legal.
> >
> >> * n=>len(items) evaluates the parameter `items`, but it isn't bound
> >>to a value yet (because `items` occurs to the right of n), and so
> >>evaluating the default raises (presumably) UnboundLocalError;
> >
> > Yes, this is legal.
> >
> >> * n=>len(items) evaluates the variable items from the surrounding scope,
> >>and so evaluates to n=2; if no such variable exists, it will presumably
> >>raise NameError.
> >
> > No, this makes no sense whatsoever. In Python, a parameter is
> > (effectively) assigned to within the function, and therefore *any*
> > reference to it *must* refer to the local, not to any surrounding
> > scope. Late-bound defaults do not change this fundamental.
>
> I understand this is unambiguous, but it is nonetheless potentially
> confusing: normal, immediate-evaluation arguments do, of course, have
> access to enclosing scope, and so one might be led to believe that this
> is still possible.

That's because immediate-evaluation is like this:

_default = SOME_EXPRESSION
def func(n=None):
if n is None: n = _default

Whereas late evaluation is like this:

def func(n=None):
if n is None: n = SOME_EXPRESSION

Unfortunately, there's not going to be any way to resolve this. The
entire point of this feature is to be able to do things that can't be
done with early evaluation, and that includes referring to other
arguments, so it fundamentally has to be done in the function's scope.
Maybe it would have been convenient for Python to define that function
defaults are *always* evaluated in the function's scope, but (a) that
ship has well and truly sailed, and (b) I'm not sure that that would
be better anyway - the current behaviour lets you do an easy snapshot
by writing something like "i=i", so it has the same name on the inside
that it has on the outside.

For the most part, it's not a problem; scopes are nested, so you can
happily refer to a name in an enclosing scope. Exceptions include
names that are shadowed, class-level names (but you'll usually be able
to write "self.X" or "cls.X" so it's just a difference of spelling),
and possibly some quirks of closures, although most of those are a
consequence of timing rather than scoping.

> >> With the behaviour unspecified, we can't predict whether the above
> >> frob() example is legal or what it will do if it is. It could vary not
> >> only between CPython and other Pythons, but from one version of CPython
> >> and another.
> >
> > That is correct. This issue ONLY happens if a late-bound default
> > refers to an early-bound argument that comes to the right of it in the
> > argument list, and the ONLY possible results are UnboundLocalError and
> > getting the value.
>
> Is there a *reason* why you are leaving this unspecified? To put it more
> baldly, is there any reason (e.g., difficulty of parsing?) why allowing
> these "forward" references should *not* be allowed? It seems that
> "n=>len(items), items=[]" might be an important use case.
>

Yes. The alternative is that I make it
"reference-implementation-defined", and I've seen so much of that that
I don't want to lock that in. Just because the way I happen to have
implemented it allows for the late-bound defaults to refer to
early-bound arguments to their right, I don't want to lock the
language into behaving that way forever; conversely, I don't want to
have a non-compliant reference implementation based on a definition of
"all arguments are assigned left to right", which is much cleaner and
simpler to describe, but a lot harder to implement. I want the
language to be open to the cleaner definition, while permitting the
"arguments are assigned left to right in two stages" implementation as
well.

That's the only distinction though. And if you simply place all
late-bound defaults to the right of all early-bound defaults, there
won't be any problem, ever.

ChrisA
___
Python-ideas mailing list -- 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Paul Moore
On Fri, 17 Jun 2022 at 13:54, Andrew Jaffe  wrote:
>
> Is there a *reason* why you are leaving this unspecified? To put it more
> baldly, is there any reason (e.g., difficulty of parsing?) why allowing
> these "forward" references should *not* be allowed? It seems that
> "n=>len(items), items=[]" might be an important use case.

Am I right in thinking the key issue here is that => is *not* used for
"items"? So

def frob(n=>len(items), items=[]):
print(n)
items.append(1)

gets very complicated to reason about. What does this print?

frob()
frob()
frob(items=[1,2,3,4,5])
frob(3, [])
frob()
frob(3)
frob()

Even if someone *can* provide an answer, I'd be reluctant to accept
that any answer could be described as "intuitive". And "well, don't do
that" is just ducking the question - in essentially the same way as
"it's implementation defined" does...

Paul
___
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/XAUNUGXYCCFU2OXUORMKRPHSRQO5HTX3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Christopher Barker
OT:

On Fri, Jun 17, 2022 at 7:35 AM Rob Cliffe

>
> def for(bar=[] later, baz=timenow() later, bam=inc(baz) later):
> Not only is the second one longer and repetitious, it adds more **words**.
> People are used to distinguishing between words and symbols and do it
> easily.
>

You have just articulated why I find type annotations so hard to read.

Back OT: add annotations to the examples, and it gets worse. I like it or
not, I suspect annotations are becoming “standard”

-CHB
-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/XFT6PXP4SCH5FO3WXAGEIMKOP6PZMIW6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Andrew Jaffe
First, let me state that I am in favour of the proposal (although still 
mildle prefer the ":=" spelling).


On 17/06/2022 13:33, Chris Angelico wrote:

On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano  wrote:


If we have:
```
items = ['spam', 'eggs']
def frob(n=>len(items), items=[]):
 print(n)
```
we cannot even tell whether `frob()` will print 0 or 2 or raise an
exception.


It will either print 0 or raise UnboundLocalError. There is no
circumstance in which it will legally print 2.


Under the PEP though, this behaviour is underspecified. The PEP
describes this case as implementation dependent. Any of the following
behaviours would be legal when `frob()` is called:

* n=>len(items) evaluates the parameter `items`, *after* it gets
   bound to the default of [], and so n=0 (that is, it has the same
   semantics as the status quo);


Yes, this is legal.


* n=>len(items) evaluates the parameter `items`, but it isn't bound
   to a value yet (because `items` occurs to the right of n), and so
   evaluating the default raises (presumably) UnboundLocalError;


Yes, this is legal.


* n=>len(items) evaluates the variable items from the surrounding scope,
   and so evaluates to n=2; if no such variable exists, it will presumably
   raise NameError.


No, this makes no sense whatsoever. In Python, a parameter is
(effectively) assigned to within the function, and therefore *any*
reference to it *must* refer to the local, not to any surrounding
scope. Late-bound defaults do not change this fundamental.


I understand this is unambiguous, but it is nonetheless potentially 
confusing: normal, immediate-evaluation arguments do, of course, have 
access to enclosing scope, and so one might be led to believe that this 
is still possible.



With the behaviour unspecified, we can't predict whether the above
frob() example is legal or what it will do if it is. It could vary not
only between CPython and other Pythons, but from one version of CPython
and another.


That is correct. This issue ONLY happens if a late-bound default
refers to an early-bound argument that comes to the right of it in the
argument list, and the ONLY possible results are UnboundLocalError and
getting the value.


Is there a *reason* why you are leaving this unspecified? To put it more 
baldly, is there any reason (e.g., difficulty of parsing?) why allowing 
these "forward" references should *not* be allowed? It seems that 
"n=>len(items), items=[]" might be an important use case.


Andrew




___
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/TJSC55W4PUBNNOVVEUQHH5YMEWGPAP4S/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Chris Angelico
On Fri, 17 Jun 2022 at 22:14, Steven D'Aprano  wrote:
>
> On Thu, Jun 16, 2022 at 08:31:19AM +1000, Chris Angelico wrote:
> > On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano  wrote:
>
> > > Under the Specification section, the PEP explicitly refers to
> > > behaviour which "may fail, may succeed", and different behaviour which
> > > is "Highly likely to give an error", and states "Using names of later
> > > arguments should not be relied upon, and while this MAY work in some
> > > Python implementations, it should be considered dubious".
> > >
> > > So, yes, the PEP *punts* on the semantics of the feature, explicitly
> > > leaving the specification implementation-dependent.
> > >
> >
> > One very very specific aspect of it is left undefined. Are you really
> > bothered by that?
>
> Yes.
>
> This is not just some minor, trivial implementation issue, it cuts right
> to the core of this feature's semantics:
>
> * Which arguments can a late-bound parameter access?

Definitely those that come before it. Potentially some of those that
come after it, but I'm not mandating that.

> * When the late-bound default is evaluated, what is the name resolution
>   rule? (Which variables from which scopes will be seen?)

Exactly the same as any other code executed in the function. I really
don't see why this is so surprising to you; it is *exactly the normal
behaviour of Python code*.

> These are fundamental details related to the meaning of code, not relatively
> minor details such as the timing of when a destructor will run.

They're exactly as fundamental, actually. The 'with' statement was
added to the language specifically because it was critically important
to clean things up in ways that CPython does, but Python does not
guarantee.

In my reference implementation, more is available than the PEP
guarantees. That's all.

> If we have:
>
> ```
> items = ['spam', 'eggs']
> def frob(n=>len(items), items=[]):
> print(n)
>
> ```
>
> we cannot even tell whether `frob()` will print 0 or 2 or raise an
> exception.

It will either print 0 or raise UnboundLocalError. There is no
circumstance in which it will legally print 2.

> I described this underspecification as a weakness of the PEP. As I said
> at the time, that was my opinion. As the PEP author, of course it is
> your perogative to leave the semantics of this feature underspecified,
> hoping that the Steering Council will be happy with implementation-
> dependent semantics.

It's a lot less implementation-dependent than you seem to think.

> For the benefit of other people reading this, in case it isn't clear,
> let me try to explain what the issue is.
>
> When late-bound defaults are simulated with the `is None` trick, we
> write:
>
> ```
> def frob(n=None, items=[]):
> # If we enter the body of the function,
> # items is guaranteed to have a value.
> if n is None:
> n = len(items)
> print(n)
> ```
>
> and there is never any doubt about the scoping rules for `len(items)`.
> It always refers to the parameter `items`, never to the variable in the
> surrounding scope, and because that parameter is guaranteed to be bound
> to a value, so the simulated default `len(items)` cannot fail with
> NameError. We can reason about the code's meaning very easily.

This is exactly the same. I don't understand what's confusing here.

> If we want "real" late-bound defaults to match that behaviour,
> `n=>len(items)` must evaluate `len(items)` *after* items is bound
> to a value, even though items occurs to the right of n.

Yes, and the ONLY part that is underspecified is the order. It is
perfectly legal for it to be implemented in either of these ways:

def frob():
n = len(items)
items = []

def frob():
items = []
n = len(items)

And I would consider code that depends on specifically one or the
other to be bad code, just like code that depends on __del__ methods
being called.

What wording could I add to the PEP to make this more obvious?

> Under the PEP though, this behaviour is underspecified. The PEP
> describes this case as implementation dependent. Any of the following
> behaviours would be legal when `frob()` is called:
>
> * n=>len(items) evaluates the parameter `items`, *after* it gets
>   bound to the default of [], and so n=0 (that is, it has the same
>   semantics as the status quo);

Yes, this is legal.

> * n=>len(items) evaluates the parameter `items`, but it isn't bound
>   to a value yet (because `items` occurs to the right of n), and so
>   evaluating the default raises (presumably) UnboundLocalError;

Yes, this is legal.

> * n=>len(items) evaluates the variable items from the surrounding scope,
>   and so evaluates to n=2; if no such variable exists, it will presumably
>   raise NameError.

No, this makes no sense whatsoever. In Python, a parameter is
(effectively) assigned to within the function, and therefore *any*
reference to it *must* refer to the local, not to any surrounding
scope. Late-bound defaults do not change 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Steven D'Aprano
On Thu, Jun 16, 2022 at 08:31:19AM +1000, Chris Angelico wrote:
> On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano  wrote:

> > Under the Specification section, the PEP explicitly refers to
> > behaviour which "may fail, may succeed", and different behaviour which
> > is "Highly likely to give an error", and states "Using names of later
> > arguments should not be relied upon, and while this MAY work in some
> > Python implementations, it should be considered dubious".
> >
> > So, yes, the PEP *punts* on the semantics of the feature, explicitly
> > leaving the specification implementation-dependent.
> >
> 
> One very very specific aspect of it is left undefined. Are you really
> bothered by that?

Yes.

This is not just some minor, trivial implementation issue, it cuts right 
to the core of this feature's semantics:

* Which arguments can a late-bound parameter access?

* When the late-bound default is evaluated, what is the name resolution 
  rule? (Which variables from which scopes will be seen?)

These are fundamental details related to the meaning of code, not relatively
minor details such as the timing of when a destructor will run.


If we have:

```
items = ['spam', 'eggs']
def frob(n=>len(items), items=[]):
print(n)

```

we cannot even tell whether `frob()` will print 0 or 2 or raise an 
exception.

I described this underspecification as a weakness of the PEP. As I said 
at the time, that was my opinion. As the PEP author, of course it is 
your perogative to leave the semantics of this feature underspecified, 
hoping that the Steering Council will be happy with implementation- 
dependent semantics.

For the benefit of other people reading this, in case it isn't clear, 
let me try to explain what the issue is.

When late-bound defaults are simulated with the `is None` trick, we 
write:

```
def frob(n=None, items=[]):
# If we enter the body of the function,
# items is guaranteed to have a value.
if n is None:
n = len(items)
print(n)
```

and there is never any doubt about the scoping rules for `len(items)`. 
It always refers to the parameter `items`, never to the variable in the 
surrounding scope, and because that parameter is guaranteed to be bound 
to a value, so the simulated default `len(items)` cannot fail with 
NameError. We can reason about the code's meaning very easily.

If we want "real" late-bound defaults to match that behaviour, 
`n=>len(items)` must evaluate `len(items)` *after* items is bound 
to a value, even though items occurs to the right of n.

Under the PEP though, this behaviour is underspecified. The PEP 
describes this case as implementation dependent. Any of the following 
behaviours would be legal when `frob()` is called:

* n=>len(items) evaluates the parameter `items`, *after* it gets
  bound to the default of [], and so n=0 (that is, it has the same
  semantics as the status quo);

* n=>len(items) evaluates the parameter `items`, but it isn't bound
  to a value yet (because `items` occurs to the right of n), and so
  evaluating the default raises (presumably) UnboundLocalError;

* n=>len(items) evaluates the variable items from the surrounding scope,
  and so evaluates to n=2; if no such variable exists, it will presumably
  raise NameError.

With the behaviour unspecified, we can't predict whether the above 
frob() example is legal or what it will do if it is. It could vary not 
only between CPython and other Pythons, but from one version of CPython 
and another.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-17 Thread Steven D'Aprano
On Fri, Jun 17, 2022 at 02:36:48AM -, Steve Jorgensen wrote:

> Is there anything that I can do, as a random Python user to help move 
> this to the next stage?

If you think the PEP is as complete and persuasive as possible right 
now, you can offer moral support and encouragement. Or you can suggest 
some improvements, and see whether the PEP author agrees.

It is up to the PEP author to decide whether, in his opinion, the PEP is 
sufficiently complete to move forward, or whether it needs more work. 
Other options include leaving it deferred/incomplete, to withdraw it, or 
solicit for somebody to take it over.

If the PEP author abandons it, you could ask to take it over, or you 
could write your own competing PEP as an alternative.

If the author decides to move forward, he needs to ask for a core dev to 
sponsor it. Assuming he gets one, that will start the next round of 
debate, followed by a request to the Steering Council to make a decision 
whether to accept it as is, demand some changes, or reject it.



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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-16 Thread Rob Cliffe via Python-ideas



On 15/06/2022 23:01, Steven D'Aprano wrote:

On Wed, Jun 15, 2022 at 01:58:28PM +0100, Rob Cliffe via Python-ideas wrote:

Please.  This has been many times by several people already.  No-one is
going to change their mind on this by now.  There's no point in
rehashing it and adding noise to the thread.

Rob, there's no rule that only "people who support this PEP" are allowed
to comment. If it is okay for you to say you like this PEP even more now
than previously, it is okay for David to say that his opinion hasn't
changed.

Of course I wasn't saying that some people aren't allowed to comment.
What I was objecting to was the rehashing of old arguments  which have 
already been done to death.  I refrained, at the time, from offering 
counter-arguments, because those have been done to death too.

  Especially since David even pointed out one potential change
which might lead him to support the PEP, or at least shift to "neutral".


You are quite right Steven, and perhaps I was too hasty, didn't pay 
enough attention to David's suggestion, and failed to address it. Well, 
let me address it now.  I am afraid I can't do so without repeating some 
of my old arguments and thus doing exactly what I asked David not to do, 
but he has made a suggestion and it merits being answered.  Thank you 
for contributing to this thread, David.


"I believe a general "deferred computation" mechanism is useful, but 
that one limited to the context of function parameters does more harm 
than good is scoped narrowly to that single use.  I keyword version 
might bridge that gap by introducing "later" or "defer" or "delay" in a 
narrow context, but not foreclosing its later use more broadly."  [DM]


The bar for adding a new hard keyword to Python is very high.
The suggestion is to add a new keyword to a PEP which absolutely doesn't 
need it, on the grounds that it **might** (**not** would - we can't know 
without a spec) give compatibility with some fictional vapourware which 
- for all people keep talking about it - hasn't happened in years, isn't 
happening (AFAIK nobody is working on it), doesn't have anything 
remotely close to even an outline specification (people disagree as to 
what it should do), very likely never will happen, and at best won't 
happen for years.
And if it does, what's the **worst** that could happen?  We would have 
two ways of writing the same thing!  Terrible!  Well, we already have 
that in effect (yes, I know they generate different compiled code):

    x = 42
    (x := 42)
    {}
    dict() # similarly for list, tuple
and I expect there are a host of other examples I can't bring to mind at 
the moment,

and the sky hasn't fallen.
I'm sorry, but if that's what it takes to make David or anyone else less 
opposed to the PEP, it ain't worth it.  Not remotely close.


So It could be a soft keyword, you say?  OK, AFAICS that could work.  
But let me note in passing that if we consider 4 possible syntaxes:

    def func(later parm = default):    # Number 1
    def func(parm later = default):    # Number 2
    def func(parm = later default):    # Number 3
    def func(parm = default later):    # Number 4
Number 3, which some might find the most attractive, won't work. Consider:
    def f(x = later -y):
Is that a late-bound default of -y?  Bad luck; it's already legal syntax 
for an early-bound default of `later` minus `y`.

AFAICS the others are possible.
If you have some other syntax in mind, David, please specify.

But (and AFAIK this has not been said before) let's think about this 
supposed "consistency".  Let's suppose we have a bright-and-shiny, 
up-and-running delayed evaluation scheme.  I imagine (and again, if this 
is not what you have in mind, David, please specify) it would allow you 
to write something like

    x = expression later
which would assign to x some entity, a "deferred evaluation object" 
(DEO), probably containing a code object, which would allow the 
expression to be evaluated at some future time (and possibly in some 
different scope, but let's not go there now).  On the principle of least 
surprise, one would want "expression later" to be a Python expression, 
and to behave as far as possible in the same way in different contexts.  
So you could write stuff like

    x = y = expression later
    someTuple = (expression1 later, expression2 later)
and so on.
(It's not relevant to my point, but I can't imagine wanting syntax like 
Number 1 or Number 2 above:
    later x = expression # value of expression to be calculated and 
assigned to x at some future time

What would these mean, if legal:
    later x = y = expression
    x = later y = expression
    later x = later y = expression
).
But when I use that same syntax *in a function signature*:
    def f(x = expression later):
and then call f(), I do **not** (in most cases) want the default value 
of x to be a DEO.  I want it evaluated NOW, at function call time.  So 
where is the consistency?  There isn't any. It's a myth.  Of 

[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-16 Thread Rob Cliffe via Python-ideas

On 17/06/2022 04:23, David Mertz, Ph.D. wrote:

I've been scolded that I'm not allowed to post unless I support the PEP.

Please do not misrepresent me.  That is NOT what I said.
Rob Cliffe

Nonetheless, I reiterate that I oppose it. There is no "preponderance" 
of support, but perhaps a slim majority of the small number who have 
commented (5 vs 3, I think).


On Thu, Jun 16, 2022, 10:38 PM Steve Jorgensen  
wrote:


Is there anything that I can do, as a random Python user to help
move this to the next stage? I'm happy to go along with whatever
the preponderance of responses here seem to think in terms of
which syntax choice is best. Although I have a slight preference,
all of the options seem decent to me.

I am definitely in favor of having the PEP accepted and implemented.
___
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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/
Code of Conduct: http://python.org/psf/codeofconduct/


___
Python-ideas mailing list --python-ideas@python.org
To unsubscribe send an email topython-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-ideas@python.org/message/73JW7MNPPHIOCMOFCTD34Z5YMK7ESNS5/
Code of Conduct:http://python.org/psf/codeofconduct/
___
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/2NDF7ER6MJWDHAFQNI7RP7L322OTXJZU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-16 Thread David Mertz, Ph.D.
I've been scolded that I'm not allowed to post unless I support the PEP.
Nonetheless, I reiterate that I oppose it. There is no "preponderance" of
support, but perhaps a slim majority of the small number who have commented
(5 vs 3, I think).

On Thu, Jun 16, 2022, 10:38 PM Steve Jorgensen  wrote:

> Is there anything that I can do, as a random Python user to help move this
> to the next stage? I'm happy to go along with whatever the preponderance of
> responses here seem to think in terms of which syntax choice is best.
> Although I have a slight preference, all of the options seem decent to me.
>
> I am definitely in favor of having the PEP accepted and implemented.
> ___
> 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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
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/73JW7MNPPHIOCMOFCTD34Z5YMK7ESNS5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-16 Thread Steve Jorgensen
Is there anything that I can do, as a random Python user to help move this to 
the next stage? I'm happy to go along with whatever the preponderance of 
responses here seem to think in terms of which syntax choice is best. Although 
I have a slight preference, all of the options seem decent to me.

I am definitely in favor of having the PEP accepted and implemented.
___
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/5572SP7T2GR5PYIVTYN5VESHV5XJ2JA5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Chris Angelico
On Thu, 16 Jun 2022 at 08:25, Steven D'Aprano  wrote:
>
> On Thu, Jun 16, 2022 at 12:02:04AM +1000, Chris Angelico wrote:
> > On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano  wrote:
> > > There's no consensus that this feature is worth the added complexity, or
> > > even what the semantics are. The PEP punts on the semantics, saying that
> > > the behaviour may vary across implementations.
> >
> > Excuse me? I left one or two things open-ended, where they're bad code
> > and I'm not going to lock the language into supporting them just
> > because the reference implementation happens to be able to, but
> > "punts"? That's a bit much. The semantics are QUITE specific.
>
> Under the Specification section, the PEP explicitly refers to
> behaviour which "may fail, may succeed", and different behaviour which
> is "Highly likely to give an error", and states "Using names of later
> arguments should not be relied upon, and while this MAY work in some
> Python implementations, it should be considered dubious".
>
> So, yes, the PEP *punts* on the semantics of the feature, explicitly
> leaving the specification implementation-dependent.
>

One very very specific aspect of it is left undefined. Are you really
bothered by that? I don't understand how you can dare to write a
single line of code, given how many other things are actually not
specified. Have you ever written a __del__ method? Python *does not
guarantee* when it will be called. Wow! Python is hopelessly
implementation-dependent, there's no WAY this should ever be used!

And then you take this tiny point where I left it open to implementers
to choose, and you say that the PEP "punts on the semantics" as if the
entire specification is in doubt.

I'm trying as hard as I can to believe that you're arguing in good
faith, but it's getting less and less plausible.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Steven D'Aprano
On Thu, Jun 16, 2022 at 12:02:04AM +1000, Chris Angelico wrote:
> On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano  wrote:
> > There's no consensus that this feature is worth the added complexity, or
> > even what the semantics are. The PEP punts on the semantics, saying that
> > the behaviour may vary across implementations.
> 
> Excuse me? I left one or two things open-ended, where they're bad code
> and I'm not going to lock the language into supporting them just
> because the reference implementation happens to be able to, but
> "punts"? That's a bit much. The semantics are QUITE specific.

Under the Specification section, the PEP explicitly refers to 
behaviour which "may fail, may succeed", and different behaviour which 
is "Highly likely to give an error", and states "Using names of later 
arguments should not be relied upon, and while this MAY work in some 
Python implementations, it should be considered dubious".

So, yes, the PEP *punts* on the semantics of the feature, explicitly 
leaving the specification implementation-dependent.


> > There's no consensus on the syntax, which may not matter, the Steering
> > Council can make the final decision if necessary. But with at least four
> > options in the PEP it would be good to narrow it down a bit. No soft
> > keywords have been considered.
> 
> """Choice of spelling. While this document specifies a single syntax
> `name=>expression`..."""
> 
> The PEP specifies *one* option.

The part of the sentence you replaced with an ellipsis says "alternate 
spellings are similarly plausible." The very next sentence says

"Open for consideration are the following"

and a couple of paragraphs later you even explicitly refer to a 
second proof of concept implemention.

The PEP has a preferred syntax, as is its right, but it lists three 
alternatives still under consideration.


-- 
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/23N2VZFHWOLR6ZKFMOU26QXFSFHSY7I4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Steven D'Aprano
On Wed, Jun 15, 2022 at 01:58:28PM +0100, Rob Cliffe via Python-ideas wrote:
> Please.  This has been many times by several people already.  No-one is 
> going to change their mind on this by now.  There's no point in 
> rehashing it and adding noise to the thread.

Rob, there's no rule that only "people who support this PEP" are allowed 
to comment. If it is okay for you to say you like this PEP even more now 
than previously, it is okay for David to say that his opinion hasn't 
changed. Especially since David even pointed out one potential change 
which might lead him to support the PEP, or at least shift to "neutral".


-- 
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/42PANNPF4YTDOQQ76BWUPFRVV7YGBUAQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Chris Angelico
On Wed, 15 Jun 2022 at 22:38, Steven D'Aprano  wrote:
> There's no consensus that this feature is worth the added complexity, or
> even what the semantics are. The PEP punts on the semantics, saying that
> the behaviour may vary across implementations.

Excuse me? I left one or two things open-ended, where they're bad code
and I'm not going to lock the language into supporting them just
because the reference implementation happens to be able to, but
"punts"? That's a bit much. The semantics are QUITE specific.

> There's no consensus on the syntax, which may not matter, the Steering
> Council can make the final decision if necessary. But with at least four
> options in the PEP it would be good to narrow it down a bit. No soft
> keywords have been considered.

"""Choice of spelling. While this document specifies a single syntax
`name=>expression`..."""

The PEP specifies *one* option.

> In my opinion, there are weaknesses in the PEP:
>
> - lack of any reference to previous discussions;
>
> - no attempt to gather feedback from other forums;
>
> - no review of languages that offer choice of early or late binding;
>
> - little attempt to justify why this is better than the status quo; the
>   PEP seems to take the position that it is self-evident that Python
>   needs this feature, rather than being a balanced document setting out
>   both pros and cons;
>
> - little or no attempt in the PEP to answer objections;
>
> - examples are all chosen to show the feature in the best possible
>   light, rather than to show both the good and bad; (e.g. no examples
>   show the parameter with annotations)
>
> - failure to acknowledge that at least one of the suggested syntaxes
>   is visually ambiguous with existing syntax.
>
> E.g. this would be legal with the PEP's second choice of spelling:
>
> def func(spam, eggs:=(x:=spam)):
>
> Even if the parser can distinguish the two uses of `:=` there, its
> awfully cryptic. In and of itself, that's not necessarily a fatal flaw
> (e.g. slicing) but the benefits have to outweigh the negatives, and the
> PEP should be a balanced discussion of both.

And that's not the recommended syntax anyway.

Please, if you're going to criticize the document, *at least* have the
decency to check your facts.

You are the PRIMARY reason that I gave up pushing this earlier. I am
within a very short span of blocking you in my mail client and
refusing to respond to your emails, because it feels like a massive
waste of my time trying.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Paul Moore
On Wed, 15 Jun 2022 at 14:04, Rob Cliffe via Python-ideas
 wrote:
>
> Please.  This has been many times by several people already.  No-one is going 
> to change their mind on this by now.  There's no point in rehashing it and 
> adding noise to the thread.

To be fair, the only real point in re-opening the discussion at all is
to determine if anyone has changed their mind. That said, IMO it's
unlikely that enough time has passed for that to have happened, so
it's unlikely that anything productive will come from this new thread.

Paul
___
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/KITPPSXCDQBTI3HJCZHLFEAU2RLJOY4W/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Rob Cliffe via Python-ideas
Please.  This has been many times by several people already.  No-one is 
going to change their mind on this by now.  There's no point in 
rehashing it and adding noise to the thread.

Best wishes
Rob Cliffe

On 15/06/2022 13:43, David Mertz, Ph.D. wrote:
As well as all the matters Steven raises, I continue to dislike the 
proposal for the same reason I did on earlier rounds.  I believe a 
general "deferred computation" mechanism is useful, but that one 
limited to the context of function parameters does more harm than good 
is scoped narrowly to that single use.  I keyword version might bridge 
that gap by introducing "later" or "defer" or "delay" in a narrow 
context, but not foreclosing its later use more broadly.


On Wed, Jun 15, 2022 at 8:38 AM Steven D'Aprano  
wrote:


On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via
Python-ideas wrote:

> I used to prefer `:=` but coming back to this topic after a long
> interval I am happy with `=>` and perhaps I even like it more,
Chris.
> The PEP status is "Draft".  What are the chances of something
happening
> any time soon, i.e. the PEP being considered by the Steering
Committee?

There's no Sponsor, so it isn't being considered by the SC. That
much is
objectively true.

Beyond that, the following is all my personal opinion, and should
not be
taken as definitive or official in any way. Importantly, I have *not*
read back through the entire thread to refresh my memory. However, I
have re-read the PEP in detail.

There's no consensus that this feature is worth the added
complexity, or
even what the semantics are. The PEP punts on the semantics,
saying that
the behaviour may vary across implementations.

There's no consensus on the syntax, which may not matter, the
Steering
Council can make the final decision if necessary. But with at
least four
options in the PEP it would be good to narrow it down a bit. No soft
keywords have been considered.

In my opinion, there are weaknesses in the PEP:

- lack of any reference to previous discussions;

- no attempt to gather feedback from other forums;

- no review of languages that offer choice of early or late binding;

- little attempt to justify why this is better than the status
quo; the
  PEP seems to take the position that it is self-evident that Python
  needs this feature, rather than being a balanced document
setting out
  both pros and cons;

- little or no attempt in the PEP to answer objections;

- examples are all chosen to show the feature in the best possible
  light, rather than to show both the good and bad; (e.g. no examples
  show the parameter with annotations)

- failure to acknowledge that at least one of the suggested syntaxes
  is visually ambiguous with existing syntax.

E.g. this would be legal with the PEP's second choice of spelling:

    def func(spam, eggs:=(x:=spam)):

Even if the parser can distinguish the two uses of `:=` there, its
awfully cryptic. In and of itself, that's not necessarily a fatal
flaw
(e.g. slicing) but the benefits have to outweigh the negatives,
and the
PEP should be a balanced discussion of both.



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



--
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.

___
Python-ideas mailing list --python-ideas@python.org
To unsubscribe send an email topython-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived 
athttps://mail.python.org/archives/list/python-ideas@python.org/message/V2WTEHWFOL5LTW76QVGYMAGSNUAHOR6R/
Code of Conduct:http://python.org/psf/codeofconduct/
___
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/HRHMR4HEMI3JCNMDYMEJ42PFDWXD7346/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread David Mertz, Ph.D.
As well as all the matters Steven raises, I continue to dislike the
proposal for the same reason I did on earlier rounds.  I believe a general
"deferred computation" mechanism is useful, but that one limited to the
context of function parameters does more harm than good is scoped narrowly
to that single use.  I keyword version might bridge that gap by introducing
"later" or "defer" or "delay" in a narrow context, but not foreclosing its
later use more broadly.

On Wed, Jun 15, 2022 at 8:38 AM Steven D'Aprano  wrote:

> On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via Python-ideas
> wrote:
>
> > I used to prefer `:=` but coming back to this topic after a long
> > interval I am happy with `=>` and perhaps I even like it more, Chris.
> > The PEP status is "Draft".  What are the chances of something happening
> > any time soon, i.e. the PEP being considered by the Steering Committee?
>
> There's no Sponsor, so it isn't being considered by the SC. That much is
> objectively true.
>
> Beyond that, the following is all my personal opinion, and should not be
> taken as definitive or official in any way. Importantly, I have *not*
> read back through the entire thread to refresh my memory. However, I
> have re-read the PEP in detail.
>
> There's no consensus that this feature is worth the added complexity, or
> even what the semantics are. The PEP punts on the semantics, saying that
> the behaviour may vary across implementations.
>
> There's no consensus on the syntax, which may not matter, the Steering
> Council can make the final decision if necessary. But with at least four
> options in the PEP it would be good to narrow it down a bit. No soft
> keywords have been considered.
>
> In my opinion, there are weaknesses in the PEP:
>
> - lack of any reference to previous discussions;
>
> - no attempt to gather feedback from other forums;
>
> - no review of languages that offer choice of early or late binding;
>
> - little attempt to justify why this is better than the status quo; the
>   PEP seems to take the position that it is self-evident that Python
>   needs this feature, rather than being a balanced document setting out
>   both pros and cons;
>
> - little or no attempt in the PEP to answer objections;
>
> - examples are all chosen to show the feature in the best possible
>   light, rather than to show both the good and bad; (e.g. no examples
>   show the parameter with annotations)
>
> - failure to acknowledge that at least one of the suggested syntaxes
>   is visually ambiguous with existing syntax.
>
> E.g. this would be legal with the PEP's second choice of spelling:
>
> def func(spam, eggs:=(x:=spam)):
>
> Even if the parser can distinguish the two uses of `:=` there, its
> awfully cryptic. In and of itself, that's not necessarily a fatal flaw
> (e.g. slicing) but the benefits have to outweigh the negatives, and the
> PEP should be a balanced discussion of both.
>
>
>
> --
> 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/V5K2JFT44A57ZXV2GS3OS6MQW2YKXMQN/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
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/V2WTEHWFOL5LTW76QVGYMAGSNUAHOR6R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Steven D'Aprano
On Tue, Jun 14, 2022 at 11:59:44AM +0100, Rob Cliffe via Python-ideas wrote:

> I used to prefer `:=` but coming back to this topic after a long 
> interval I am happy with `=>` and perhaps I even like it more, Chris.
> The PEP status is "Draft".  What are the chances of something happening 
> any time soon, i.e. the PEP being considered by the Steering Committee?  

There's no Sponsor, so it isn't being considered by the SC. That much is 
objectively true.

Beyond that, the following is all my personal opinion, and should not be 
taken as definitive or official in any way. Importantly, I have *not* 
read back through the entire thread to refresh my memory. However, I 
have re-read the PEP in detail.

There's no consensus that this feature is worth the added complexity, or 
even what the semantics are. The PEP punts on the semantics, saying that 
the behaviour may vary across implementations.

There's no consensus on the syntax, which may not matter, the Steering 
Council can make the final decision if necessary. But with at least four 
options in the PEP it would be good to narrow it down a bit. No soft 
keywords have been considered.

In my opinion, there are weaknesses in the PEP:

- lack of any reference to previous discussions;

- no attempt to gather feedback from other forums;

- no review of languages that offer choice of early or late binding;

- little attempt to justify why this is better than the status quo; the 
  PEP seems to take the position that it is self-evident that Python 
  needs this feature, rather than being a balanced document setting out
  both pros and cons;

- little or no attempt in the PEP to answer objections;

- examples are all chosen to show the feature in the best possible 
  light, rather than to show both the good and bad; (e.g. no examples
  show the parameter with annotations)

- failure to acknowledge that at least one of the suggested syntaxes
  is visually ambiguous with existing syntax.

E.g. this would be legal with the PEP's second choice of spelling:

def func(spam, eggs:=(x:=spam)):

Even if the parser can distinguish the two uses of `:=` there, its 
awfully cryptic. In and of itself, that's not necessarily a fatal flaw 
(e.g. slicing) but the benefits have to outweigh the negatives, and the 
PEP should be a balanced discussion of both.



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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Steven D'Aprano
On Mon, Jun 13, 2022 at 07:41:12AM -0400, Todd wrote:

> This has been proposed many times. You can check the mailing list history.
> Such proposals have been even less popular then PEP 671, since it requires
> a new keyword, which is generally avoided at nearly all costs,

Now that Python is using a PEG parser, adding a soft keyword is no big 
deal. We could use a named keyword:

def spam(arg = defer default_expression):
pass

without affecting code that used "defer" as a variable or function name. 
We could even write:

def spam(defer = defer defer()): ...

where the same word "defer" refers to a parameter, a soft keyword, and a 
function call, all in the same function signature. Needless to say one 
should not make a habit of this. But it would be allowed.


-- 
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/5V2SEWXFCVDI6RHBVX4QME4ZAYL4NPPO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Steven D'Aprano
On Wed, Jun 15, 2022 at 10:44:28AM -, Mathew Elman wrote:

> Could this be the behaviour of passing in an Ellipsis? e.g.
> 
> def foo(defaults_to_one=1):
> return defaults_to_one
> 
> assert foo(...) == foo()

It isn't clear to me whether your question is a request for clarification
(does the PEP mean this...?) or a request for a change in behaviour
(could you change the PEP to do this...?).

Why would you want to type `foo(...)` when you could just type `foo()`?


> The only place that I am aware of the Ellipsis being used is in index 
> notation (numpy).
> So this would have likely an impact on __getitem__ or the slice object.

Ellipsis has been around for over twenty years so we have to assume it 
would have an impact on thousands of programs. We don't just care about 
famous, popular libraries like numpy, we care about breaking little 
scripts used by one person too.


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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Chris Angelico
On Wed, 15 Jun 2022 at 20:45, Mathew Elman  wrote:
>
> Could this be the behaviour of passing in an Ellipsis? e.g.
>
> def foo(defaults_to_one=1):
> return defaults_to_one
>
> assert foo(...) == foo()
>
> def bar(something=...):
> return foo(something)
>
> assert bar() == foo()
>
> def baz(arg):  # no defaults
> return arg
>
> assert baz(...) == ...
>
> The only place that I am aware of the Ellipsis being used is in index 
> notation (numpy).
> So this would have likely an impact on __getitem__ or the slice object.
>
> *Alternatively* a subtype of Ellipses specifically for when used in argument 
> defaults DefaultEllipsis (or equivalent):
> def foo(x=...):
> return x
>
> assert isinstance(foo(), EllipsisType)
> assert foo() != Ellipsis
>
> assert isinstance(foo(...), EllipsisType)
> assert foo(...) == Ellipsis

No, because Ellipsis is a very real object and could be passed as a
parameter at any time. Although, since it's unusual, it's actually a
slightly deoptimized case in my reference implementation - or rather,
whenever a function observes that it's been passed Ellipsis, it checks
to see if the parameter was actually omitted.

Fundamentally, Python does not have any value that indicates the lack
of a value. And having worked with a number of JavaScript APIs where
undefined is used as "absent", I don't want to inflict that on anyone.
(For instance, classList.toggle("some-class", X) will add the class if
X is truthy, remove it if it's falsy, but... toggle if X is undefined.
Which is otherwise falsy. Extremely annoying to try to track down.)
The standard way in Python to indicate "no value" is to raise an
exception instead of returning, but that doesn't work for parameters.

You can use sequence unpacking to achieve that sort of effect, though.

foo(*([] if x is ... else [x]))

This will skip the parameter if x is Ellipsis. Obviously, you use this
only when you know you'll never use Ellipsis as an actual value,
though, so this can't be done in the language, but it could be useful.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-15 Thread Mathew Elman
Could this be the behaviour of passing in an Ellipsis? e.g.

def foo(defaults_to_one=1):
return defaults_to_one

assert foo(...) == foo()

def bar(something=...):
return foo(something)

assert bar() == foo()

def baz(arg):  # no defaults
return arg

assert baz(...) == ...

The only place that I am aware of the Ellipsis being used is in index notation 
(numpy).
So this would have likely an impact on __getitem__ or the slice object.

*Alternatively* a subtype of Ellipses specifically for when used in argument 
defaults DefaultEllipsis (or equivalent):
def foo(x=...):
return x

assert isinstance(foo(), EllipsisType)
assert foo() != Ellipsis

assert isinstance(foo(...), EllipsisType)
assert foo(...) == Ellipsis
___
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/C2L3COISYSSVFAYXRFVVNPFBBOQYXVQU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-14 Thread Chris Angelico
On Tue, 14 Jun 2022 at 21:00, Rob Cliffe via Python-ideas
 wrote:
>
> I used to prefer `:=` but coming back to this topic after a long
> interval I am happy with `=>` and perhaps I even like it more, Chris.
> The PEP status is "Draft".  What are the chances of something happening
> any time soon, i.e. the PEP being considered by the Steering Committee?
> Or is it still too controversial, or is there some other obstacle?
> In case it's not clear, I support the PEP.  I think it plugs an obvious gap.

The main obstacle is that I got weary of responding to emails on it,
put it on the back burner, and let the topic go cold.

To revive it, what I'd recommend is: Go through the PEP and figure out
everything that *you* would need to see done before *you* would
approve it, supposing that you were a member of the SC. Then either
suggest wording changes, or at least list your concerns, and we can
reopen the discussion.

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


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-14 Thread Rob Cliffe via Python-ideas
I used to prefer `:=` but coming back to this topic after a long 
interval I am happy with `=>` and perhaps I even like it more, Chris.
The PEP status is "Draft".  What are the chances of something happening 
any time soon, i.e. the PEP being considered by the Steering Committee?  
Or is it still too controversial, or is there some other obstacle?

In case it's not clear, I support the PEP.  I think it plugs an obvious gap.
Best wishes
Rob Cliffe

On 13/06/2022 09:38, Steve Jorgensen wrote:

To clarify my statement about readability of the '@' prefix option…

I think that its meaning is less clear if one doesn't already know what the 
syntax means. I think the code would be easier to skim, however, using that 
option after one does know its meaning.

My favorite options are '@' or '?=' (tied), followed by ':=' followed by '=>'.
___
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/TDPKOPGWQ4ORRJDHWJMX5GMW2TQ5FI5B/
Code of Conduct: http://python.org/psf/codeofconduct/


___
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/KWYUYR3WT3VFUI4CNCGQT6ZZYOIBUPQB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 671 (late-bound arg defaults), next round of discussion!

2022-06-13 Thread Todd
On Sun, Jun 12, 2022, 16:22 Bluenix  wrote:

> I stumbled upon PEP 671 again today, and for what it's worth I fully agree
> with everything said here.
>
> For the same reasons as you listed, I am generally opposed to PEP 671.
> Wrapping functions in one way or another is extremely common and this PEP
> will make a problem which is currently super small much bigger - the
> inability to have a function's defaults apply without messing with `*args`
> and `**kwargs`.
>
> The reason this probably isn't brought up a lot is because of the
> existence of None. A wrapping function can set its default to None matching
> the wrapped function's default. If the wrapped function were to use PEP 671
> this would cause the wrapping function to need to go to dynamic `*args` and
> `**kwargs` to match this behaviour.
>
> JavaScript users can use `undefined` for this; if you pass `undefined` to
> a parameter in JavaScript, the default will be applied. I think that Python
> should have a similar mechanic (but that's another discussion) which would
> need to be added before PEP 671. Together that adds up to being years away
> (because of dependencies minimum Python requirement, etc) and at that point
> I would rather see the current status quo being upheld and PEP 671 deferred.
>
> Tl;Dr PEP 671 makes things worse without other additions



This has been proposed many times. You can check the mailing list history.
Such proposals have been even less popular then PEP 671, since it requires
a new keyword, which is generally avoided at nearly all costs, and requires
it either be restricted to only being used in defs, or will just end up
like None where people are passing it as arguments, which defeats the
purpose.

You may not like PEP-671, but it at least provides a feasible solution.
Using a new special parameter is never going to fly.
___
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/YFONN2M73HZE6CGQL2SYSGBOEK2AJCKQ/
Code of Conduct: http://python.org/psf/codeofconduct/


  1   2   3   4   >