Mailing List Archive

New assignmens ...
Hi!

Why doesn't this work
if (self.ctr:=self.ctr-1)<=0:
while this works
if (ctr:=ctr-1)<=0:

Thanks
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
>>Why doesn't this work
>> if (self.ctr:=self.ctr-1)<=0:
>>while this works
>> if (ctr:=ctr-1)<=0:
>
> assignment_expression ::= [identifier ":="] expression,
> but the attribute references "self.ctr" is no identifier!

This seems a surprising omission. You'd expect at least 'attributeref'
and 'subscription' to be allowed, if not the whole of 'target'.
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
<python-list@python.org> wrote:
>
> On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> > Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
> >>Why doesn't this work
> >> if (self.ctr:=self.ctr-1)<=0:
> >>while this works
> >> if (ctr:=ctr-1)<=0:
> >
> > assignment_expression ::= [identifier ":="] expression,
> > but the attribute references "self.ctr" is no identifier!
>
> This seems a surprising omission. You'd expect at least 'attributeref'
> and 'subscription' to be allowed, if not the whole of 'target'.

That's not the primary use-case for assignment expressions, and they
were highly controversial. It is much easier to expand it afterwards
than to restrict it, or to have the feature rejected because people
are scared of some small aspect of it.

If you want to propose relaxing the restrictions, make your use-case
and attempt to convince people of the value.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 23/10/2021 08.34, Chris Angelico wrote:
> On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
> <python-list@python.org> wrote:
>>
>> On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>>> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
>>>> Why doesn't this work
>>>> if (self.ctr:=self.ctr-1)<=0:
>>>> while this works
>>>> if (ctr:=ctr-1)<=0:
>>>
>>> assignment_expression ::= [identifier ":="] expression,
>>> but the attribute references "self.ctr" is no identifier!
>>
>> This seems a surprising omission. You'd expect at least 'attributeref'
>> and 'subscription' to be allowed, if not the whole of 'target'.
>
> That's not the primary use-case for assignment expressions, and they
> were highly controversial. It is much easier to expand it afterwards
> than to restrict it, or to have the feature rejected because people
> are scared of some small aspect of it.


ie neither can one use subscripted elements, eg list-elements, as the
LHS of an assignment expression.
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
With apologies for pressing Send too early...

On 23/10/2021 08.41, dn via Python-list wrote:
> On 23/10/2021 08.34, Chris Angelico wrote:
>> On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
>> <python-list@python.org> wrote:
>>>
>>> On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>>>> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
>>>>> Why doesn't this work
>>>>> if (self.ctr:=self.ctr-1)<=0:
>>>>> while this works
>>>>> if (ctr:=ctr-1)<=0:
>>>>
>>>> assignment_expression ::= [identifier ":="] expression,
>>>> but the attribute references "self.ctr" is no identifier!
>>>
>>> This seems a surprising omission. You'd expect at least 'attributeref'
>>> and 'subscription' to be allowed, if not the whole of 'target'.
>>
>> That's not the primary use-case for assignment expressions, and they
>> were highly controversial. It is much easier to expand it afterwards
>> than to restrict it, or to have the feature rejected because people
>> are scared of some small aspect of it.
>
>
> ie neither can one use subscripted elements, eg list-elements, as the
> LHS of an assignment expression.

Whereas, creating a list (or tuple...) is legal because the structure's
name is an "identifier"!

if ( l := [ 1, 2, 3 ] > [ 1, 2 ] ):
print( "True" )

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 23/10/21 8:49 am, dn wrote:
> Whereas, creating a list (or tuple...) is legal because the structure's
> name is an "identifier"!

No, the restriction only applies to the LHS. The list construction
is on the RHS.

--
Greg

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
Às 20:34 de 22/10/21, Chris Angelico escreveu:
> On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
> <python-list@python.org> wrote:
>>
>> On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>>> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
>>>> Why doesn't this work
>>>> if (self.ctr:=self.ctr-1)<=0:
>>>> while this works
>>>> if (ctr:=ctr-1)<=0:
>>>
>>> assignment_expression ::= [identifier ":="] expression,
>>> but the attribute references "self.ctr" is no identifier!
>>
>> This seems a surprising omission. You'd expect at least 'attributeref'
>> and 'subscription' to be allowed, if not the whole of 'target'.
>
> That's not the primary use-case for assignment expressions, and they
> were highly controversial. It is much easier to expand it afterwards
> than to restrict it, or to have the feature rejected because people
> are scared of some small aspect of it.
>
> If you want to propose relaxing the restrictions, make your use-case
> and attempt to convince people of the value.
>
Well, I didn't follow the discussion of this new feature, but the reason
I can see behind allowing it seems so valid for for ctr:=ctr-1 as for
self.ctr:=self.ctr-1. The kind of use is exactly the same. One is for a
normal function, the other for a method.
IMHO this makes no sense at all. Arguable may be for example LHS
ctrs[i], or something like that. But self.ctr ...! Too weird.

Thanks
Paulo
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Sat, Oct 23, 2021 at 12:24 PM Paulo da Silva
<p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:
>
> Às 20:34 de 22/10/21, Chris Angelico escreveu:
> > On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
> > <python-list@python.org> wrote:
> >>
> >> On 2021-10-22, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> >>> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
> >>>> Why doesn't this work
> >>>> if (self.ctr:=self.ctr-1)<=0:
> >>>> while this works
> >>>> if (ctr:=ctr-1)<=0:
> >>>
> >>> assignment_expression ::= [identifier ":="] expression,
> >>> but the attribute references "self.ctr" is no identifier!
> >>
> >> This seems a surprising omission. You'd expect at least 'attributeref'
> >> and 'subscription' to be allowed, if not the whole of 'target'.
> >
> > That's not the primary use-case for assignment expressions, and they
> > were highly controversial. It is much easier to expand it afterwards
> > than to restrict it, or to have the feature rejected because people
> > are scared of some small aspect of it.
> >
> > If you want to propose relaxing the restrictions, make your use-case
> > and attempt to convince people of the value.
> >
> Well, I didn't follow the discussion of this new feature, but the reason
> I can see behind allowing it seems so valid for for ctr:=ctr-1 as for
> self.ctr:=self.ctr-1. The kind of use is exactly the same. One is for a
> normal function, the other for a method.
> IMHO this makes no sense at all. Arguable may be for example LHS
> ctrs[i], or something like that. But self.ctr ...! Too weird.
>

I've never used ctr:=ctr-1 either, though, so I don't know the actual
use cases. Why is this being used in an assignment expression? Is it
an ersatz loop?

Common use-cases include:

if m := re.match(...):

while data := thing.read():

etc. All of them are doing exactly two things: testing if something is
empty, and if it isn't, using it in a block of code.

In what situations do you need to mutate an attribute and also test
it, and how much hassle is it to simply break it out into two lines?
The onus is on you to show that it needs to be more flexible.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 23/10/2021 12.51, Greg Ewing wrote:
> On 23/10/21 8:49 am, dn wrote:
>> Whereas, creating a list (or tuple...) is legal because the structure's
>> name is an "identifier"!
>
> No, the restriction only applies to the LHS. The list construction
> is on the RHS.


That contention (above) may have been taken slightly out-of-context.

Referring back to the previous contribution: mutating a list-element is
not legal, because just like an object's attribute addressed with
dotted-notation, a subscripted object is not regarded as an identifier.
Whereas creating a (whole) new list (for example) IS legal, because the
list's name IS an identifier.

Yes, the LHS must be an identifier - the point that was made in the
first response (quoting "Python Language Reference") and since.
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
> I've never used ctr:=ctr-1 either, though, so I don't know the actual
> use cases. Why is this being used in an assignment expression? Is it
> an ersatz loop?
>
> Common use-cases include:
>
> if m := re.match(...):
>
> while data := thing.read():
>
> etc. All of them are doing exactly two things: testing if something is
> empty, and if it isn't, using it in a block of code.
>
> In what situations do you need to mutate an attribute and also test
> it, and how much hassle is it to simply break it out into two lines?

It's not hard to imagine something like:

def get_expensive(self):
return self.expensive or self.expensive := self.calculate_expensive()

> The onus is on you to show that it needs to be more flexible.

Is it though? It seems to me that the onus is on you to show that
this special case is special enough to be given its own unique
existence. It's a bit surprising that the PEP doesn't discuss this
decision at all.
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
<python-list@python.org> wrote:
>
> On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
> > I've never used ctr:=ctr-1 either, though, so I don't know the actual
> > use cases. Why is this being used in an assignment expression? Is it
> > an ersatz loop?
> >
> > Common use-cases include:
> >
> > if m := re.match(...):
> >
> > while data := thing.read():
> >
> > etc. All of them are doing exactly two things: testing if something is
> > empty, and if it isn't, using it in a block of code.
> >
> > In what situations do you need to mutate an attribute and also test
> > it, and how much hassle is it to simply break it out into two lines?
>
> It's not hard to imagine something like:
>
> def get_expensive(self):
> return self.expensive or self.expensive := self.calculate_expensive()

I usually write this sort of thing the other way:

def get_expensive(self, key):
if key not in self.cache:
self.cache[key] = ...
return self.cache[key]

and then if you don't like the duplication, the cleanest way is to put
the expensive calculation into the __missing__ method of a dict
subclass.

> > The onus is on you to show that it needs to be more flexible.
>
> Is it though? It seems to me that the onus is on you to show that
> this special case is special enough to be given its own unique
> existence. It's a bit surprising that the PEP doesn't discuss this
> decision at all.

The PEP was accepted. Thus it is now up to someone proposing a change
to show that the change is worthwhile.

Python has frequently started with a more restricted rule set, with
the option to make it less restricted in the future. Case in point:
Decorator syntax used to be limited to a small set of options, aimed
at the known use-cases at the time. Then very recently, that was
opened up to basically any expression.

https://www.python.org/dev/peps/pep-0614/

Read over that document for an excellent example of how to take a
tight proposal and recommend that it be made more flexible. Assignment
expressions are currently in the restricted form, allowing only simple
names, and it's up to you to propose and demonstrate the value of the
increased flexibility.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
> On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
><python-list@python.org> wrote:
>> On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
>> > In what situations do you need to mutate an attribute and also test
>> > it, and how much hassle is it to simply break it out into two lines?
>>
>> It's not hard to imagine something like:
>>
>> def get_expensive(self):
>> return self.expensive or self.expensive := self.calculate_expensive()
>
> I usually write this sort of thing the other way:
>
> def get_expensive(self, key):
> if key not in self.cache:
> self.cache[key] = ...
> return self.cache[key]
>
> and then if you don't like the duplication, the cleanest way is to put
> the expensive calculation into the __missing__ method of a dict
> subclass.

Sure, but if "there's already another way of doing it" was a winning
argument then assignment expressions wouldn't have been accepted into
the language at all.

>> > The onus is on you to show that it needs to be more flexible.
>>
>> Is it though? It seems to me that the onus is on you to show that
>> this special case is special enough to be given its own unique
>> existence. It's a bit surprising that the PEP doesn't discuss this
>> decision at all.
>
> The PEP was accepted. Thus it is now up to someone proposing a change
> to show that the change is worthwhile.
>
> Python has frequently started with a more restricted rule set, with
> the option to make it less restricted in the future. Case in point:
> Decorator syntax used to be limited to a small set of options, aimed
> at the known use-cases at the time. Then very recently, that was
> opened up to basically any expression.
>
> https://www.python.org/dev/peps/pep-0614/
>
> Read over that document for an excellent example of how to take a
> tight proposal and recommend that it be made more flexible. Assignment
> expressions are currently in the restricted form, allowing only simple
> names, and it's up to you to propose and demonstrate the value of the
> increased flexibility.

I think we're allowed to discuss things in this group without them
having to turn into formal proposals. Personally I've never written
a Python assignment expression, and I think it'll be a few years
before Python 3.8 is old enough for them to be conveniently usable.
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 10/23/21 6:42 AM, Jon Ribbens via Python-list wrote:
> On 2021-10-23, Chris Angelico wrote:

>> The onus is on you to show that it needs to be more flexible.
>
> Is it though?

Yes.

> It seems to me that the onus is on you to show that
> this special case is special enough to be given its own unique
> existence.

It already has existence, so no further proof is needed.

> It's a bit surprising that the PEP doesn't discuss this
> decision at all.

In conversations as long as that one was, I'm not surprised this and maybe a couple other options didn't make it back to
the PEP. Nevertheless, I recall the decision to start simple, and expand later if needed.

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Sun, Oct 24, 2021 at 7:48 AM Jon Ribbens via Python-list
<python-list@python.org> wrote:
>
> On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
> > On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
> ><python-list@python.org> wrote:
> >> On 2021-10-23, Chris Angelico <rosuav@gmail.com> wrote:
> >> > In what situations do you need to mutate an attribute and also test
> >> > it, and how much hassle is it to simply break it out into two lines?
> >>
> >> It's not hard to imagine something like:
> >>
> >> def get_expensive(self):
> >> return self.expensive or self.expensive := self.calculate_expensive()
> >
> > I usually write this sort of thing the other way:
> >
> > def get_expensive(self, key):
> > if key not in self.cache:
> > self.cache[key] = ...
> > return self.cache[key]
> >
> > and then if you don't like the duplication, the cleanest way is to put
> > the expensive calculation into the __missing__ method of a dict
> > subclass.
>
> Sure, but if "there's already another way of doing it" was a winning
> argument then assignment expressions wouldn't have been accepted into
> the language at all.

There is always another way of doing it. The question is not so much
"is this something that's currently absolutely impossible?" but more
"how ugly is the current way of doing things?". Ugly is, of course,
somewhat subjective, but if the current way of doing things involves a
lot of extra hassle, or is error-prone, etc, etc, then there's room to
show improvement.

The original PEP showed this improvement in ways that involved simple
names. Expanding on this is a separate proposal.


> > Read over that document for an excellent example of how to take a
> > tight proposal and recommend that it be made more flexible. Assignment
> > expressions are currently in the restricted form, allowing only simple
> > names, and it's up to you to propose and demonstrate the value of the
> > increased flexibility.
>
> I think we're allowed to discuss things in this group without them
> having to turn into formal proposals. Personally I've never written
> a Python assignment expression, and I think it'll be a few years
> before Python 3.8 is old enough for them to be conveniently usable.

Well, if you don't use them, then you don't really have a horse in
this race, so it doesn't matter. Someone who *does* want to make use
of them can read over that document etc etc, and demonstrate the value
of the proposal.

BTW, it doesn't have to be a "formal proposal" in any sense; it just
needs to be a logical and reasonable argument showing the value of the
improvement (or the problems with the status quo).

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
It seemed weird to me that only an identifier was allowed to be the
target of an assignment expression. Then it occurred to me that
function definitions are another place where only identifiers are
allowed, but where I could imagine an attributeref or a subscription
being used. E.g.

def table[i](x):
...

would mean the same thing as:

def _temp_(x):
...
table[i] = _temp_

I don't immediately see that this would screw up the grammar in any way,
so why not allow it? A `def` statement is just another form of
assignment, so just as for `:=` expressions, we should allow the target
to be as general as possible!

I'm guessing that about 70% of you will think that this is a horrible
idea, 10% of you will find it compelling, and the remaining 20% will
find themselves conflicted. You can count me in that last category...

--
Alan Bawden
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
Op 23/10/2021 om 03:22 schreef Stefan Ram:
> Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
>> Well, I didn't follow the discussion of this new feature, but the reason
>> I can see behind allowing it seems so valid for for ctr:=ctr-1 as for
>> self.ctr:=self.ctr-1. The kind of use is exactly the same. One is for a
>> normal function, the other for a method.
> The intention of the introduction of the assignment expression
> was to allow grab the values of subexpressions so as to be able
> to later use these value. This can be done with an identifier:
>
> if env_base := os.environ.get( "PYTHONUSERBASE", None ):
> return env_base
>
> . I am wondering what use cases are there for having something
> different than an identifier on the left side.

Well I have the following use case:

while (temp_result := calculate_next_couple(a, b))[1]:
a, b = temp_result
more calculations

Which IMO would be clearer if I could just write:

while ((a, b) := calculate_next_couple(a,b))[1]:
more calculations

Of course it would even more clear if I could write something like:

while (a, b) := calculate_next_couple(a, b); b:
more calculations

or

do:
a, b = calculate_next_couple(a, b)
while b:
more calculations

--
Antoon.

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Mon, Oct 25, 2021 at 2:13 AM Alan Bawden <alan@csail.mit.edu> wrote:
>
> It seemed weird to me that only an identifier was allowed to be the
> target of an assignment expression. Then it occurred to me that
> function definitions are another place where only identifiers are
> allowed, but where I could imagine an attributeref or a subscription
> being used. E.g.
>
> def table[i](x):
> ...
>
> would mean the same thing as:
>
> def _temp_(x):
> ...
> table[i] = _temp_
>
> I don't immediately see that this would screw up the grammar in any way,
> so why not allow it? A `def` statement is just another form of
> assignment, so just as for `:=` expressions, we should allow the target
> to be as general as possible!
>
> I'm guessing that about 70% of you will think that this is a horrible
> idea, 10% of you will find it compelling, and the remaining 20% will
> find themselves conflicted. You can count me in that last category...

This has come up periodically, but it's a bit tricky to define some of
the edge cases, like what the function's name should be. But it would
definitely help with building dispatch tables. Currently, I tend to
build them with a decorator:

tools = {}
def tool(f):
tools[f.__name__] = f
return f

@tool
def frobnicate(): ...

@tool
def spamify(): ...

In theory, it would be possible to do this:

def tools["frobnicate"](): ...

But I'm not sure that it's truly better.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
RE: New assignmens ... [ In reply to ]
No, many things need not be as general as possible once you consider how
much work it may take to develop code and how many bugs and oddities might
be introduced and even how much it may slow the interpreter.

I could make an argument that everywhere you can put in a character string
should also allow a regular expression but why? It makes no sense to allow
you to supply a filename to create using a regular expression as you are not
matching anything. Worse, perfectly valid string that may contain a dollar
sign or period or many other characters used in regular expression may
really be messed up if evaluated as a regular expression. So is it any
wonder NOBODY suggests the above be done?

As Chris has said, something was added to Python that is a partial
implementation. There are fairly reasonable ways to do additional things and
until recently, those were the proper and only way. But the recent change
does not preclude a later upgrade if anyone is not only convinced it is
worth doing but of higher priority than the scarce resources needed to do
lots of other worthy and requested things including fixing bugs.

I imagine you can create some fairly complex examples you can suggest should
be handled for generality including some very indirect references created
dynamically. The code to recognize any abstract use of symbols may not only
slow down every operation of even the simplest type but generate all kinds
of error messages nobody will understand, let alone translate into other
languages properly! Right now, it is simpler. An error message can say that
only certain simple usages are allowed.

Now if anyone wants to donate a few hundred thousand dollars if used to make
the change, or offer to do it free, who knows? Of course, this means anyone
using the feature may need to check your version of Python to see if the
feature exists before ...



-----Original Message-----
From: Python-list <python-list-bounces+avigross=verizon.net@python.org> On
Behalf Of Alan Bawden
Sent: Sunday, October 24, 2021 3:53 AM
To: python-list@python.org
Subject: Re: New assignmens ...

It seemed weird to me that only an identifier was allowed to be the target
of an assignment expression. Then it occurred to me that function
definitions are another place where only identifiers are allowed, but where
I could imagine an attributeref or a subscription being used. E.g.

def table[i](x):
...

would mean the same thing as:

def _temp_(x):
...
table[i] = _temp_

I don't immediately see that this would screw up the grammar in any way, so
why not allow it? A `def` statement is just another form of assignment, so
just as for `:=` expressions, we should allow the target to be as general as
possible!

I'm guessing that about 70% of you will think that this is a horrible idea,
10% of you will find it compelling, and the remaining 20% will find
themselves conflicted. You can count me in that last category...

--
Alan Bawden
--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On 25/10/2021 01:46, Avi Gross via Python-list wrote:
> No, many things need not be as general as possible once you consider how
> much work it may take to develop code and how many bugs and oddities might
> be introduced and even how much it may slow the interpreter.
...
> I imagine you can create some fairly complex examples you can suggest should
> be handled for generality including some very indirect references created
> dynamically. The code to recognize any abstract use of symbols may not only
> slow down every operation of even the simplest type but generate all kinds
> of error messages nobody will understand, let alone translate into other
> languages properly! Right now, it is simpler. An error message can say that
> only certain simple usages are allowed.

I don't consider this a strong argument. Limiting the scope of the walrus operator
will just force people organizing there code where they will use a normal assignment.
So the resulting code will not be faster, less complex or generate less error messages
because the complexity of the assignment that is needed is still the same.

Or you force people to be "creative" as follows:

Suppose I would like to write a loop as follows:

while ((a, b) := next_couple(a, b))[1]:
do needed calculations


What I can do is write it as follows:

while [tmp := next_couple(a,b), a := tmp[0], b := tmp[1]][-1]:
do needed calculations

I really don't see what is gained by "forcing" me to right the second code over the first.

--
Antoon Pardon

--
https://mail.python.org/mailman/listinfo/python-list
RE: New assignmens ... [ In reply to ]
Antoon,

Just to be clear. I am talking about a different measure of efficiency. If
you have code that handles a limited functionality properly it can be quite
simple. If you then expand the code to handle ever more situations, then it
may do things like a series of IF statements to determine which of many
things to do so it now takes a while to just reach the part that does the
most common case. I have seen people use code that knows what arguments to
expect and just does things simply, like adding two integers together. Then
the code is improved so it detects if either argument is floating point and
now does any needed conversions. Soon you add support for complex numbers or
character strings that look like "23" and then even parse "twelve dollars
and forty two cents" in English and then a few other languages. Next you
accept range objects and other things that make sense to add and accept an
undefined number of arguments and name the darn thing sum_everything() and
proudly show it off. It now has an amazing number of errors it can propagate
or warn about. But, you can still use it to add 2 and 2.

Now, yes, nobody needs a function to just add two numbers. If that bothers
you, make is add the absolute values or something a tad more interesting.
But the point is that any code that invokes sum_everything() may now pay a
penalty in terms of performance just in the beginning part where it tests
how many arguments it got, what types they are, and so on.

The topic here is the Python run-time parser though. It is reading your code
and doing whatever complex set of things it has to do to parse from a fairly
large set of possible valid programs as well as invalid ones. I have never
looked deeply at how it works but my guess is that somewhere in there are
concepts like:

simple_asignment_expression can look like THIS.
complex _assignment expression can look like simple_assignment_expression OR
THAT OR ...

So to parse code you often need to look at alternate ways of connecting
symbols and hopefully find the one and only way it has to be looked at.
Parentheses as an example have many possible meanings and you may not know
which meaning when you encounter it until you keep going and see where there
may be a matching one but ignore any within a character string. I won't go
on but the point is that the parser can jump through more hoops even in the
most usual cases when it has to look for new cases not originally designed
in.

Your argument that people using other techniques to get the functionality
they want is not really relevant as I do not deny it. My point is that the
most common ways NORMALLY used are the ones that drive the efficiency of a
system. So if adding functionality to include new cases/situations doubles
the time it takes to do the most common case and that is used 98% of the
time, then how much overall gain for the other 2% is needed to
counterbalance it?

I find a common pattern in software that often looks like extra layers
around a function call. There may be a function to create an object given a
character string argument like vector("integer", 1, 2, 3") or
vector("character", "a", "b") that lets you create all kinds of vectors.
Someone comes along with a bright idea to make programmers instead call
make_integer(1, 2, 3) and make_character("a", "b") and more like that. We
now have lots of new function that are just going to turn around and call
vector() with a different appropriate string as the first argument and pass
along the rest. We now have a function calling a second function. Yes, there
are many possible advantages here including ways to check if you are using
your code as intended. But there is overhead. And in a tight loop repeated
millions of times, can you blame a programmer who knows, if they just call
vector() directly, or perhaps a deeper function that vector() calls when it
knows it is using integers?

I will end with this. If someone wants to design a new language from scratch
and with a goal of starting with as general a set of concepts as they can,
fine. Design it carefully. Build it and if it works well enough, use it. But
to ask an existing language to add features or expand existing ones is not
at all the same thing and requires much more care. In python, you can find
areas that are a bit confusing such as how multiple inheritance in objects
is done. It can require some tweaking to make your objects in ways that the
right thing is inherited from the other objects the way you want if more
than one has the same method and you can have subtle errors. Arguably the
darn thing is too general and many other languages instead decide not to
support multiple inheritance and may use other interesting ways to get
similar functionality. But although this can be a very nice feature allowing
you to design quite sophisticated sets of objects that inherit all kinds of
nifty powers from other existing objects, it can be a drag on performance if
it does a search through a big mess to find the right function to call at
run time! Sometimes it may be easier to not use multiple inheritance in some
part of your code and use a work-around to get what you want.

I am not against extending Python in the direction someone wants. I am FOR
careful examination and study before making the change and weighing whether
this is likely to be more useful than other things being asked for and other
relative costs. Many things turn out not to be needed. I recall programs
designed to use every letter of the alphabet (and other symbols) whether
needed or not. I mean things like "d" for delete and "a" for add and "t" for
transpose. Just to be complete, make up something that "q" or "z" do. Why?
Not because anyone wants or needs those. I have seen projects like that then
take longer to create and harder to test and the users mostly thought it was
too complex and rarely or never used some functionality. I have made macros
that allow something in an emacs editor like transpose-letter and
transpose-word and continued with sentences, paragraphs, chapters and
something beyond like transpose-on-paste-buffers. But most people actually
just do a cut and move and paste operation for the more complex scenarios
even if they remember the fancy version exists and is bound to some
forgotten series of keys clicked together like control-X control-alt-t or
something.



-----Original Message-----
From: Python-list <python-list-bounces+avigross=verizon.net@python.org> On
Behalf Of Antoon Pardon
Sent: Monday, October 25, 2021 5:21 AM
To: python-list@python.org
Subject: Re: New assignmens ...

On 25/10/2021 01:46, Avi Gross via Python-list wrote:
> No, many things need not be as general as possible once you consider
> how much work it may take to develop code and how many bugs and
> oddities might be introduced and even how much it may slow the
interpreter.
...
> I imagine you can create some fairly complex examples you can suggest
> should be handled for generality including some very indirect
> references created dynamically. The code to recognize any abstract use
> of symbols may not only slow down every operation of even the simplest
> type but generate all kinds of error messages nobody will understand,
> let alone translate into other languages properly! Right now, it is
> simpler. An error message can say that only certain simple usages are
allowed.

I don't consider this a strong argument. Limiting the scope of the walrus
operator will just force people organizing there code where they will use a
normal assignment.
So the resulting code will not be faster, less complex or generate less
error messages because the complexity of the assignment that is needed is
still the same.

Or you force people to be "creative" as follows:

Suppose I would like to write a loop as follows:

while ((a, b) := next_couple(a, b))[1]:
do needed calculations


What I can do is write it as follows:

while [tmp := next_couple(a,b), a := tmp[0], b := tmp[1]][-1]:
do needed calculations

I really don't see what is gained by "forcing" me to right the second code
over the first.

--
Antoon Pardon

--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
Message: 8
Date: Mon, 25 Oct 2021 11:20:52 +0200
From: Antoon Pardon <antoon.pardon@vub.be>
To: python-list@python.org
Subject: Re: New assignmens ...
Message-ID: <5761dd65-4e87-8b8c-1400-edb8212048db@vub.be>
Content-Type: text/plain; charset=utf-8; format=flowed
On 25/10/2021 11:20, Anton Pardon wrote:
> Suppose I would like to write a loop as follows:

> while ((a, b) := next_couple(a, b))[1]:
> do needed calculations


> What I can do is write it as follows:

> while [tmp := next_couple(a,b), a := tmp[0], b := tmp[1]][-1]:
> do needed calculations

> I really don't see what is gained by "forcing" me to right the second code over the first.

No, nobody is forcing you to right it the second way over the first.
Nobody is forcing you to use the walrus operator at all!

Instead, I would recommend something more like:

while b:
do needed calculations
(a,b) = next_couple(a,b)

This requires even less typing than what you had before!

But it also raises a whole lot of problems with this particular example:
-- neither a nor b is defined in your sample while loop. It seems you would
need to initialize a and b before your while loop (and mine)
-- is b truly a boolean value, or are you short-cutting some other value?
-- are a and b truly necessary parameters to next_couple, or are they just
there to remind the function of its previous return values?
If the latter, poerhaps you want a stream or list or something with yield

This example (and some of the others I have seen) just highlight how
programmers will take advantage of any new tool to help them write
worse code than if they did not have the tool. In my mind, the walrus
operator was designed to serve a particular niche case like this one:

while (x := input()) > 0:

where not having the operator required duplicating the input() operation
both before the loop and at the end of the loop -- or more complicated
cases where some additional operations had to be performed to get
that test value for the while condition (such as getting the b out of (a,b)).

But the walrus only adds a benefit if it is there to avoid the duplication
of the code that is used to obtain that test condition. This next_couple
example does not qualify, since apparently (a,b) are initialized by some
other means (and not be a call to next_couple with undefined values)

Or the other abuse I saw recently about using the walrus operator:

while (self.ctr := self.ctr-1) > 0:

-- there was no compelling reason for a loop counter to be a class variable
(anyone who peeks at this counter when the loop is down would only see a zero)
-- this requires self.ctr to be initialized to a value one higher than the first
meaningful value (start at 11 if you want to count down from 10)
So my recommended alternative, which furthermore also takes less typing:

while ctr > 0:
...
ctr = ctr-1

TL;DR: The Walrus operator serves the purpose as described in its PEP
just as it is, and I see no compelling reason to expand its use.
It is there to reduce code size by eliminating a duplication of code,
If the code you write using the walrus operator is longer or more
complicated than the code would be without it, you are misusing it.

Roger Christman
Pennsylvania State University
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Tue, Oct 26, 2021 at 3:07 AM Avi Gross via Python-list
<python-list@python.org> wrote:
> I will end with this. If someone wants to design a new language from scratch
> and with a goal of starting with as general a set of concepts as they can,
> fine. Design it carefully. Build it and if it works well enough, use it.

I'll add to this: Please do exactly that! It's a great mental
exercise. Sometimes you'll end up using it as a domain-specific
language, or maybe it'll become a sort of ersatz command interpreter,
or something; other times, you do the work of designing it purely for
the effect of trying it, and you've learned how languages work.

What you'll find is that there are extremes that are utterly and
completely useless, such as Turing tarpits (almost no language
facilities, but technically possible to write anything), or things so
generic that they are nothing more than containers ("a script in this
language is whatever code will make it happen"). In between, every
programming language has to make decisions. What are its goals? What
kinds of problems should be easy to solve in this language? Is it
meant to be general-purpose and able to do most things, or
special-purpose but extremely elegant within its domain?

And along the way, you'll gain a better appreciation for every
language you work with, plus a mental comprehension that lets you
understand WHY this language or that language is good for some task.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
Op 25/10/2021 om 18:06 schreef Avi Gross via Python-list:
> Antoon,
>
> Just to be clear. I am talking about a different measure of efficiency.

No you are not.

>
> The topic here is the Python run-time parser though.

Yes and that is what I am talking about.

> It is reading your code
> and doing whatever complex set of things it has to do to parse from a fairly
> large set of possible valid programs as well as invalid ones. I have never
> looked deeply at how it works but my guess is that somewhere in there are
> concepts like:
>
> simple_asignment_expression can look like THIS.
> complex _assignment expression can look like simple_assignment_expression OR
> THAT OR ...
>
> So to parse code you often need to look at alternate ways of connecting
> symbols and hopefully find the one and only way it has to be looked at.
> Parentheses as an example have many possible meanings and you may not know
> which meaning when you encounter it until you keep going and see where there
> may be a matching one but ignore any within a character string. I won't go
> on but the point is that the parser can jump through more hoops even in the
> most usual cases when it has to look for new cases not originally designed
> in.

IMO that extra complexity is insignificant. You really don't reduce the complexity of your
parser much if you would limit it so that indexes can only be names so that the programmer
instead of being able to write:

var = tab[some expression]

is forced to write it as:

index = some expression
var = tab[index]

Because all that machinery to evaluate some expression needs to be there anyway.

In the same way we have already all the machinery present for assignments.

By putting limits on the walrus code, you are not reducing complexity, you are increasing it.
You are increasing complexity because you can't just reuse the code that handles an ordinary
assignment. You now need specific code to limit it's use.

--
Antoon Pardon.

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon <antoon.pardon@vub.be> wrote:
> By putting limits on the walrus code, you are not reducing complexity, you are increasing it.
> You are increasing complexity because you can't just reuse the code that handles an ordinary
> assignment. You now need specific code to limit it's use.
>

What does this code do?

while x, y := foo():
...

Is it more complicated or less complicated when arbitrary assignment
targets are permitted?

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
Op 25/10/2021 om 20:39 schreef Chris Angelico:
> On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon <antoon.pardon@vub.be> wrote:
>> By putting limits on the walrus code, you are not reducing complexity, you are increasing it.
>> You are increasing complexity because you can't just reuse the code that handles an ordinary
>> assignment. You now need specific code to limit it's use.
>>
> What does this code do?
>
> while x, y := foo():
> ...
>
> Is it more complicated or less complicated when arbitrary assignment
> targets are permitted?

Well I would guess it would do something similar to

while [x, y := foo()]:
...

--
https://mail.python.org/mailman/listinfo/python-list

1 2 3  View All