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

2021-12-01 Thread Brendan Barnwell

On 2021-12-01 23:36, Chris Angelico wrote:

That's exactly why it's such a close parallel. The late-evaluated
default is just code, nothing else. It's not "stored" in any way - it
is evaluated as part of the function beginning execution.


	But it IS stored!  There is no way for it to be evaluated without it 
being stored!


	I know we're talking past each other here but it is quite obvious that 
something has to be stored if it is going to be evaluated later.  You 
can say that it is "just code" but that doesn't change the fact that 
that code has to be stored.  You can say that it is just prepended to 
the function body but that's still storing it.  That is still not 
parallel to a ternary operator in which no part of the expression is 
EVER re-executed unless control flow causes execution to return to that 
same source code line and re-execute it as a whole.


	Actually this raises a question that maybe was answered in the earlier 
thread but if so I forgot: if a function has a late-bound default, will 
the code to evaluate it be stored as part of the function's code object?


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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 6:27 PM Brendan Barnwell  wrote:
>
> On 2021-12-01 18:35, Chris Angelico wrote:
> > In my reference implementation, there is no object that stores it;
> > it's simply part of the function. A good parallel is the if/else
> > expression:
> >
> > x = float("inf") if z == 0 else y/z
> >
> > Is there an object that represents the if/else expression (or the
> > deferred "y/z" part)? No, although it could be implemented that way if
> > you chose:
>
> This is not a good parallel.  There is nothing deferred there.  The
> entire line is evaluated when it is encountered and you get a result and
> no part of the if/else expression can ever impact anything else again
> unless, via some external control flow, execution returns and
> re-executes the entire line.  That is not comparable to a function
> default, which is STORED and evaluated later independently of the
> context in which it was originally written (i.e., the function default
> is re-executed but the function definition itself is not re-executed).
>
> The ternary expression vanishes without a trace by the next line,
> leaving only its evaluated result.  There would be no use in being able
> to access some part of it, since the whole (i.e., the ternary
> expression) is completely finished by the time you would be able to
> access it.  This is not the case with a function definition.  The
> function definition leaves behind a function object, and that function
> object needs to "know" about the late-bound default as an independent
> entity so that it can be evaluated later.  It is bad for the function to
> store that late-bound default only in some private format for its
> exclusive future use without providing any means for other code to
> access it as a first-class value.
>

That's exactly why it's such a close parallel. The late-evaluated
default is just code, nothing else. It's not "stored" in any way - it
is evaluated as part of the function beginning execution.

There is no "first class object" for a late-evaluated default any more
than there is one for the "y/z" part of the ternary.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 6:12 PM  wrote:
>
> Brendan Barnwell wrote:
> > > No.  As I mentioned in the earlier thread, I don't support any proposal
> > in which an argument can "have a default" but that default is not a
> > first-class Python object of some sort.
>
> What if a default is a function?
>
> I was inspired by learning Django and saw in models that fields can have a 
> default which is either a regular (early-bound) default such as a first-class 
> Python object as one would expect, *or* a function -- which will be called 
> 'later' when needed.
>
> That prompted me to contemplate a syntax for late-bound defaults, albeit a 
> bit clunky, but I did think it suited a special-case requirement met by 
> late-bound defaults. I still think that littering function arguments 
> throughout all code with large numbers of arrows would make things less 
> readable. Special requirements need special treatment, I'm thinking.
>
> The problem is passing arguments to such a function without it looking like 
> it's being called at definition time.
>

Also has the same problem of other deferreds, which is: when exactly
is it evaluated?

def func(stuff, n=>len(stuff)):
stuff.append("spam")
print(n)

func(["spam", "ham"])

What will this print? If it's a function default, it MUST print 2,
since len(stuff) is 2 as the function starts. But if it's a deferred
object of some sort, then it should probably print 3, since len(stuff)
is 3 at the time that n gets printed. Which is it to be?

That's why PEP 671 is *not* about generic deferred evaluation. It is
specifically about function default arguments, and guarantees that
they will be evaluated prior to the first line of code in 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/7IQQ34WYQOJGSBMLWINYV4NSOAR6ZTOH/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Brendan Barnwell

On 2021-12-01 18:35, Chris Angelico wrote:

In my reference implementation, there is no object that stores it;
it's simply part of the function. A good parallel is the if/else
expression:

x = float("inf") if z == 0 else y/z

Is there an object that represents the if/else expression (or the
deferred "y/z" part)? No, although it could be implemented that way if
you chose:


	This is not a good parallel.  There is nothing deferred there.  The 
entire line is evaluated when it is encountered and you get a result and 
no part of the if/else expression can ever impact anything else again 
unless, via some external control flow, execution returns and 
re-executes the entire line.  That is not comparable to a function 
default, which is STORED and evaluated later independently of the 
context in which it was originally written (i.e., the function default 
is re-executed but the function definition itself is not re-executed).


	The ternary expression vanishes without a trace by the next line, 
leaving only its evaluated result.  There would be no use in being able 
to access some part of it, since the whole (i.e., the ternary 
expression) is completely finished by the time you would be able to 
access it.  This is not the case with a function definition.  The 
function definition leaves behind a function object, and that function 
object needs to "know" about the late-bound default as an independent 
entity so that it can be evaluated later.  It is bad for the function to 
store that late-bound default only in some private format for its 
exclusive future use without providing any means for other code to 
access it as a first-class value.


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


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

2021-12-01 Thread role . pythonorg-readers
Brendan Barnwell wrote:
> > No.  As I mentioned in the earlier thread, I don't support any proposal 
> in which an argument can "have a default" but that default is not a 
> first-class Python object of some sort.

What if a default is a function?

I was inspired by learning Django and saw in models that fields can have a 
default which is either a regular (early-bound) default such as a first-class 
Python object as one would expect, *or* a function -- which will be called 
'later' when needed.

That prompted me to contemplate a syntax for late-bound defaults, albeit a bit 
clunky, but I did think it suited a special-case requirement met by late-bound 
defaults. I still think that littering function arguments throughout all code 
with large numbers of arrows would make things less readable. Special 
requirements need special treatment, I'm thinking.

The problem is passing arguments to such a function without it looking like 
it's being called at definition 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/PJNVHV3UY5L67GDEZWGXMRPIL6SN4563/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Brendan Barnwell

On 2021-11-30 22:16, Chris Angelico wrote:

I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
with some additional information about the reference implementation,
and some clarifications elsewhere.

*PEP 671: Syntax for late-bound function argument defaults*

Questions, for you all:

1) If this feature existed in Python 3.11 exactly as described, would
you use it?


I hope not.  :-)

	Realistically I might wind up using it at some point way down the line. 
 I wouldn't start using it immediately.  I still almost never use the 
walrus and only occasionally use f-strings.


	You didn't ask how people would feel about READING this rather than 
writing it, but what I would do is get really annoyed at seeing it in 
code as people start to use it and confuse me and others.



2) Independently: Is the syntactic distinction between "=" and "=>" a
cognitive burden?

(It's absolutely valid to say "yes" and "yes", and feel free to say
which of those pulls is the stronger one.)


Yes, it is yet another reason not to do this.


3) If "yes" to question 1, would you use it for any/all of (a) mutable
defaults, (b) referencing things that might have changed, (c)
referencing other arguments, (d) something else?


N/A.


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


	No.  As I mentioned in the earlier thread, I don't support any proposal 
in which an argument can "have a default" but that default is not a 
first-class Python object of some sort.



5) Do you know how to compile CPython from source, and would you be
willing to try this out? Please? :)


No, I don't.

	I know I said this before, but I really hope this change is not 
adopted.  It is to me a classic example of adding significant complexity 
to the language and reducing readability for only a very small benefit 
in expressiveness.


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


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

2021-12-01 Thread Abdulla Al Kathiri
Exactly like you. I can read => to mean late-bound or supposedly lambda 
function and I can distinguish it from the callable typing ->  but 
"@param=value” is definitely better in my eyes. => won’t prevent me from using 
it for default mutable objects.

> On 2 Dec 2021, at 3:45 AM, Jeremiah Vivian  
> wrote:
> 
> To be honest, I like the `@param=value` syntax. It is sort of easier to read 
> than `param=>value`, though I do not have problems with distinguishing the 
> arrow `=>` from other things.

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


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

2021-12-01 Thread abed...@gmail.com
2% of functions is a lot of functions. We're talking about a language 
that's been around 30 years. The feature set is pretty mature. If it were 
lacking features that would improve a much larger percent of code for so 
long, I don't think it would be as popular. It's not like the next PIP is 
going to be as big as the for-loop.
On Wednesday, December 1, 2021 at 9:56:40 PM UTC-6 David Mertz, Ph.D. wrote:

> On Wed, Dec 1, 2021, 10:38 PM Steven D'Aprano 
>
>> "If param is missing **or None**, the default if blah..."
>> I reject Chris' characterisation of this as a hack. There are function 
>> parameters where None will *never* in any conceivable circumstances become 
>> a valid argument value, and it is safe to use it as a sentinel.
>>
>
> In particular, the cases where None will never, in any conceivable 
> circumstances, be a non-sentinel value are at least 98% of all the 
> functions (that have named parameters) I've ever written in Python.
>
> All of this discussion of a syntax change is for, at most, 2% of functions 
> that need a different sentinel.
>
___
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/UJYHPTIAKEITYW6N2NK6KRINV4TPAE2M/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread abed...@gmail.com
Steven D'Aprano
""If param is missing **or None**, the default if blah..."

I reject Chris' characterisation of this as a hack. There are function
parameters where None will *never* in any conceivable circumstances
become a valid argument value, and it is safe to use it as a sentinel."

Yes, we know *why* the hack works. We're all familiar with it. That doesn't 
mean it's not a hack.

The bottom line is:
you *don't actually* want the parameter to default to the value of a 
sentinel.
you *have* to use that hack because you can't express what you want the 
default to actually be.
You're doing something misleading to work around a shortcoming of the 
language.
That's a hack.
You have to write something that you don't actually intend.
On Wednesday, December 1, 2021 at 9:39:12 PM UTC-6 Steven D'Aprano wrote:

> On Wed, Dec 01, 2021 at 05:16:34PM +1100, Chris Angelico wrote:
>
> > 1) If this feature existed in Python 3.11 exactly as described, would
> > you use it?
>
> Yes I would, but probably not as often as counting cases of the "if 
> param is None: ..." idiom might lead you to expect.
>
> The problem is, as Neil also pointed out, that it becomes tricky to 
> explicitly ask for the default behaviour except by leaving the argument 
> out altogether. Not impossible, as Chris mentions elsewhere, you can 
> mess about with `*args` or `**kwargs`, but it is decidedly less 
> convenient, more verbose, and likely to have a performance hit.
>
> So if I were messing about in the interactive interpreter, I would 
> totally use this for the convenience:
>
> def func(L=>[]): ...
>
> but if I were writing a library, I reckon that probably at least half 
> the time I'll stick to the old idiom so I can document the parameter:
>
> "If param is missing **or None**, the default if blah..."
>
> I reject Chris' characterisation of this as a hack. There are function 
> parameters where None will *never* in any conceivable circumstances 
> become a valid argument value, and it is safe to use it as a sentinel.
>
> For example, I have a function that takes a `collation=None` parameter. 
> The collation is a sequence of characters, usually a string. Using None 
> to indicate "use the default collation" will never conflict with some 
> possible future use of "use None as the actual collation" because None 
> is not a sequence of characters.
>
> In this specific case, my function's current signature is:
>
> def itoa(n, base,
> collation=None,
> plus='',
> minus='-',
> width=0,
> ):
>
> I could re-write it as:
>
> def itoa(n, base,
> collation=>_default_collation(base),
> plus='',
> minus='-',
> width=0,
> ):
>
> but that would lose the ability to explicitly say "use the default 
> collation" by passing None. So I think that, on balance, I would 
> likely stick to the existing idiom for this function.
>
> On the other hand, if None were a valid value, so the signature used a 
> private and undocumented sentinel:
>
> collation=_MISSING
>
> (and I've used that many times in other functions) then I would be 
> likely to swap to this feature and drop the private sentinel.
>
>
> > 2) Independently: Is the syntactic distinction between "=" and "=>" a
> > cognitive burden?
>
> I think you know my opinion on the `=>` syntax :-)
>
> I shall not belabour it further here. I reserve the right to belabour it 
> later on :-)
>
>
> > 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> > defaults, (b) referencing things that might have changed, (c)
> > referencing other arguments, (d) something else?
>
> Any of the above.
>
>
>
> > 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.)
>
> There's lots of Python features that I use even though I don't like the 
> spelling. Not a day goes by that I don't wish we spelled the base class 
> of the object hierarchy "Object", so it were easier to distinguish 
> between Object the base class and object as a generic term for any 
> object.
>
> If the Steering Council loves your `=>` syntax then I would disagree 
> with their decision but still use it.
>
>
> -- 
> Steve
> ___
> Python-ideas mailing list -- python...@python.org
> To unsubscribe send an email to python-id...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python...@python.org/message/G3V47ST6INLI7Y3C5RZSWVXFLNUTELQT/
>  
> 
> 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 

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

2021-12-01 Thread Abe Dillon
I like the => syntax and would use it probably 80% of the time for mutable
defaults.

I don't think it causes cognitive load.

I especially disagree with the argument that it looks like arbitrary
symbols and adds more 'line noise' than a keyword. My eye picks it up as a
distinct arrow rather than a random assembly of punctuation. Maybe it's not
as hard as people claim to visually parse strings of punctuation that make
little pictures ¯\_(ツ)_/¯

I also disagree that it makes Python harder to teach or learn. You *have
to* teach students about early binding anyway. That's the hard part.
Explaining how parameter binding works so that they can avoid the pit traps
is the hard part. Then you either show them a verbose and clumsy work
around of checking for a sentinel or you show them a cute little arrow.

I think people are missing the overall point of doing in the function
header what belongs in the function header so that it doesn't spill into
the body.

My favorite alternative is ?= if people think  =>  and -> are getting
overly loaded. What I really don't like is @param=[] because it puts the
emphasis on the parameter name rather than the act of binding. Not only
does it make it look like @param is a special kind of variable, it also
mimics the *args and **kwargs syntax which makes them seem related.

On Wed, Dec 1, 2021, 8:36 PM Chris Angelico  wrote:

> On Thu, Dec 2, 2021 at 1:30 PM Steven D'Aprano 
> wrote:
> >
> > On Wed, Dec 01, 2021 at 12:26:33PM +, Matt del Valle wrote:
> >
> > > If anything I think
> > > the symmetry between the proposed '=>' syntax and the arrow syntax for
> > > lambdas in other languages (potentially even in python in the future)
> > > reduces the cognitive burden significantly, given the there is an
> > > equivalent symmetry with their semantics (in both cases the code is
> being
> > > evaluated later when something is called).
> >
> > It may be that behind the scenes the default expression is stored as a
> > callable function which the interpreter calls. (I believe that list
> > comprehensions do something similar.) But that's an implementation
> > detail that can change: it might just as well store the source code as a
> > string, and pass it to eval().
>
> In my reference implementation, there is no object that stores it;
> it's simply part of the function. A good parallel is the if/else
> expression:
>
> x = float("inf") if z == 0 else y/z
>
> Is there an object that represents the if/else expression (or the
> deferred "y/z" part)? No, although it could be implemented that way if
> you chose:
>
> x = iff(z == 0, lambda: y/z, lambda: float("inf"))
>
> But just because you CAN use a function to simulate this behaviour,
> that doesn't mean that it's inherently a function.
>
> So I agree with Steve that the parallel is quite weak. That said,
> though, I still like the arrow notation, not because of any parallel
> with a lambda function, but because of the parallel with assignment.
>
> (And hey. You're allowed to think of things in any way you like. I'm
> not forcing you to interpret everything using the same justifications
> I do.)
>
> > Or use some other mechanism that I'm not clever enough to think of, so I
> > shall just call "deepest black magic".
>
> Remind me some time to use some slightly shallower black magic.
>
> > There is no *neccessity* for the late-bound default to be a hidden
> > function, and it is certainly not part of the semantics of late-bound
> > defaults. Just the implementation.
> >
> > If you disagree, and still think that the symmetry is powerful enough to
> > use the same syntax for both lambdas and default arguments, well, how
> > about if we *literally* do that?
> >
> > def function(spam=expression,  # regular default
> >  lambda eggs: expression,  # late-bound default
> >  )
> >
> > Heh, perhaps the symmetry is not that strong after all :-)
>
> That. is hilariously confusing. I like it. Just not EVER in the
> language :)
>
> 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/AQWFM7KYVMLBD6FH7XDYLMQVUBZOJGNW/
> 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/QB4BL4BV5CGDUXGDLCA4622DCSG2THZ6/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread David Mertz, Ph.D.
On Wed, Dec 1, 2021, 10:38 PM Steven D'Aprano

> "If param is missing **or None**, the default if blah..."
> I reject Chris' characterisation of this as a hack. There are function
> parameters where None will *never* in any conceivable circumstances become
> a valid argument value, and it is safe to use it as a sentinel.
>

In particular, the cases where None will never, in any conceivable
circumstances, be a non-sentinel value are at least 98% of all the
functions (that have named parameters) I've ever written in Python.

All of this discussion of a syntax change is for, at most, 2% of functions
that need a different sentinel.
___
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/FNG2ZQD7SPCLBLNKDBCN64A5VVW5S2ZR/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Steven D'Aprano
On Wed, Dec 01, 2021 at 05:16:34PM +1100, Chris Angelico wrote:

> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

Yes I would, but probably not as often as counting cases of the "if 
param is None: ..." idiom might lead you to expect.

The problem is, as Neil also pointed out, that it becomes tricky to 
explicitly ask for the default behaviour except by leaving the argument 
out altogether. Not impossible, as Chris mentions elsewhere, you can 
mess about with `*args` or `**kwargs`, but it is decidedly less 
convenient, more verbose, and likely to have a performance hit.

So if I were messing about in the interactive interpreter, I would 
totally use this for the convenience:

def func(L=>[]): ...

but if I were writing a library, I reckon that probably at least half 
the time I'll stick to the old idiom so I can document the parameter:

"If param is missing **or None**, the default if blah..."

I reject Chris' characterisation of this as a hack. There are function 
parameters where None will *never* in any conceivable circumstances 
become a valid argument value, and it is safe to use it as a sentinel.

For example, I have a function that takes a `collation=None` parameter. 
The collation is a sequence of characters, usually a string. Using None 
to indicate "use the default collation" will never conflict with some 
possible future use of "use None as the actual collation" because None 
is not a sequence of characters.

In this specific case, my function's current signature is:

def itoa(n, base,
 collation=None,
 plus='',
 minus='-',
 width=0,
 ):

I could re-write it as:

def itoa(n, base,
 collation=>_default_collation(base),
 plus='',
 minus='-',
 width=0,
 ):

but that would lose the ability to explicitly say "use the default 
collation" by passing None. So I think that, on balance, I would 
likely stick to the existing idiom for this function.

On the other hand, if None were a valid value, so the signature used a 
private and undocumented sentinel:

collation=_MISSING

(and I've used that many times in other functions) then I would be 
likely to swap to this feature and drop the private sentinel.


> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?

I think you know my opinion on the `=>` syntax :-)

I shall not belabour it further here. I reserve the right to belabour it 
later on :-)


> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

Any of the above.



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

There's lots of Python features that I use even though I don't like the 
spelling. Not a day goes by that I don't wish we spelled the base class 
of the object hierarchy "Object", so it were easier to distinguish 
between Object the base class and object as a generic term for any 
object.

If the Steering Council loves your `=>` syntax then I would disagree 
with their decision but still use 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/G3V47ST6INLI7Y3C5RZSWVXFLNUTELQT/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 1:30 PM Steven D'Aprano  wrote:
>
> On Wed, Dec 01, 2021 at 12:26:33PM +, Matt del Valle wrote:
>
> > If anything I think
> > the symmetry between the proposed '=>' syntax and the arrow syntax for
> > lambdas in other languages (potentially even in python in the future)
> > reduces the cognitive burden significantly, given the there is an
> > equivalent symmetry with their semantics (in both cases the code is being
> > evaluated later when something is called).
>
> It may be that behind the scenes the default expression is stored as a
> callable function which the interpreter calls. (I believe that list
> comprehensions do something similar.) But that's an implementation
> detail that can change: it might just as well store the source code as a
> string, and pass it to eval().

In my reference implementation, there is no object that stores it;
it's simply part of the function. A good parallel is the if/else
expression:

x = float("inf") if z == 0 else y/z

Is there an object that represents the if/else expression (or the
deferred "y/z" part)? No, although it could be implemented that way if
you chose:

x = iff(z == 0, lambda: y/z, lambda: float("inf"))

But just because you CAN use a function to simulate this behaviour,
that doesn't mean that it's inherently a function.

So I agree with Steve that the parallel is quite weak. That said,
though, I still like the arrow notation, not because of any parallel
with a lambda function, but because of the parallel with assignment.

(And hey. You're allowed to think of things in any way you like. I'm
not forcing you to interpret everything using the same justifications
I do.)

> Or use some other mechanism that I'm not clever enough to think of, so I
> shall just call "deepest black magic".

Remind me some time to use some slightly shallower black magic.

> There is no *neccessity* for the late-bound default to be a hidden
> function, and it is certainly not part of the semantics of late-bound
> defaults. Just the implementation.
>
> If you disagree, and still think that the symmetry is powerful enough to
> use the same syntax for both lambdas and default arguments, well, how
> about if we *literally* do that?
>
> def function(spam=expression,  # regular default
>  lambda eggs: expression,  # late-bound default
>  )
>
> Heh, perhaps the symmetry is not that strong after all :-)

That. is hilariously confusing. I like it. Just not EVER in the language :)

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


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

2021-12-01 Thread Steven D'Aprano
On Wed, Dec 01, 2021 at 12:26:33PM +, Matt del Valle wrote:

> If anything I think
> the symmetry between the proposed '=>' syntax and the arrow syntax for
> lambdas in other languages (potentially even in python in the future)
> reduces the cognitive burden significantly, given the there is an
> equivalent symmetry with their semantics (in both cases the code is being
> evaluated later when something is called).

There is not as much symmetry as you might think between a hypothetical 
lambda arrow and the proposed late-bound default arrow.

arg => arg + 1  # lambda
arg=>expr  # late-bound default

The first case is (or could be some day...) an actual expression that 
returns a function object, which we will explicitly call at some point. 
Or at least pass the function to another function, which will call it.

But the late bound default is not an expression, it is a declaration. It 
declares the default value used for arg. We don't have to call anything 
to get access to the default value. It just shows up when we access the 
parameter without providing an argument for it.

We certainly don't need to call arg explicitly to evaluate the default.

It may be that behind the scenes the default expression is stored as a 
callable function which the interpreter calls. (I believe that list 
comprehensions do something similar.) But that's an implementation 
detail that can change: it might just as well store the source code as a 
string, and pass it to eval().

Or use some other mechanism that I'm not clever enough to think of, so I 
shall just call "deepest black magic".

There is no *neccessity* for the late-bound default to be a hidden 
function, and it is certainly not part of the semantics of late-bound 
defaults. Just the implementation.

If you disagree, and still think that the symmetry is powerful enough to 
use the same syntax for both lambdas and default arguments, well, how 
about if we *literally* do that?

def function(spam=expression,  # regular default
 lambda eggs: expression,  # late-bound default
 )

Heh, perhaps the symmetry is not that strong after all :-)



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


[Python-ideas] Re: PEP 671: Syntax for late-bound function argument defaults

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 12:42 PM David Lukeš  wrote:
>
> > That's an oversimplification:
> >
> > foo = 42
> > def bar():
> > print(foo)
> > foo = 1
> >
> > This won't print 42.
>
> Oh, right. I've run afoul of this in the past, but clearly not often
> enough to make it second nature :) Thanks for being helpful!
>
> I still think nudging people to only refer to previous arguments in
> their late-bound defaults is a good idea though, for readability and
> intuitiveness.

Oh yes, absolutely. Whether it's legal or not, referring to future
arguments will always be frowned upon.

> Maybe a good way to enforce it naturally (at least w.r.t.
> to arguments without late-bound defaults) would be via a similar syntax
> as keyword-only arguments? Something like:
>
> def foo(bar, *, baz=1, @, qux=[baz]):
> ...
>

That's rather restricting, and it implies that there's a major
difference in the way that functions would be defined ("late-bound
default keyword-only arguments" would become a brand new type of
argument) rather than a small difference in the way a function default
is defined.

> Now that I look at it, I actually like this bikeshed quite a lot. It
> trades some of the flexibility for expliciteness (the @ is very
> conspicuous in this position), consistency and predictability, which
> feels Pythonic. The @-as-barrier-to-eager-evaluation mnemonic still
> works. No potential => footgun.
>
> But it's late at night and I need to go to bed, so I probably messed
> something up again?

Not messed up, other than the fact that it's more change than I think
this needs. :)

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


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

2021-12-01 Thread Jeremiah Vivian
To be honest, I like the `@param=value` syntax. It is sort of easier to read 
than `param=>value`, though I do not have problems with distinguishing the 
arrow `=>` from other things.
___
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/AG2JBB5SYNZNW6P7VYHU3LBTDHJU3TIV/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Greg Ewing

On 2/12/21 4:40 am, Paul Moore wrote:

the
intended use is that people must supply a list[int] or not supply the
argument *at all*.


I don't think this is a style of API that we should be encouraging
people to create, because it results in things that are very
awkward to wrap.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 8:50 AM Barry Scott  wrote:
>
>
>
> > On 1 Dec 2021, at 17:59, Chris Angelico  wrote:
> >
> > On Thu, Dec 2, 2021 at 4:40 AM Barry Scott  wrote:
> >>
> >> On 1 Dec 2021, at 06:16, Chris Angelico  wrote:
> >> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> >> defaults, (b) referencing things that might have changed, (c)
> >> referencing other arguments, (d) something else?
> >>
> >>
> >> yes (a)
> >> What does (b) mean? example please.
> >> yes (c)
> >>
> >
> > global_default = 500
> > def do_thing(timeout=>global_default): ...
>
> >
> > If the global_default timeout changes between function definition and
> > call, omitting timeout will use the updated global.
> >
> > Similarly, you could say "file=>sys.stdout" and if code elsewhere
> > changes sys.stdout, you'll use that.
>
> On a case-by-case basis I might still put defaulting into the body
> of the function if that made the intent clearer.
>
> I could see me using @file=sys.stdout.
>

That's a simplified version, but you might have the same default shown
as get_default_timeout() or Defaults.timeout or something like that.
The point is that it might be a simple integer, but it could change at
any time, and the default should always be "whatever this name refers
to".

In any case, it's just one of many use-cases. I was curious what
people would use and what they wouldn't.

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


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

2021-12-01 Thread Barry Scott



> On 1 Dec 2021, at 17:59, Chris Angelico  wrote:
> 
> On Thu, Dec 2, 2021 at 4:40 AM Barry Scott  wrote:
>> 
>> On 1 Dec 2021, at 06:16, Chris Angelico  wrote:
>> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
>> defaults, (b) referencing things that might have changed, (c)
>> referencing other arguments, (d) something else?
>> 
>> 
>> yes (a)
>> What does (b) mean? example please.
>> yes (c)
>> 
> 
> global_default = 500
> def do_thing(timeout=>global_default): ...

> 
> If the global_default timeout changes between function definition and
> call, omitting timeout will use the updated global.
> 
> Similarly, you could say "file=>sys.stdout" and if code elsewhere
> changes sys.stdout, you'll use that.

On a case-by-case basis I might still put defaulting into the body
of the function if that made the intent clearer.

I could see me using @file=sys.stdout.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 4:40 AM Barry Scott  wrote:
>
> On 1 Dec 2021, at 06:16, Chris Angelico  wrote:
> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?
>
>
> yes (a)
> What does (b) mean? example please.
> yes (c)
>

global_default = 500
def do_thing(timeout=>global_default): ...

If the global_default timeout changes between function definition and
call, omitting timeout will use the updated global.

Similarly, you could say "file=>sys.stdout" and if code elsewhere
changes sys.stdout, you'll use that.

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


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

2021-12-01 Thread Barry Scott


> On 1 Dec 2021, at 06:16, Chris Angelico  wrote:
> 
> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> with some additional information about the reference implementation,
> and some clarifications elsewhere.
> 
> *PEP 671: Syntax for late-bound function argument defaults*
> 
> Questions, for you all:
> 
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

no because of name=>

> 
> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?

yes.

> 
> (It's absolutely valid to say "yes" and "yes", and feel free to say
> which of those pulls is the stronger one.)
> 
> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

yes (a)
What does (b) mean? example please.
yes (c)

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

Use the @name to avoid the confusing with the set of = things.

> 
> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)

no promises, if I get spare time I'll give it a go,
should be easy to hack the Fedora python RPM to build your
version.

> 
> I'd love to hear, also, from anyone's friends/family who know a bit of
> Python but haven't been involved in this discussion. If late-bound
> defaults "just make sense" to people, that would be highly
> informative.
> 
> Any and all comments welcomed. I mean, this is python-ideas after
> all... bikeshedding is what we do best!
> 
> The reference implementation currently has some test failures, which
> I'm looking into. I'm probably going to make this my personal default
> Python interpreter for a while, to see how things go.

Barry

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 2:40 AM David Mertz, Ph.D.  wrote:
>
> On Wed, Dec 1, 2021 at 10:12 AM Chris Angelico  wrote:
>>
>> On Thu, Dec 2, 2021 at 12:42 AM David Mertz, Ph.D.
>>  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.)
>> >
>> > Yes, the delay/later/defer keyword approach is not confusing, and does not 
>> > preempt a later feature that would actually be worth having.
>>
>> Do you mean changing the spelling of the existing proposal, or a
>> completely different proposal for deferred objects that are actually
>> objects? Because that is NOT what I mean by a "small change". :)
>
>
> The spelling of the existing proposal.  I.e. if the proposal were:
>
> def fun(things: list[int] = defer []) -> int:
> # ... some implementation
>
>
> I'd be -0 on the idea rather than -100.

Okay. If it's JUST the spelling, then yes, I'll take that into
consideration (though I am still against keywords myself).

> Yes, my change in attitude is largely because I want *some future PEP* to 
> address the more general situation like:
>
> result = defer really_expensive_calculation()
> if predicate:
> doubled = result * 2
>
>
> But I do not think your PEP does (nor even should) include that potential 
> future behavior/syntax.  Such a hypothetical future PEP would have a 
> continuity with the syntax of your feature, albeit DEFINITELY need to address 
> many independent concerns/issues that yours does not create.
>
> However, even if I assume the mythical future PEP never happens, in terms of 
> readability, a WORD is vastly less confusing than a combination of 
> punctuation that has no obvious or natural interpretation like '=>'.  Or 
> rather, I think that spelling is kinda-sorta obvious for the lambda meaning, 
> and the use you want is kinda-sorta similar to a lambda.  So I *do* 
> understand how you get there... but it still seems like much too much line 
> noise for a very minimal need.
>

The trouble is that this actually would be incompatible. If you can
defer an expensive calculation and have some "placeholder" value in
the variable 'result', then logically, you should be able to have that
placeholder as a function default argument, which would be an
early-bound default of the placeholder. That is quite different in
behaviour from a late-bound default, so if I were to use the word
"defer" for late-bound defaults, it would actually prevent the more
general proposal.

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


[Python-ideas] Re: PEP 671: Syntax for late-bound function argument defaults

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 2:47 AM David Lukeš  wrote:
>
> This was probably mentioned at some point (apologies, can't afford to
> read the entire thread), but since the issue of left-to-right vs.
> early-first-then-late binding was hotly debated, I just want to point out
> that left-to-right better preserves scoping intuitions:
>
> foo = 42
> def bar(@baz=foo, foo=1):
> return baz, foo
>
> With left-to-right, bar() returns (42, 1) (or whatever other value the
> foo global currently has). With early-first-then-late, it returns (1,
> 1). And according to the current version of the PEP, it's essentially
> undefined behavior, though AFAICS, the possibility that baz would take
> its value from global foo isn't even considered.

There are only two possible interpretations: either it uses the
provided foo (or early-bound default), or it fails with
UnboundLocalError. Under no circumstances would it be able to see a
global. This isn't a class namespace, so the name 'foo' is always
local.

> As a teacher, I'd much rather teach/explain the first option, because
> in most of Python, you can figure out what value a name refers to by
> looking to the left and above of where it's used, and if you can't find
> it in the local scope, check globals.
>
> (One prominent place where this doesn't hold is comprehensions/genexprs,
> which in practice tend to be a learning bump for beginners.)

That's an oversimplification:

foo = 42
def bar():
print(foo)
foo = 1

This won't print 42. But with that understanding ("locals are locals
no matter where you use them"), late-bound defaults are the same as
any other locals.

> The PEP doesn't have any examples of what the syntax for *assigning*
> late bound arguments is, so I'm assuming there's no special syntax? As
> in, bar can be called e.g. as bar(1, 2), bar(baz=1, foo=2) or bar(foo=1,
> baz=2)? That makes sense, but I think it's a small argument in favor of
> a prefix notation, so that = is kept the same across definitions and
> calls. Somehow, I would expect my students to be more likely to
> erroneously think they need to replicate => and call bar as bar(baz=>1),
> and less likely to write bar(@baz=1), especially with that barrier
> mnemonic. Just a hunch though.

Definitely no special syntax. This makes no changes to the way
functions are called, only what happens with omitted args.

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


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

2021-12-01 Thread Piotr Duda
> *PEP 671: Syntax for late-bound function argument defaults*
>
> Questions, for you all:
>
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

Yes


> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?

No, but it will be cognitive burden with shorthand lambda proposed
syntax, for example
def x(a: (b, c)=>c):
is annotation for a (b, c) or maybe (b, c)=>c


> (It's absolutely valid to say "yes" and "yes", and feel free to say
> which of those pulls is the stronger one.)
>
> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

mostly (a), sometimes (c)


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

While I answered yes to question 1, personally I would prefer not
adding new syntax, but switching completly to late defaults (requiring
future import for some next versions)


> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)

Don't have enough 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/EAUYTHGRRA337IEM4AZBVBFPIW2SLSPT/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Ethan Furman

On 11/30/21 10:16 PM, Chris Angelico wrote:

> *PEP 671: Syntax for late-bound function argument defaults*
>
> Questions, for you all:
>
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

No.

> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?

Yes.

> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

a, b, c

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

Have the token/keyword be at the beginning instead of in the middle.

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


[Python-ideas] Re: PEP 671: Syntax for late-bound function argument defaults

2021-12-01 Thread David Lukeš
This was probably mentioned at some point (apologies, can't afford to
read the entire thread), but since the issue of left-to-right vs.
early-first-then-late binding was hotly debated, I just want to point out
that left-to-right better preserves scoping intuitions:

foo = 42
def bar(@baz=foo, foo=1):
return baz, foo

With left-to-right, bar() returns (42, 1) (or whatever other value the
foo global currently has). With early-first-then-late, it returns (1,
1). And according to the current version of the PEP, it's essentially
undefined behavior, though AFAICS, the possibility that baz would take
its value from global foo isn't even considered.

As a teacher, I'd much rather teach/explain the first option, because
in most of Python, you can figure out what value a name refers to by
looking to the left and above of where it's used, and if you can't find
it in the local scope, check globals.

(One prominent place where this doesn't hold is comprehensions/genexprs,
which in practice tend to be a learning bump for beginners.)

As for errors -- if SyntaxError were used, then the example above would
raise it, wouldn't it? Because there's no way to statically determine
whether foo might also be a global, in addition to being a function
parameter. So there would be no way of having a late-bound parameter
take a default from a global, while having an early-bound parameter with
the same name as the global. I freely acknowledge you probably won't
need this most of the time, but why prohibit it outright (or why make it
into undefined behavior, without even considering the global, as the PEP
currently does), especially since it aligns with scoping intuitions as
outlined above?

Finally, as hinted by the example, I'm leaning towards the @ notation.
=> is pointing in the wrong direction, when programming languages use
some kind of arrow-like operator for assignment, it tends to point
towards the name, not the value. (I realize this is not really
assignment, but the syntactic analogy is clear.) Whereas I can easily
see myself telling students that the @ acts as a sort of barrier to
eager evaluation/assignment of the default value (as a mnemonic).

It could also be written after the =, as in baz=@foo, which reads like a
quote operator and is open to future extensions where unary @ could be
used to defer evaluation in more places (as some people seem to want --
I personally am wary of quote/eval/substitute shenanigans, such as R
has). The barrier mnemonic could remain the same. OTOH, I like the way
the prefix is more conspicuous and visually signals that the parameter
is special/different right off the bat.

The PEP doesn't have any examples of what the syntax for *assigning*
late bound arguments is, so I'm assuming there's no special syntax? As
in, bar can be called e.g. as bar(1, 2), bar(baz=1, foo=2) or bar(foo=1,
baz=2)? That makes sense, but I think it's a small argument in favor of
a prefix notation, so that = is kept the same across definitions and
calls. Somehow, I would expect my students to be more likely to
erroneously think they need to replicate => and call bar as bar(baz=>1),
and less likely to write bar(@baz=1), especially with that barrier
mnemonic. Just a hunch though.

More seriously though, if => ever makes it into Python as the new lambda
too, then bar(baz=>1) is a beginner footgun waiting to happen: you
probably meant bar(baz=1), but instead, you wrote bar(baz=lambda baz:
1). Whereas bar(@baz=1) remains a harmless SyntaxError (harmless in that
it fails early and gives you a good hint as to what's wrong).

Best,

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


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

2021-12-01 Thread role . pythonorg-readers
Chris Angelico wrote:
> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> Questions, for you all:
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

When needed, but I'm uncomfortable with the syntax.

> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?

Yes. A lot of arrows with different meanings require the reader of the code to 
know and remember what each does. Something more distinctive feels better.

I'm way too new to Python to have much say, but anyway, arrows make more sense 
for other uses. Late binding feels to me like it is best served by something 
more distinctive.

> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

I'd certainly use it only when I felt it was absolutely necessary. The 
readability is not aided by utilising syntax to alter behaviour when the 
altered behaviour is not required. We only quote, escape, etc., when we need 
to. (Silly example to illustrate, I know.)

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

When I first saw this (very few months ago indeed!!), I wondered about 
something rather clunkier but more explicit, such as, for example -- 
```def foo(x=__late__['bar']):
def bar():
#something
etc...
```

Ugly though. And I subsequently realised some use cases are not well-served by 
this. (Particularly when [speculatively] considering some implementation 
issues.)

The point in any case, is that for the occasions when the mechanism is needed, 
then a clearly explicit way to indicate something is evaluated late, and a tidy 
place to put the definition of how it's handled (late), seemed to me to be 
preferable.

Of the **cited** examples, I find the `@hi=len(a)` spelling most readable.

> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)

Sadly not yet, but time permitting I will one day figure that out, for sure.

> bikeshedding is what we do best!

Should we introduce choice of colour, as we run out of new symbols to use? /jk

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


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

2021-12-01 Thread Paul Moore
On Wed, 1 Dec 2021 at 15:24, David Mertz, Ph.D.  wrote:
>
> On Wed, Dec 1, 2021 at 9:24 AM Paul Moore  wrote:
>>
>> I think that the only
>> thing I might use it for is to make it easier to annotate defaults (as
>> f(a: list[int] => []) rather than as f(a: list[int] | None = None).
>
>
> Why not `f(a: Optional[list[int]] = None)`?
>
> I'm not counting characters, but that form seems to express the intention 
> better than either of the others IMHO.

If None were a valid argument, and I was using an opaque sentinel,
Optional doesn't work, and exposing the type of the sentinel is not
what I intend (as it's invalid to explicitly supply the sentinel
value).

Also, Optional[list[int]] doesn't express the intent accurately - the
intended use is that people must supply a list[int] or not supply the
argument *at all*. Optional allows them to supply None as well.

As I say, I don't consider this an intended use case for the feature,
because what I'm actually discussing here is optional arguments and
sentinels, which is a completely different feature. All I'm saying is
that the only case when I can imagine using this feature is for when I
want a genuinely opaque way of behaving differently if the caller
omitted an argument (and using None or a sentinel has been good enough
all these years, so it's not exactly a pressing need).

Let's just go back to the basic point, which is that I can't think of
a realistic case where I'd want to actually use the new feature.

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


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

2021-12-01 Thread David Mertz, Ph.D.
On Wed, Dec 1, 2021 at 10:12 AM Chris Angelico  wrote:

> On Thu, Dec 2, 2021 at 12:42 AM David Mertz, Ph.D.
>  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.)
> >
> > Yes, the delay/later/defer keyword approach is not confusing, and does
> not preempt a later feature that would actually be worth having.
>
> Do you mean changing the spelling of the existing proposal, or a
> completely different proposal for deferred objects that are actually
> objects? Because that is NOT what I mean by a "small change". :)
>

The spelling of the existing proposal.  I.e. if the proposal were:

def fun(things: list[int] = defer []) -> int:
# ... some implementation


I'd be -0 on the idea rather than -100.

Yes, my change in attitude is largely because I want *some future PEP* to
address the more general situation like:

result = defer really_expensive_calculation()
if predicate:
doubled = result * 2


But I do not think your PEP does (nor even should) include that potential
future behavior/syntax.  Such a hypothetical future PEP would have a
continuity with the syntax of your feature, albeit DEFINITELY need to
address many independent concerns/issues that yours does not create.

However, even if I assume the mythical future PEP never happens, in terms
of readability, a WORD is vastly less confusing than a combination of
punctuation that has no obvious or natural interpretation like '=>'.  Or
rather, I think that spelling is kinda-sorta obvious for the lambda
meaning, and the use you want is kinda-sorta similar to a lambda.  So I
*do* understand how you get there... but it still seems like much too much
line noise for a very minimal need.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 1:33 AM André Roberge  wrote:
> On Wed, Dec 1, 2021 at 7:51 AM Chris Angelico  wrote:
>>
>> On Wed, Dec 1, 2021 at 10:30 PM André Roberge  
>> wrote:
>>
>> >> 2) Independently: Is the syntactic distinction between "=" and "=>" a
>> >> cognitive burden?
>> >
>> > Yes.
>> > I really think that using a keyword like defer, or from_calling_scope ;-), 
>> > would significantly reduce the cognitive burden.
>>
>> Also fair. I'm not a fan of keywords for this sort of thing, since it
>> implies that you could do this:
>>
>> def f(x=defer []): ...
>>
>> dflt = defer []
>> def f(x=dflt): ...
>>
>> which is a completely different proposal (eg it would be evaluated
>> only when you "touch" that, rather than being guaranteed to be
>> evaluated before the first line of the function body). That's why I
>> want to adorn the equals sign and nothing else.
>
>
> Shouldn't the PEP contain a rejected idea section where this could be 
> mentioned?
>

Hmm, maybe. It's such a completely different proposal, but it does get
asked a few times. If someone could actually put it forward as a full
proposal, I'd gladly mention it as an interaction with another PEP.
Otherwise, I'll write up a very brief thing on deferred expressions
and how they're not what this is about.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 2:24 AM David Mertz, Ph.D.  wrote:
>
> On Wed, Dec 1, 2021 at 9:24 AM Paul Moore  wrote:
>>
>> I think that the only
>> thing I might use it for is to make it easier to annotate defaults (as
>> f(a: list[int] => []) rather than as f(a: list[int] | None = None).
>
>
> Why not `f(a: Optional[list[int]] = None)`?
>
> I'm not counting characters, but that form seems to express the intention 
> better than either of the others IMHO.
>

"a: list[int] => []" fully expresses the intention IMO, but yes,
Optional is usually better than "| None". That's just a minor spelling
problem though.

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


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

2021-12-01 Thread David Mertz, Ph.D.
On Wed, Dec 1, 2021 at 9:24 AM Paul Moore  wrote:

> I think that the only
> thing I might use it for is to make it easier to annotate defaults (as
> f(a: list[int] => []) rather than as f(a: list[int] | None = None).
>

Why not `f(a: Optional[list[int]] = None)`?

I'm not counting characters, but that form seems to express the intention
better than either of the others IMHO.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 1:21 AM Paul Moore  wrote:
>
> On Wed, 1 Dec 2021 at 06:19, Chris Angelico  wrote:
> > 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> > defaults, (b) referencing things that might have changed, (c)
> > referencing other arguments, (d) something else?
>
> N/A, except to say that when you enumerate the use cases like this,
> none of them even tempt me to use this feature.

I'm just listing some of the common use-cases, not all of them.

> I think that the only
> thing I might use it for is to make it easier to annotate defaults (as
> f(a: list[int] => []) rather than as f(a: list[int] | None = None).

That's exactly the goal! It's hugely simpler to say "this is always a
list, and defaults to a new empty list" than "this is a list or None,
defaults to None, and hey, if it's None, I'll make a new empty list".

> So I'll revise my answer to (1) and say that I *might* use this, but
> only in a way it wasn't intended to be used in, and mostly because I
> hate how verbose it is to express optional arguments in type
> annotations. (And the fact that the annotation exposes the sentinel
> value, even when you want it to be opaque). I hope I don't succumb and
> do that, though ;-)

That's definitely an intended use-case ("mutable defaults" above);
you're focusing on the fact that it improves the annotations, I'm
focusing on the fact that it improves documentation and introspection,
but it's all the same improvement :)

> > 5) Do you know how to compile CPython from source, and would you be
> > willing to try this out? Please? :)
>
> Sorry, I really don't have time to, in the foreseeable future. If I
> did have time, one thing I would experiment with is how this interacts
> with typing and tools like pyright and mypy (yes, I know type checkers
> would need updating for the new syntax, so that would mostly be a
> thought experiment) - as I say, I'd expect to annotate a function with
> an optional list argument defaulting to an empty list as f(a:
> list[int] => []), which means that __annotations__ needs to
> distinguish between this case and f(a: list[int]) with no default.

No problem, yup.

> Sorry, I don't have any feedback like that. What I can say, though, is
> I'd find it quite hard to express the question, in the sense that I'd
> struggle to explain the difference between early and late bound
> parameters to a non-expert, much less explain why we need both. I'd
> probably just say "it's short for a default of None and a check" which
> doesn't really capture the point...

The point is that it's a shortcut for "omitted" rather than "a default
of None", but there are many ways to explain it, and I only have one
brother who knows enough Python to be able to talk to about this (and
I got feedback from him VERY early).

> > Any and all comments welcomed. I mean, this is python-ideas after
> > all... bikeshedding is what we do best!
>
> I hope this was useful feedback.

It was. Thank you.

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


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

2021-12-01 Thread Chris Angelico
On Thu, Dec 2, 2021 at 12:42 AM David Mertz, Ph.D.
 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.)
>
>
> Yes, the delay/later/defer keyword approach is not confusing, and does not 
> preempt a later feature that would actually be worth having.

Do you mean changing the spelling of the existing proposal, or a
completely different proposal for deferred objects that are actually
objects? Because that is NOT what I mean by a "small change". :)

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


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

2021-12-01 Thread André Roberge
On Wed, Dec 1, 2021 at 7:51 AM Chris Angelico  wrote:

> On Wed, Dec 1, 2021 at 10:30 PM André Roberge 
> wrote:
>
> >> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> >> cognitive burden?
> >
> > Yes.
> > I really think that using a keyword like defer, or from_calling_scope
> ;-), would significantly reduce the cognitive burden.
>
> Also fair. I'm not a fan of keywords for this sort of thing, since it
> implies that you could do this:
>
> def f(x=defer []): ...
>
> dflt = defer []
> def f(x=dflt): ...
>
> which is a completely different proposal (eg it would be evaluated
> only when you "touch" that, rather than being guaranteed to be
> evaluated before the first line of the function body). That's why I
> want to adorn the equals sign and nothing else.
>

Shouldn't the PEP contain a rejected idea section where this could be
mentioned?



>
> >> 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.)
> >
> >
> > *Perhaps* if a keyword would be used instead of symbols, I might
> reconsider.
> >
> > I find the emphasis of trying to cram too much information in single
> lines of code to be really a burden. Many years ago, I argued very
> unsuccessfully for using a 'where:' code block for annotations.  (To this
> day, I still believe it would make the code much more readable, at the cost
> of a slight duplication.)  Using what is at first glance a cryptic operator
> like => for late binding is not helping readability, especially when type
> annotations are thrown in the mix.
> >
> > Aside: at the same time, I can see how using => instead of lambda as a
> potential win in readability, including for beginners.
>
> It's interesting how different people's views go on that sort of
> thing. It depends a lot on how much people expect to use something.
> Features you use a lot want to have short notations, features you
> seldom use are allowed to have longer words.
>
> I rarely use lambda in my own code, and have never written a line of code
anywhere that uses a '=>' operator.

If Python had a 'function' keyword instead of 'lambda', I would prefer to
keep the function keyword instead of adding => as a symbol.  For me, it is
not a question of terseness for commonly used features, but one of easing
the learning curve.  Starting from zero, I do believe that => would be
easier to grasp than learning about lambda as a keyword and the syntactic
rules to use with it.  With function as a keyword, I believe that it is the
other way around.  No doubt many others will disagree!

André Roberge

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


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

2021-12-01 Thread Paul Moore
On Wed, 1 Dec 2021 at 06:19, Chris Angelico  wrote:
>
> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> with some additional information about the reference implementation,
> and some clarifications elsewhere.
>
> *PEP 671: Syntax for late-bound function argument defaults*
>
> Questions, for you all:
>
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?

Probably not. Mainly because I don't have any real use for it rather
than because I have any inherent problem with it (but see below, the
more I thought about it the more uncomfortable with it I became).

> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?
>
> (It's absolutely valid to say "yes" and "yes", and feel free to say
> which of those pulls is the stronger one.)

Not especially. The idea of having both late-bound and early-bound
parameters is probably more of a cognitive burden than the syntax.

> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?

N/A, except to say that when you enumerate the use cases like this,
none of them even tempt me to use this feature. I think that the only
thing I might use it for is to make it easier to annotate defaults (as
f(a: list[int] => []) rather than as f(a: list[int] | None = None).

So I'll revise my answer to (1) and say that I *might* use this, but
only in a way it wasn't intended to be used in, and mostly because I
hate how verbose it is to express optional arguments in type
annotations. (And the fact that the annotation exposes the sentinel
value, even when you want it to be opaque). I hope I don't succumb and
do that, though ;-)

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

Not really. It addresses a wart in the language, but on consideration,
it feels like the cure is no better than the disease.

> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)

Sorry, I really don't have time to, in the foreseeable future. If I
did have time, one thing I would experiment with is how this interacts
with typing and tools like pyright and mypy (yes, I know type checkers
would need updating for the new syntax, so that would mostly be a
thought experiment) - as I say, I'd expect to annotate a function with
an optional list argument defaulting to an empty list as f(a:
list[int] => []), which means that __annotations__ needs to
distinguish between this case and f(a: list[int]) with no default.

>>> def f(a: list[int]): pass
...
>>> f.__annotations__
{'a': list[int]}

>>> def f(a: list[int] => []): pass
...
>>> f.__annotations__
???

> I'd love to hear, also, from anyone's friends/family who know a bit of
> Python but haven't been involved in this discussion. If late-bound
> defaults "just make sense" to people, that would be highly
> informative.

Sorry, I don't have any feedback like that. What I can say, though, is
I'd find it quite hard to express the question, in the sense that I'd
struggle to explain the difference between early and late bound
parameters to a non-expert, much less explain why we need both. I'd
probably just say "it's short for a default of None and a check" which
doesn't really capture the point...

> Any and all comments welcomed. I mean, this is python-ideas after
> all... bikeshedding is what we do best!

I hope this was useful feedback.
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/BMJLEOHEA7MYC5IPYUSXELPRWGW4VG6M/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread David Mertz, Ph.D.
On Wed, Dec 1, 2021 at 1:18 AM Chris Angelico  wrote:

> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?
>

No.

... except in the sense that as I trainer I have to teach the warts in
Python, and would need to warn students they might see that.


> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?
>

YES!

A few weeks later than the prior long discussion that I read in full, it
took a triple take not to read it as >= (which would mean something
syntactical in many cases, just not what is intended).


> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?
>

I would always recommend against its use if I had any influence on code
review.


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

Yes, the delay/later/defer keyword approach is not confusing, and does not
preempt a later feature that would actually be worth having.

5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)
>

I do know how, but it is unlikely I'll have time.


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


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

2021-12-01 Thread Matt del Valle
>
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?
>

Absolutely!


> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?
>

Nope, I don't think this is an undue cognitive burden. If anything I think
the symmetry between the proposed '=>' syntax and the arrow syntax for
lambdas in other languages (potentially even in python in the future)
reduces the cognitive burden significantly, given the there is an
equivalent symmetry with their semantics (in both cases the code is being
evaluated later when something is called).

Steven gave the following example of a function signature that would be
difficult to visually parse if this proposal and arrow lambdas were
accepted:

def process(func:List->int=>xs=>expression)->int:

And while I agree that it does sort of stop you in your tracks when you see
this, I think there are a couple of reasons why this is not as big of a
problem as it appears.

Firstly, I think if you're writing this sort of code, you can improve the
legibility a lot by using appropriate spacing and adding parentheses around
the lambda arguments (even if they're unnecessary for a lambda with only a
single argument, like in Steven's example):

def process(func: (List) -> int => (xs) => expression) -> int:

Personally I find this much easier to visually parse since I'm used to
seeing lambdas in the form:

(*args) => expr

So my brain just kind of groups `(List) -> int` and `(xs) => expression`
into atomic chunks fairly effortlessly. And this is before even mentioning
the *massive* cognitive assistance provided by syntax highlighting :)

But at this point I would also like to point out that code like this is
probably going to be vanishingly rare in the wild. The majority of
use-cases for late-bound defaults as far as I can tell are going to be for
mutable defaults (and maybe some references to early-bound arguments). I
don't like the idea of compromising on what is a very clean and intuitive
syntax in 99% of cases to cater to the hypothetical 1% of cases where it
admittedly takes a bit more cognitive effort to parse.

I agree with the statement Chris made above where he mentioned that the
same symbols sometimes have different meanings based on context, and that's
okay. For example:

def some_func(some_arg: int) -> int: ...

def another_func(another_arg: int = some_func(some_arg=3)) -> int: ...

In the second function definition above you've got the '=' symbol pulling
double-duty both as declaring an argument for a function def and as a
keyword arg for a function call in the same statement. I think this is
perfectly fine, and I think the same thing is true of the => symbol being
used for both lambdas and late-bound arguments, especially given they are
semantically related.

3) If "yes" to question 1, would you use it for any/all of (a) mutable
> defaults, (b) referencing things that might have changed, (c)
> referencing other arguments, (d) something else?
>

(a) is the primary use-case I can see myself using this feature for. I'm
not sure what you mean by (b). I can also definitely see some situations
where (c) would be dead useful, though I don't think this would come up in
the sort of code I write as much as (a). Still, when the use-case for (c)
did present itself, I would be *extremely* grateful to have late-bound
defaults to reach for.

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

Not relevant, since my strong preference for late-bound default syntax is
the '=>' symbol.

On Wed, Dec 1, 2021 at 11:50 AM Chris Angelico  wrote:

> On Wed, Dec 1, 2021 at 10:30 PM André Roberge 
> wrote:
> > On Wed, Dec 1, 2021 at 2:17 AM Chris Angelico  wrote:
> >>
> >> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> >> with some additional information about the reference implementation,
> >> and some clarifications elsewhere.
> >>
> >> *PEP 671: Syntax for late-bound function argument defaults*
> >>
> >> Questions, for you all:
> >>
> >> 1) If this feature existed in Python 3.11 exactly as described, would
> >> you use it?
> >>
> > Currently, I'm thinking "absolutely not".
> >
> > However, I thought the same about the walrus operator and I now miss not
> being able to use it in a program that includes support for Python 3.6 and
> where I have literally dozens of places where I would use it if I could.
>
> Very fair :)
>
> >> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> >> cognitive burden?
> >
> > Yes.
> > I really think that using a keyword like defer, or from_calling_scope
> ;-), would significantly reduce the cognitive burden.
>
> Also fair. I'm not a fan of keywords for this sort of thing, since it
> implies that you could do this:
>
> def f(x=defer []): ...
>
> dflt = defer []
> def f(x=dflt): ...
>
> which is a completely different proposal (eg it would be evaluated
> only when you 

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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 10:30 PM André Roberge  wrote:
> On Wed, Dec 1, 2021 at 2:17 AM Chris Angelico  wrote:
>>
>> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
>> with some additional information about the reference implementation,
>> and some clarifications elsewhere.
>>
>> *PEP 671: Syntax for late-bound function argument defaults*
>>
>> Questions, for you all:
>>
>> 1) If this feature existed in Python 3.11 exactly as described, would
>> you use it?
>>
> Currently, I'm thinking "absolutely not".
>
> However, I thought the same about the walrus operator and I now miss not 
> being able to use it in a program that includes support for Python 3.6 and 
> where I have literally dozens of places where I would use it if I could.

Very fair :)

>> 2) Independently: Is the syntactic distinction between "=" and "=>" a
>> cognitive burden?
>
> Yes.
> I really think that using a keyword like defer, or from_calling_scope ;-), 
> would significantly reduce the cognitive burden.

Also fair. I'm not a fan of keywords for this sort of thing, since it
implies that you could do this:

def f(x=defer []): ...

dflt = defer []
def f(x=dflt): ...

which is a completely different proposal (eg it would be evaluated
only when you "touch" that, rather than being guaranteed to be
evaluated before the first line of the function body). That's why I
want to adorn the equals sign and nothing else.

>> 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.)
>
>
> *Perhaps* if a keyword would be used instead of symbols, I might reconsider.
>
> I find the emphasis of trying to cram too much information in single lines of 
> code to be really a burden. Many years ago, I argued very unsuccessfully for 
> using a 'where:' code block for annotations.  (To this day, I still believe 
> it would make the code much more readable, at the cost of a slight 
> duplication.)  Using what is at first glance a cryptic operator like => for 
> late binding is not helping readability, especially when type annotations are 
> thrown in the mix.
>
> Aside: at the same time, I can see how using => instead of lambda as a 
> potential win in readability, including for beginners.

It's interesting how different people's views go on that sort of
thing. It depends a lot on how much people expect to use something.
Features you use a lot want to have short notations, features you
seldom use are allowed to have longer words.

>> 5) Do you know how to compile CPython from source, and would you be
>> willing to try this out? Please? :)
>
>
> Sorry, I'm not interested enough at this point but, given the amount of work 
> you put into this, I decided that the least I could do is provide feedback 
> rather than be a passive reader.

That's absolutely fine. I don't by any means expect everyone to be
able or willing to compile CPython. Feedback is absolutely
appreciated, and I asked the question with full expectation of getting
a few "No" responses :)

Thank you for taking the time to respond. Thoughtful feedback is
incredibly helpful.

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


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

2021-12-01 Thread André Roberge
On Wed, Dec 1, 2021 at 2:17 AM Chris Angelico  wrote:

> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
> with some additional information about the reference implementation,
> and some clarifications elsewhere.
>
> *PEP 671: Syntax for late-bound function argument defaults*
>
> Questions, for you all:
>
> 1) If this feature existed in Python 3.11 exactly as described, would
> you use it?
>
> Currently, I'm thinking "absolutely not".

However, I thought the same about the walrus operator and I now miss not
being able to use it in a program that includes support for Python 3.6 and
where I have literally dozens of places where I would use it if I could.



> 2) Independently: Is the syntactic distinction between "=" and "=>" a
> cognitive burden?
>
Yes.
I really think that using a keyword like defer, or from_calling_scope ;-),
would significantly reduce the cognitive burden.


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

*Perhaps* if a keyword would be used instead of symbols, I might reconsider.

I find the emphasis of trying to cram too much information in single lines
of code to be really a burden. Many years ago, I argued very unsuccessfully
for using a 'where:' code block for annotations.  (To this day, I still
believe it would make the code much more readable, at the cost of a slight
duplication.)  Using what is at first glance a cryptic operator like => for
late binding is not helping readability, especially when type annotations
are thrown in the mix.

Aside: at the same time, I can see how using => instead of lambda as a
potential win in readability, including for beginners.


> 5) Do you know how to compile CPython from source, and would you be
> willing to try this out? Please? :)
>

Sorry, I'm not interested enough at this point but, given the amount of
work you put into this, I decided that the least I could do is provide
feedback rather than be a passive reader.

André Roberge


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


[Python-ideas] Re: Enhancing iterator objects with map, filter, reduce methods

2021-12-01 Thread TobiasHT
Matt D wrote:
> In your comprehension example, I'm fairly certain the filtering should be on 
> the post incremented remainder
> [ x+1 for x in [1,2,3] if (x+1) % 2 == 0]

how about
[ sum for num in [1,2,3] if ((sum := num + 1) %2 == 0]
___
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/QHNJHTU5HRNLVGH7M27G5DZJACYR7GYZ/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 9:09 PM Steven D'Aprano  wrote:
>
> On Wed, Dec 01, 2021 at 07:07:20PM +1100, Chris Angelico wrote:
>
> > > def process(func:List->int=>xs=>expression)->int:
> > > ...
>
> > I'm not sure what that's supposed to mean.
>
> You did a pretty good job of working it out :-)

Okay, cool, thanks.

> Exactly my point. Beyond your arrow syntax for default parameters, and
> the existing return annotation use, there are two other hypothetical
> proposals for arrow syntax on the table:
>
> - using `->` as an alias for typing.Callable;
>
> - using `=>` as a more compact lambda;

That confuses me. Why would they use different arrows?

If we have a compact lambda syntax, why can't actual functions be used
as annotations to represent functions? I believe there's plans to have
[str] mean List[str], which makes a lot of sense. Why not have "lambda
str: int" or "str=>int" be an annotation too?

But okay. Supposing that annotations have to use one arrow and lambda
functions use another, then yes, this is a good reason to use "=:" for
late-bound defaults. It's not that big a change.

> > func:ann=>dflt # late-bound default, completely unnecessary here
>
> Come on Chris, how can you say that it is "completely unnecessary"?
> Unless that's an admission that late-bound defaults are all
> unnecessary... *wink*
>
> There is a difference between these two:
>
> def func(arg=lambda a: expression):
> ...
>
> and this:
>
> def func(arg=None):
> if arg is None:
> arg = lambda a: expression
> ...
>
> therefore there will be a difference between:
>
> def func(arg=lambda a: expression):
> def func(arg=>lambda a: expression):
>
> If nothing else, in the first case (early binding) you get the same
> function object every time. In the second, you get a freshly made
> function object each time. Since function objects are mutable (they have
> a writable `__dict__` that's a visible difference even if the bodies are
> identical. And they may not be.

Yes. Okay. There is a technical way in which you might want this
alternate behaviour. Is that REALLY something you're planning on doing
- having a function which takes another function as an argument, and
which behaves differently based on whether it's given the same
function every time or multiple different functions with the same
behaviour?

> But even if it is unnecessary, it will still be permitted, just as we
> will be able to write:
>
> # Now this *actually is* totally unnecessary use of late-binding
> def func(arg=>None):

Yes. That one is absolutely unnecessary, since there is no way you'll
ever get back a different result. Except that you could then mutate
func's dunders and change the behaviour. So in a purely technical
sense, nothing can be called "unnecessary".

Now, in real terms: late-binding a lambda function with no default
arguments seems like a pretty pointless thing to do. I stand by my
original statement :) And I also stand by my original statement that
proper use of the space bar can not only improve readability, it can
also help you find a date with space girls and space guys... or maybe
that last part only works on Mars.

> > xs=>expression # presumably a lambda function
> > def process(args)->int # return value annotation
> >
> > Why should List->int and xs=>expression use different arrows?
>
> Because they do different things. To avoid confusion.
>
> Chris, you wrote the PEP for the walrus operator. Why should the
> assignment operator use a different symbol from the assignment
> statement? Same reason that typing.Callable and lambda will likely use
> different arrows.
>
> Anyway, if you disagree, take it up with Guido, it was his suggestion to
> use different arrows :-P

Fair enough, but typing also started out with List[str] and is now
looking at using list[str] and, I think, [str], because it's more
consistent :)

> > Wouldn't
> > it be much more reasonable for them to use the same one, whichever
> > that be? And if that does turn out to be "=>", then yes, I would be
> > looking at changing PEP 671 to recommend := or =: or something, for
> > clarity (but still an equals sign with one other symbol next to it).
>
> Oh great, now you're going to conflict with walrus...
>
> def process(obj:Union[T:=something, List[T]]:=func(x:=expression)+x)->T:
>
> We ought to at least try to avoid clear and obvious conflicts between
> new and existing syntax.
>
> Using `:=` is even worse than `=>`, and `=:` is just *begging* to
> confuse newcomers "why do we have THREE different assignment symbols?"

If you look at every way the equals sign is used in Python grammar,
there are a lot of subtle differences. The difference between "f(x=1)"
and "x=1" doesn't bother people, and those are exactly the same
symbol. There are only so many symbols that we can type on everyone's
keyboards.

But you're right, and that's why I would very much like to reuse an
existing symbol rather than create new ones.


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 8:57 PM Neil Girdhar  wrote:
>
>
>
> On Wednesday, December 1, 2021 at 1:18:33 AM UTC-5 Chris Angelico wrote:
>>
>> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/
>> with some additional information about the reference implementation,
>> and some clarifications elsewhere.
>>
>> *PEP 671: Syntax for late-bound function argument defaults*
>>
>> Questions, for you all:
>>
>> 1) If this feature existed in Python 3.11 exactly as described, would
>> you use it?
>
> No, I would avoid for the sake of readers.  Anyway, it can't be used in any 
> public projects until thy drop support for 3.10, which is many years off.
>
> Also, I think this question is quite the biased sample on python-ideas. 
> Please consider asking this to less advanced python users, e.g., 
> reddit.com/r/python or learnpython.

I know it is :) I never expected to get an unbiased sample (from
anywhere, least of all here).

> This PEP has a lot of interesting ideas.  I still think that none-aware 
> operators (PEP 505) are an easier, more readable general solution to binding 
> calculated default values to arguments succinctly.  I think the problems with 
> this idea include:
> * The caller cannot explicitly ask for default behaviour except by omitting 
> the parameter.  This can be very annoying to set up when the parameter values 
> are provided from other places, e.g.,
> if need_x:
>   # do lots of stuff
>   x = whatever
> else:
>   # do more
>   x = None
> f(x=x, ...)  # easy, but with this PEP, you would have to find a way to 
> remove x from the parameter list.  Typically, removing a parameter from a 
> dynamically-created parameter list is hard.
>

You can always do that with *args or **kwargs if that's what you need,
and that actually DOES represent the concept of "don't pass this
argument". Passing None is a hack that doesn't actually mean "don't
pass this argument", and if you're depending on that behaviour, it's
been locked in as the function's API, which causes problems if None
ever becomes a meaningful non-default value.

None-aware operators are solving a different problem. They allow you
to accept None, but then simplify the replacement of it with some
other value. This proposal allows you to leave None out of the
equation altogether. And it only works if None isn't a valid value.

> * The function code becomes unreadable if the parameter-setting code is long. 
>  Having a long piece of code inside the function after "if parameter is None" 
> is just fine.  Having none-aware operators would make such code more succinct.
>

Again, that only works if None is not a valid parameter value, and PEP
505 doesn't generalize to other sentinels at all.

If the code is too long, don't put it into the parameter default. But
"if x is None: x = []" can easily be replaced with "x=>[]" and the
parameters will actually become shorter.

ANY feature can be used badly. You can daisy-chain everything into a
gigantic expression with horrendous abuses of lambda functions, but
that doesn't mean you should. It also doesn't mean that lambda
functions are bad :)

> * People nearly always avoid writing code in the parameter defaults 
> themselves, and this new practice adds a lot of cognitive load.  E.g., people 
> rarely write:
> def f(x: int = 1+g()) -> None: ...
> Parameter lists are already busy enough with parameter names, annotations, 
> and defaults.  We don't need to encourage this practice.
>

They don't become any more noisy by being able to use defaults that
aren't constant. The main goal is to put the function header in the
function header, and the function body in the function body, instead
of having the function body doing part of the work of the header :)

> In short, I think this is a creative idea, a great exploration.  While 
> optional parameters are common, and some of them have defaults that are 
> calculated inside the function, my feeling is that people will continue to 
> set their values inside the function.
>

In some cases, they certainly will. And that's not a problem. But for
the cases where it's better to put it in the header, it's better to
have that option than to restrict it for an arbitrary technical
limitation.

Some languages don't have ANY function defaults. They simply have
"optional arguments", where an omitted optional argument will always
and only have a specific null value. Python allows you to show what
the default REALLY is, and that's an improvement. I want to be able to
show what the default is, even if that is defined in a non-constant
way.

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


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

2021-12-01 Thread Steven D'Aprano
On Wed, Dec 01, 2021 at 07:07:20PM +1100, Chris Angelico wrote:

> > def process(func:List->int=>xs=>expression)->int:
> > ...

> I'm not sure what that's supposed to mean.

You did a pretty good job of working it out :-)


> Is List->int an annotation,
> and if so, who's deciding on that syntax? You seem to have used two
> different arrows in two different ways:

Exactly my point. Beyond your arrow syntax for default parameters, and 
the existing return annotation use, there are two other hypothetical 
proposals for arrow syntax on the table:

- using `->` as an alias for typing.Callable;

- using `=>` as a more compact lambda;

See here:

https://lwn.net/Articles/847960/

I rate the first one (the typing.Callable alias) as extremely likely. It 
is hard to annotate parameters which are functions, and the typing 
community is actively working on making annotations easier. So my gut 
feeling is that it is only a matter of time before we have annotations 
like `func:List->int`. And probably closer to 3.11 than 3.20 :-)

The second, the compact lambda, I rate as only moderately likely. Guido 
seems to like it, but whether somebody writes a PEP and the Steering 
Council accepts it is uncertain. But it is something that does keep 
coming up, and I think we should consider it as a possibility.

Even if `=>` doesn't get used for compact lambda, it is an obvious 
syntax to use for *something* and so we should consider how late-binding 
will look, not just with existing syntax, but also with *likely* future 
syntax.

(When you build a road, you don't plan for just the population you have 
now, but also the population you are likely to have in the future.)

I don't expect anyone to take into account *arbitrary* and unpredictable 
future syntax, but it is wise to take into account future syntax that 
we're already planning or that seems likely.


> List->int # presumably an annotation meaning "function that takes
> List, returns int"

Correct.


> func:ann=>dflt # late-bound default, completely unnecessary here

Come on Chris, how can you say that it is "completely unnecessary"? 
Unless that's an admission that late-bound defaults are all 
unnecessary... *wink*

There is a difference between these two:

def func(arg=lambda a: expression):
...

and this:

def func(arg=None):
if arg is None:
arg = lambda a: expression
...

therefore there will be a difference between:

def func(arg=lambda a: expression):
def func(arg=>lambda a: expression):

If nothing else, in the first case (early binding) you get the same 
function object every time. In the second, you get a freshly made 
function object each time. Since function objects are mutable (they have 
a writable `__dict__` that's a visible difference even if the bodies are 
identical. And they may not be.

But even if it is unnecessary, it will still be permitted, just as we 
will be able to write:

# Now this *actually is* totally unnecessary use of late-binding
def func(arg=>None):


> xs=>expression # presumably a lambda function
> def process(args)->int # return value annotation
> 
> Why should List->int and xs=>expression use different arrows?

Because they do different things. To avoid confusion.

Chris, you wrote the PEP for the walrus operator. Why should the 
assignment operator use a different symbol from the assignment 
statement? Same reason that typing.Callable and lambda will likely use 
different arrows.

Anyway, if you disagree, take it up with Guido, it was his suggestion to 
use different arrows :-P


> Wouldn't
> it be much more reasonable for them to use the same one, whichever
> that be? And if that does turn out to be "=>", then yes, I would be
> looking at changing PEP 671 to recommend := or =: or something, for
> clarity (but still an equals sign with one other symbol next to it).

Oh great, now you're going to conflict with walrus...

def process(obj:Union[T:=something, List[T]]:=func(x:=expression)+x)->T:

We ought to at least try to avoid clear and obvious conflicts between 
new and existing syntax.

Using `:=` is even worse than `=>`, and `=:` is just *begging* to 
confuse newcomers "why do we have THREE different assignment symbols?"


> It's always possible to come up with pathological code. But this is
> only really as bad as you describe if it has zero spaces in it.
> Otherwise, it's pretty easy to clarify which parts go where:
> 
> def process(func: List->int => xs=>expression) -> int:
> ...

"My linter complains about spaces around operators! Take them out!"

Or maybe we should put more in? Spaces are optional.

def process(func : List -> int => xs => expression) -> int:
...

I'm not saying that an experienced Pythonista who is a careful reader 
can't work out what the meaning is. It's not *ambiguous* syntax to a 
careful reader. But it's *confusing* syntax to somebody who may not be 
as careful and experienced as you, or is coding late at night, 

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

2021-12-01 Thread Neil Girdhar


On Wednesday, December 1, 2021 at 1:18:33 AM UTC-5 Chris Angelico wrote:

> I've just updated PEP 671 https://www.python.org/dev/peps/pep-0671/ 
> with some additional information about the reference implementation, 
> and some clarifications elsewhere. 
>
> *PEP 671: Syntax for late-bound function argument defaults* 
>
> Questions, for you all: 
>
> 1) If this feature existed in Python 3.11 exactly as described, would 
> you use it?

No, I would avoid for the sake of readers.  Anyway, it can't be used in any 
public projects until thy drop support for 3.10, which is many years off.

Also, I think this question is quite the biased sample on python-ideas. 
Please consider asking this to less advanced python users, e.g., 
reddit.com/r/python or learnpython. 

>
> 2) Independently: Is the syntactic distinction between "=" and "=>" a 
> cognitive burden? 
>
> (It's absolutely valid to say "yes" and "yes", and feel free to say 
> which of those pulls is the stronger one.)

 Yes.

>
>
> 3) If "yes" to question 1, would you use it for any/all of (a) mutable 
> defaults, (b) referencing things that might have changed, (c) 
> referencing other arguments, (d) something else? 
>
> 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.)

No. 
 

> 5) Do you know how to compile CPython from source, and would you be 
> willing to try this out? Please? :) 
>
> I'd love to hear, also, from anyone's friends/family who know a bit of 
> Python but haven't been involved in this discussion. If late-bound 
> defaults "just make sense" to people, that would be highly 
> informative. 
>
> Any and all comments welcomed. I mean, this is python-ideas after 
> all... bikeshedding is what we do best! 

 


This PEP has a lot of interesting ideas.  I still think that none-aware 
operators (PEP 505) are an easier, more readable general solution to 
binding calculated default values to arguments succinctly.  I think the 
problems with this idea include:
* The caller cannot explicitly ask for default behaviour except by omitting 
the parameter.  This can be very annoying to set up when the parameter 
values are provided from other places, e.g.,
if need_x:
  # do lots of stuff
  x = whatever
else:
  # do more
  x = None
f(x=x, ...)  # easy, but with this PEP, you would have to find a way to 
remove x from the parameter list.  Typically, removing a parameter from a 
dynamically-created parameter list is hard.

* The function code becomes unreadable if the parameter-setting code is 
long.  Having a long piece of code inside the function after "if parameter 
is None" is just fine.  Having none-aware operators would make such code 
more succinct.

* People nearly always avoid writing code in the parameter defaults 
themselves, and this new practice adds a lot of cognitive load.  E.g., 
people rarely write:
def f(x: int = 1+g()) -> None: ...
Parameter lists are already busy enough with parameter names, annotations, 
and defaults.  We don't need to encourage this practice.

In short, I think this is a creative idea, a great exploration.  While 
optional parameters are common, and some of them have defaults that are 
calculated inside the function, my feeling is that people will continue to 
set their values inside the function.

Best,

Neil

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


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 8:18 PM Abdulla Al Kathiri
 wrote:
>
>
>
> > On 1 Dec 2021, at 12:01 PM, Chris Angelico  wrote:
> >
> > On Wed, Dec 1, 2021 at 6:43 PM Abdulla Al Kathiri
> >  wrote:
> >>> On 1 Dec 2021, at 10:16 AM, Chris Angelico  wrote:
> >>> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> >>> defaults, (b) referencing things that might have changed, (c)
> >>> referencing other arguments, (d) something else?
> >> I will definitely use it for default mutable collections like list, set, 
> >> dictionary etc. I will also use it to reference things that might have 
> >> changed. For example, when making callbacks to GUI push buttons, I find 
> >> myself at the start of the function/callback to be fetching the values 
> >> from other widgets so we can do something with them. Now those values can 
> >> be directly passed as late-bound defaults from their respective widgets 
> >> (e.g., def callback(self, text1 => self.line_edit.text()): …).
> >>>
> >
> > Very interesting. That doesn't normally seem like a function default -
> > is the callback ever going to be passed two arguments (self and actual
> > text) such that the default would be ignored?
> Yeah. Let’s say the callback prints the text on the main window console. I 
> could use the same function to print something on the console not related to 
> the default widget changing text. Maybe another push button that prints 
> literal “WOW”. If I made the second argument a default widget (def 
> callback(self, line_edit=self.line_edit):...) and then call line_edit.text() 
> inside the function, I would be able to pass any other widget that has the 
> method text() but I wouldn’t be able to pass a literal text.
>

Ahh gotcha. Then yes, you have a function that takes up to two
parameters (or one if you don't count self), and yes, omitting the
second argument will have the same effect as fetching the text from
that control. So, sounds like a great use for 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/7GUNW4R3TSJC6UXQ5D4P7QQ3XBF75NK2/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Abdulla Al Kathiri


> On 1 Dec 2021, at 12:01 PM, Chris Angelico  wrote:
> 
> On Wed, Dec 1, 2021 at 6:43 PM Abdulla Al Kathiri
>  wrote:
>>> On 1 Dec 2021, at 10:16 AM, Chris Angelico  wrote:
>>> 3) If "yes" to question 1, would you use it for any/all of (a) mutable
>>> defaults, (b) referencing things that might have changed, (c)
>>> referencing other arguments, (d) something else?
>> I will definitely use it for default mutable collections like list, set, 
>> dictionary etc. I will also use it to reference things that might have 
>> changed. For example, when making callbacks to GUI push buttons, I find 
>> myself at the start of the function/callback to be fetching the values from 
>> other widgets so we can do something with them. Now those values can be 
>> directly passed as late-bound defaults from their respective widgets (e.g., 
>> def callback(self, text1 => self.line_edit.text()): …).
>>> 
> 
> Very interesting. That doesn't normally seem like a function default -
> is the callback ever going to be passed two arguments (self and actual
> text) such that the default would be ignored?
Yeah. Let’s say the callback prints the text on the main window console. I 
could use the same function to print something on the console not related to 
the default widget changing text. Maybe another push button that prints literal 
“WOW”. If I made the second argument a default widget (def callback(self, 
line_edit=self.line_edit):...) and then call line_edit.text() inside the 
function, I would be able to pass any other widget that has the method text() 
but I wouldn’t be able to pass a literal text. 
> 
> But, hey, if it makes sense in your code to make it a parameter, sure!
> 
>>> 5) Do you know how to compile CPython from source, and would you be
>>> willing to try this out? Please? :)
>> I haven’t done it from source. I might try to learn how to do it in the next 
>> weekend and give it a try.
>> 
>>> I'd love to hear, also, from anyone's friends/family who know a bit of
>>> Python but haven't been involved in this discussion. If late-bound
>>> defaults "just make sense" to people, that would be highly
>>> informative.
>> I will show this to some of my coworkers who are python experts and I will 
>> report back.
> 
> Thank you! All feedback greatly appreciated.
> 
> Building CPython from source can be done by following these instructions:
> 
> https://devguide.python.org/setup/
> 
> Instead of creating your own clone from the pristine master copy,
> instead clone my repository at https://github.com/rosuav/cpython and
> checkout the pep-671 branch. That'll give you my existing reference
> implementation (it's pretty crummy but it mostly works).
> 
> 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/7VOA7BVTV5UJ24HOPMKO4XK6HW73DH5H/
> 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/HE3ST52STGZQ3OJRVEQ2DGEPCM3RQHZF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Enhancing iterator objects with map, filter, reduce methods

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 7:35 PM Abdulla Al Kathiri
 wrote:
>
>
> Sometimes when I do complicated regular expressions, I like to divide the 
> patterns from a big pattern to small patterns until I reach what I want. re 
> module functions take the text as a second argument. Furthermore, you can’t 
> pass the Match object directly, you need to extract the group/text from it. 
> If we have a placeholder for the passed argument, we could do both 1) put it 
> wherever we want, not necessarily first 2) further manipulate it so it 
> becomes a valid argument
>
> number = text -> re.search(pattern1, _)
> -> re.search(pattern2, _.group(0))
> -> re.search(pattern3, _.group(1))
> -> float(_.group(0))
>
> Yeah that can look ugly I agree (here intentionally the placeholder is 
> overused). But the person can still write a flowing chained operation if they 
> want or if it’s easier for them to understand. Or just do it the traditional 
> way …
>
> text1 = re.search(pattern1, text).group(0)
> text2 = re.search(pattern2, text1).group(1)
> text3 = re.search(pattern3, text2).group(0)
> number = float(text3)
>

Yep, that would definitely be the cleaner way to do it. Not everything
feels like a pipeline.

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


[Python-ideas] Re: Enhancing iterator objects with map, filter, reduce methods

2021-12-01 Thread Abdulla Al Kathiri

Sometimes when I do complicated regular expressions, I like to divide the 
patterns from a big pattern to small patterns until I reach what I want. re 
module functions take the text as a second argument. Furthermore, you can’t 
pass the Match object directly, you need to extract the group/text from it. If 
we have a placeholder for the passed argument, we could do both 1) put it 
wherever we want, not necessarily first 2) further manipulate it so it becomes 
a valid argument 

number = text -> re.search(pattern1, _) 
-> re.search(pattern2, _.group(0)) 
-> re.search(pattern3, _.group(1)) 
-> float(_.group(0))

Yeah that can look ugly I agree (here intentionally the placeholder is 
overused). But the person can still write a flowing chained operation if they 
want or if it’s easier for them to understand. Or just do it the traditional 
way … 

text1 = re.search(pattern1, text).group(0) 
text2 = re.search(pattern2, text1).group(1) 
text3 = re.search(pattern3, text2).group(0) 
number = float(text3)


> It's always possible to make a proposal more general by making it less
> clean. Is the loss of generality from "must pipe into the first
> argument" (or "must pipe into last argument", pick whichever one you
> want to go with) actually as restrictive as you think? People don't
> tend to write add() and pow() like this, because we have operators.
> With real-world code, how commonly is this actually going to be a
> problem?
> 
> 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/YAWWKU3BRXNVJAJIPPKNOOHXWLSUGQU2/
>  
> 
> 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/6MMPIMAZ4NLOXJLV66JVO7BAZYMCUMME/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 7:12 PM Jeremiah Vivian
 wrote:
>
> > I'll reply to this comment once I've done so.
> I just realized that this message replied on a comment instead of the thread. 
> Anyways, it's a really impressive implementation (hope this statement doesn't 
> spark some sort of debate).
>

I'm going to take that at face value and interpret it as a
compliment. Thank you. :)

If you intended that to be taken differently, then yeah, you're
probably not wrong there too - it is, in a sense, quite... impressive.

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


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 6:58 PM Steven D'Aprano  wrote:
>
> On Wed, Dec 01, 2021 at 07:47:49AM -, Jeremiah Vivian wrote:
>
> > > 2) Independently: Is the syntactic distinction between "=" and "=>" a
> > > cognitive burden?
> > No, it isn't much of a cognitive burden.
>
> You say that now, but if you read function definitions that looked
> like this:
>
> def process(func:List->int=>xs=>expression)->int:
> ...
>
>
> would you still agree?
>

I'm not sure what that's supposed to mean. Is List->int an annotation,
and if so, who's deciding on that syntax? You seem to have used two
different arrows in two different ways:

List->int # presumably an annotation meaning "function that takes
List, returns int"
func:ann=>dflt # late-bound default, completely unnecessary here
xs=>expression # presumably a lambda function
def process(args)->int # return value annotation

Why should List->int and xs=>expression use different arrows? Wouldn't
it be much more reasonable for them to use the same one, whichever
that be? And if that does turn out to be "=>", then yes, I would be
looking at changing PEP 671 to recommend := or =: or something, for
clarity (but still an equals sign with one other symbol next to it).

It's always possible to come up with pathological code. But this is
only really as bad as you describe if it has zero spaces in it.
Otherwise, it's pretty easy to clarify which parts go where:

def process(func: List->int => xs=>expression) -> int:
...

Tada, easy grouping.

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


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

2021-12-01 Thread Jeremiah Vivian
> I'll reply to this comment once I've done so.
I just realized that this message replied on a comment instead of the thread. 
Anyways, it's a really impressive implementation (hope this statement doesn't 
spark some sort of debate).
___
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/F7R5WL7OINCGOC2MQJYYXPDBEWSPDB4V/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 7:07 PM Chris Angelico  wrote:
>
> On Wed, Dec 1, 2021 at 6:58 PM Steven D'Aprano  wrote:
> > You say that now, but if you read function definitions that looked
> > like this:
> >
> > def process(func:List->int=>xs=>expression)->int:
> > ...
> >
> >
> > would you still agree?
> >
>
> I'm not sure what that's supposed to mean.

(To clarify: by "that", I mean "the hypothetical line of code", not
the question you're asking. I'm not sure what the code example is
supposed to mean.)

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


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

2021-12-01 Thread Chris Angelico
On Wed, Dec 1, 2021 at 6:43 PM Abdulla Al Kathiri
 wrote:
> > On 1 Dec 2021, at 10:16 AM, Chris Angelico  wrote:
> > 3) If "yes" to question 1, would you use it for any/all of (a) mutable
> > defaults, (b) referencing things that might have changed, (c)
> > referencing other arguments, (d) something else?
> I will definitely use it for default mutable collections like list, set, 
> dictionary etc. I will also use it to reference things that might have 
> changed. For example, when making callbacks to GUI push buttons, I find 
> myself at the start of the function/callback to be fetching the values from 
> other widgets so we can do something with them. Now those values can be 
> directly passed as late-bound defaults from their respective widgets (e.g., 
> def callback(self, text1 => self.line_edit.text()): …).
> >

Very interesting. That doesn't normally seem like a function default -
is the callback ever going to be passed two arguments (self and actual
text) such that the default would be ignored?

But, hey, if it makes sense in your code to make it a parameter, sure!

> > 5) Do you know how to compile CPython from source, and would you be
> > willing to try this out? Please? :)
> I haven’t done it from source. I might try to learn how to do it in the next 
> weekend and give it a try.
>
> > I'd love to hear, also, from anyone's friends/family who know a bit of
> > Python but haven't been involved in this discussion. If late-bound
> > defaults "just make sense" to people, that would be highly
> > informative.
> I will show this to some of my coworkers who are python experts and I will 
> report back.

Thank you! All feedback greatly appreciated.

Building CPython from source can be done by following these instructions:

https://devguide.python.org/setup/

Instead of creating your own clone from the pristine master copy,
instead clone my repository at https://github.com/rosuav/cpython and
checkout the pep-671 branch. That'll give you my existing reference
implementation (it's pretty crummy but it mostly works).

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