RE: New assignmens ...

2021-10-29 Thread Avi Gross via Python-list
Antoon,

As long as we understand that my suggestion is not meant to be taken seriously, 
your extension is along the lines I intended.

You might indeed have a family of helper functions whose purpose is to bot make 
a change on the side and return the value to be used in a computation. Your 
specific implementation of something like that:

 def setxattr(obj, attr, value):
 setattr(obj, attr, value)
 return value

Would need to have access to the original object and change it in a way that 
propagates properly. So when you do this:

if setxattr(self, 'ctr', self.ctr - 1) <= 0 :

Then assuming passing it 'ctr' as a string makes sense, and the object self is 
passed by reference, I can see it working without a walrus operator.

But it is extra overhead. This being python, setting values WITHIN an object is 
a challenge. I mean there are ways to make a value readable but not writeable 
or writeable only using a designated method, or an attempt to set the value may 
be intercepted and the interceptor may choose to do something different such as 
ignoring the request if someone tries to set the time to thirteen o'clock or 
even setting it to 1 o'clock instead. The above kind of code perhaps should not 
return value but obj.attr so we see what was stored. But again, Python lets you 
intercept things in interesting ways so I can imagine it showing something 
other that what you stored. 

Sigh

As noted, the general case implemented walrus style may have challenges and 
even efforts like the above may not always be straightforward.

Language design is not as trivial as some think and like with many things, 
adding a neat new feature may open up holes including security holes if people 
figure out how to abuse it. Shutting down some such abilities is exactly why 
people code defensively and try to hide the inner aspects of an object by doing 
things like having a proxy in front of it and creating getters and setters.


-Original Message-
From: Python-list  On 
Behalf Of Antoon Pardon
Sent: Friday, October 29, 2021 10:04 AM
To: python-list@python.org
Subject: Re: New assignmens ...



Op 28/10/2021 om 19:36 schreef Avi Gross via Python-list:
> Now for a dumb question. Many languages allow a form of setting a variable to 
> a value like:
>
>   
>
>  assign(var, 5+sin(x))
>
>   
>
> If we had a function that then returned var or the value of var, cleanly, 
> then would that allow an end run on the walrus operator?
>
>   
>
> if (assign(sign, 5+sin(x)) <= assign(cosign, 5+cos(x))) …
>
>   
>
> Not necessarily pretty and I am sure there may well be reasons it won’t work, 
> but I wonder if it will work in more places than the currently minimal walrus 
> operator.

This was the orginal code to illustrate the question:

 if (self.ctr:=self.ctr-1)<=0

So if I understand your sugested solution it would be something like:

 def setxattr(obj, attr, value):
 setattr(obj, attr, value)
 return value

 if setxattr(self, 'ctr', self.ctr - 1) <= 0

Did I get that right?

-- 
Antoon Pardon.



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

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


Re: New assignmens ...

2021-10-29 Thread Antoon Pardon



Op 28/10/2021 om 19:36 schreef Avi Gross via Python-list:

Now for a dumb question. Many languages allow a form of setting a variable to a 
value like:

  


 assign(var, 5+sin(x))

  


If we had a function that then returned var or the value of var, cleanly, then 
would that allow an end run on the walrus operator?

  


if (assign(sign, 5+sin(x)) <= assign(cosign, 5+cos(x))) …

  


Not necessarily pretty and I am sure there may well be reasons it won’t work, 
but I wonder if it will work in more places than the currently minimal walrus 
operator.


This was the orginal code to illustrate the question:

if (self.ctr:=self.ctr-1)<=0

So if I understand your sugested solution it would be something like:

def setxattr(obj, attr, value):
setattr(obj, attr, value)
return value

if setxattr(self, 'ctr', self.ctr - 1) <= 0

Did I get that right?

--
Antoon Pardon.

   


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


Re: New assignmens ...

2021-10-29 Thread Antoon Pardon




Op 28/10/2021 om 19:36 schreef Avi Gross via Python-list:

Antoon,

  
You keep beating a dead horse. NOBODY denies there are benefits to suggestions like the one we are describing. It is a logical fallacy to keep arguing this way.


Please point to the specific logical falacy you think I am commiting. Don't 
hand wave about what I supposedly
am doing.


And nobody (meaning me) suggests costs are a dominant factor in decisions no 
matter the benefits. The realistic suggestion is to not only weight costs and 
benefits for one proposal but for all reasonable proposals and then choose.


So what if *you* don't suggest that. Others have. Then when I responded to 
those with a remark about seperating
costs and benefits, you budded in with the assertion that those who suggest 
seperating benefits and cost belong
in the accademic world because you understood that remark as implying costs are 
not as issue. I then explain you
misunderdood en now you come with the above.

Maybe you should be more aware of the history of a thread before coming with 
this kind of statements.

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


Re: New assignmens ...

2021-10-28 Thread Chris Angelico
On Fri, Oct 29, 2021 at 4:37 AM Avi Gross via Python-list
 wrote:
> Now for a dumb question. Many languages allow a form of setting a variable to 
> a value like:
>
> assign(var, 5+sin(x))
>
> If we had a function that then returned var or the value of var, cleanly, 
> then would that allow an end run on the walrus operator?
>
> if (assign(sign, 5+sin(x)) <= assign(cosign, 5+cos(x))) …
>
> Not necessarily pretty and I am sure there may well be reasons it won’t work, 
> but I wonder if it will work in more places than the currently minimal walrus 
> operator.

For that to work, the language needs one of three things:

1) A way to pass an lvalue to a function, which it can then change
2) A form of pointer or reference (same thing, but you'd adorn it at
the call site - eg in C, you can write )
3) Magical compiler support for the assign function, so it isn't
really a function, just something that looks like one.

(Are there any other ways? I can't think of any.)

Python currently doesn't have any of those, so you'd have to pick
which one you're advocating for and show how it would be beneficial.
Personally, I'm dubious of all three, but I would be most interested
in the second option and its consequences.

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


RE: New assignmens ...

2021-10-28 Thread Avi Gross via Python-list
Antoon,

 

You keep beating a dead horse. NOBODY denies there are benefits to suggestions 
like the one we are describing. It is a logical fallacy to keep arguing this 
way.

 

And nobody (meaning me) suggests costs are a dominant factor in decisions no 
matter the benefits. The realistic suggestion is to not only weight costs and 
benefits for one proposal but for all reasonable proposals and then choose.

 

I have no idea what the actual cost of changing the parser is. It may be 
trivial or very nontrivial. I do not know if the actual chosen change, from a 
range of possible implementations, will leave the speed of typical programs 
untouched or will add lots of overhead for all programs including the ones not 
using this feature. Nor do I know how many existing features might clash with 
the choice of implementation and need to be changed to resolve them or face 
lots of bug reports later.

 

So what I and others have said here is not based completely on known and 
measured facts. But before approving a proposal, some analysis and estimates 
must be made including a decision to just cancel any work if it over-runs 
targeted costs of various kinds.

 

Now for a dumb question. Many languages allow a form of setting a variable to a 
value like:

 

assign(var, 5+sin(x))

 

If we had a function that then returned var or the value of var, cleanly, then 
would that allow an end run on the walrus operator?

 

if (assign(sign, 5+sin(x)) <= assign(cosign, 5+cos(x))) …

 

Not necessarily pretty and I am sure there may well be reasons it won’t work, 
but I wonder if it will work in more places than the currently minimal walrus 
operator.

 

From: Antoon Pardon  
Sent: Thursday, October 28, 2021 3:03 AM
To: Avi Gross ; python-list@python.org
Subject: Re: New assignmens ...

 

 

Op 27/10/2021 om 20:20 schreef Avi Gross:

I think anyone who suggests we should separate costs from benefits belongs
securely within the academic world and should remain there.
 
Practical things need to be built considering costs. Theoretical things,
sure, cost is not an issue.

 
Seperating costs from benefits doesn't mean costs are not an issue. It means
you don't deny de benefits because there are costs. Sure in the end the costs
may outweight the benefits but that is still not the same as there being no
benefits at all.
 
If you want to weight the costs against the benefits you need to acknowledge
both and not start by denying the benefits because you presume they will
not outweight the costs.
 
-- 
Antoon.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-28 Thread Jon Ribbens via Python-list
On 2021-10-28, Paul Rubin  wrote:
> Chris Angelico  writes:
>> But it all depends on the exact process being done, which is why I've
>> been asking for real examples.
>
> My most frequent use case for walrus is so common that I have sometimes
> implemented a special class for it:
>
>if g := re.search(pat1, text):
>   hack(g.group(1))
>elif g := re.search(pat2, text):
>   smack(g.group(2), "foo")
>...
>
> It's way messier if you have to separate the assignment and test the old
> way.  That said, I'm still on Python 3.7 so I haven't yet gotten to use
> walrus or the new match statement (or is it expression).
>
> I do feel surprised that you can't use an arbitrary lvalue (to use C
> terminology) on the lhs of a walrus.  That seems downright weird to me.
> But, I haven't studied the PEP so I don't know if there was a particular
> rationale.

Well, that's what I was saying: there's no rationale - the limitation
is not even mentioned, let alone explained.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-28 Thread Antoon Pardon




Op 27/10/2021 om 17:05 schreef Christman, Roger Graydon:

I'm going to provide two loop-and-a-half segments to illustrate my 
interpretation
of this PEP and the purpose of the walrus operator:

[ first example ]

Now contrast with this example:

Without the walrus:

replay = True
while replay:
 play_game()
 replay = input("Play again? ") in ['y','Y','yes','Yes']

(I think it silly to ask about playing again at first).

With the walrus:

replay = None
while replay==None or (replay := input("Play again? ") in ['y','Y','yes','Yes']:
  play_game()

To use the walrus operator here, I have to fabricate a value that would
allow me to bypass the input operation, that cannot be otherwise produced.
I do not find this second version any clearer or more intuitive than the first
(and the PEP did emphasize the value of clarity).


But the above is not a one and a half loop. The above is essentially a do
loop (repeat loop in pascal), where you have the test at the end of the
loop body. But because python doesn't have that loop you have to use a
boolean to control the loop that is initialized to True and then later
assign that boolean the result of the test which you use to control this
loop.

Should I think it worth the trouble to rewrite your example, quod non,
it would be like below, with that unneeded list.

while [
play_game(),
input("Play again? ") in ['y', 'Y', 'yes', 'Yes']][-1]:
pass

--
Antoon Pardon.

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


Re: New assignmens ...

2021-10-28 Thread Antoon Pardon




Op 27/10/2021 om 20:20 schreef Avi Gross:

I think anyone who suggests we should separate costs from benefits belongs
securely within the academic world and should remain there.

Practical things need to be built considering costs. Theoretical things,
sure, cost is not an issue.


Seperating costs from benefits doesn't mean costs are not an issue. It means
you don't deny de benefits because there are costs. Sure in the end the costs
may outweight the benefits but that is still not the same as there being no
benefits at all.

If you want to weight the costs against the benefits you need to acknowledge
both and not start by denying the benefits because you presume they will
not outweight the costs.

--
Antoon.

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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Thu, Oct 28, 2021 at 11:08 AM Avi Gross via Python-list
 wrote:
>
> Dave,
>
> You make me wonder about unintended side effects. Are we allowing the ++ and
> --- operations into Python through a side door?
>

class IncrementableInteger(int):
def __pos__(self): return HalfIncremented(self)
def __neg__(self): return HalfDecremented(self)

class HalfIncremented(IncrementableInteger):
def __pos__(self): return IncrementableInteger(self + 1)

class HalfDecremented(IncrementableInteger):
def __neg__(self): return IncrementableInteger(self - 1)

Up to you to make the actual mutation work but have fun making a
nightmare for subsequent maintainers!

ChrisA
PS. Nobody's ever stopping you from def __add_(self, other): return
self * other + 3
Just sayin'.
-- 
https://mail.python.org/mailman/listinfo/python-list


RE: New assignmens ...

2021-10-27 Thread Avi Gross via Python-list
Dave,

You make me wonder about unintended side effects. Are we allowing the ++ and
--- operations into Python through a side door?

any context that allows you to insert the walrus operator like:

index := index + 1
index := index - 1

Is now similar to notations in C/C++ and others like 
++index
--index

If you can set or reset a variable this way, it can even look more efficient
that counting by 2 or more which in C would look like:

++(++index)

Of course we now would get suggestions to just add the pre-increment
operator to Python, and while we are added, for completeness, add the
post-increment version of index++ ...

I mean if cost is no object, and worrying how it may impact current programs
or conflicts is nothing to be concerned about in the interest of some
academic purity ...


-Original Message-
From: Python-list  On
Behalf Of dn via Python-list
Sent: Wednesday, October 27, 2021 4:38 AM
To: python-list@python.org
Subject: Re: New assignmens ...

On 24/10/2021 22.23, O365 Dict wrote:
> 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


Found (all of) the above less-than-obvious to read. Putting it in front of
trainees this morning caused only confusion - even the currently-legal
variation.


Accordingly: is this a job for the walrus operator at all? Let's "talk of
many [other] things"*.


Is this an algorithmic complexity, or a complicated way to look at (and
manipulate) data?

Well, judging from the code (above), use of the walrus certainly presumes
the former. Instead let's review any possibility of the latter (if only for
academic interest)...


What do we want out of the first line? (in no particular order)

1 use calculate_next_couple() to compute (new) a from an (old) a and b
2 use calculate_next_couple() to compute (new) b from an (old) a and b
3 use (new) b to decide if the loop should execute or terminate

The 'problem' then, has been phrased as these three objectives ask too much
of the (current implementation of the) walrus-operator.


NB after one (or more) cycles, when the loop 'returns to the top', what I've
termed 'new' a and b (above), will become (my reference) the 'old'
pair/tuple.


That all looks simple. What is dn complaining about?


Could we use a data structure to continue to keep things straight-forward?

class my_class():
def __init__( self, a, b )->None;
self.a = a
self.b = b

instance = my_class( a, b )


Sorry, you're probably becoming impatient with me. Surely I'm typing more
code than necessary? Maybe, but there are other measures of
code-quality/good-practice/etc, and there's likely more to 'it' than just
these few lines...


First consideration: the algorithm needs us to 'feed' the while-condition.
So let's flesh-out:

def is_more( self )->bool:
# you know what goes here - I don't, but that's not the issue
# the return value is all that matters
return is_there_any_more_data_to_calculate?

In which case, the loop becomes:

while instance.is_more():
more calculations

and 'readability' improves immeasurably!

NB for extra credit, turn the boolean function into a "property", and be
able to omit the (unsightly?) parentheses from the 'call'!


But, not so fast - what about the calculation itself, currently embedded in
calculate_next_couple()?

Well, those details are out of my sight, and I'm assuming include reasonable
complexity - otherwise you wouldn't propose this as a good-example. Allow me
to muddle-through with:

def calculate_next_couple( self )->None:
self.a = calculation of 'new' a
self.b = calculation of 'new' b

To avoid an 'extra' call against the instance from the while-loop, execute
the 'calculate' method from either __init__() or is_more(), as appropriate
(given that it likely needs to precede the return from the latter -
particularly if the computation is 'expensive'). The choice may be
subject-dependent ...


Now within "more calculations", one assumes, references to "a" and "b"
will need to be amended to become 'instance.a' and 'instance.b'. More
typing! What about preserving our fingers?


Readability will further improve when "a" and "b" (etc) are replaced by
'real names'.

The processing steps within "more calculations" could be reviewed. Some may
be can

Re: New assignmens ...

2021-10-27 Thread Abdur-Rahmaan Janhangeer
I no longer track the threads on the subject ... Many simultaneous ones
ongoing!

Kind Regards,

Abdur-Rahmaan Janhangeer
about  | blog

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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Thu, Oct 28, 2021 at 4:34 AM Christman, Roger Graydon  wrote:
> Do you put special code in next_couple() to recognize that the provided 
> arguments
> are actually the first couple so it can return those unmodified, but then 
> require its
> own mental note not to give you an infinite loop forever returning that first 
> couple?
>
> Do you have to define a special case such as (a,b) = (0,0) or (None,None) to 
> tell
> next_couple that you really want the first one?   That seems a little 
> counter-intuitive
> to have something named "next" need a special input to mean "first",

In some cases, there is a very real special startup value (a seed).
For instance, if we're calculating something relating to the
Mandelbrot set:

# The point we're working with
c = (0.25 + 0.125j)
# Always start here
z = (0 + 0j) # or just 0
while abs(z := z*z+c) < 2:
...


Though in this case, you don't look for a next_couple, you look for a
single next value, and the other value is constant.

But it all depends on the exact process being done, which is why I've
been asking for real examples.

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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Thu, Oct 28, 2021 at 4:03 AM Antoon Pardon  wrote:
>
> So suppose I have an arbitrary number of simple statements. The
> latter possible using results from previous assignment and at the
> end a condition to control the one and a half loop. How do you write
> the python code so that the one and a half loop is easy to recognize?
>

The most general way to write a loop-and-a-half is to invert the
condition and break. For cases too complicated to fit into the loop
header, that would be the obvious solution.

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


RE: New assignmens ...

2021-10-27 Thread Avi Gross via Python-list
I think anyone who suggests we should separate costs from benefits belongs
securely within the academic world and should remain there.

Practical things need to be built considering costs. Theoretical things,
sure, cost is not an issue.

Python is not only a real-world set of applications but an evolving one with
a huge embedded base. We have seen how hard it was for some to move when 2.X
and 3.X versions were not upward compatible. Some have refused to move. So
adding new features must not only be done carefully with an eye for  path
upward but also to not destroy existing programs when possible. When a
change is needed, it is often done in stages with some things being
deprecated for a while before the change.

So the half-submerged  walrus operator was added instead of the flying
walrus operator with anti-gravity built in. If the proposal had been to
allow EVERYTHING you and others are suggesting, it is quite possible we
would never have had anything changed and no walrus. True, in another decade
or so, they might have gotten around to adding the unrestricted walrus. or
not.

What we have today is a path that may lead to more functionality
incrementally. If people are using the walrus and like it and it makes
coding easier AND they ask for more, it may come, at incremental cost.

-Original Message-
From: Python-list  On
Behalf Of Antoon Pardon
Sent: Wednesday, October 27, 2021 2:59 AM
To: python-list@python.org
Subject: Re: New assignmens ...



Op 26/10/2021 om 00:24 schreef Chris Angelico:
> TBH, I don't think there's a lot of value in multiple-assignment, 
> since it has a number of annoying conflicts of syntax and few viable 
> use-cases. But if you have great examples of "x.y :=" or "x[y] :=", 
> then by all means, post on python-ideas to propose widening the scope.

I think you should seperate the costs from the benefits. It is not because
the costs can be high there is little value.

And how do you count use cases? What about the following pattern:

while (a, b) := next_couple(a,b)[-1]:
 ...

Is that one use case or is that a use case for each kind of couple?

And even if the benefits are little per case, they can add up with every
occasion such a case pops up.

--
Antoon Pardon.

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

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


Re: New assignmens ...

2021-10-27 Thread Christman, Roger Graydon



On 27/10/2021 8:28, 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 write 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)

> But AIU the walrus operator was introduced so we no longer needed, to write 
> such code,
> with the calculation of the next candidate at the bottom and the test at the 
> top.
> You just confirmed the walrus operator is not very useful once the next 
> candidate is
> no longer just a name.

I must disagree with the first sentence here regarding why the walrus operator 
was introduced.
I read through the PEP, and saw nothing about that in the Rationale.   I do see 
the loop-and-a-half
example, but that actually had its next candidate value near the top (just 
before a break).

I'm going to provide two loop-and-a-half segments to illustrate my 
interpretation
of this PEP and the purpose of the walrus operator:

Without the walrus:

total = 0
value = input()
while value >= 0:
 total += value
 value = input()
print(total)

With the walrus:

total = 0
while (value := input()) > 0:
 total += value
print(total)

In terms of the PEP -- I want to compare each input value to 0 for the loop 
test,
but I also want to preserve that value, to add to the total.   There is a 
subexpression
(input()) within a larger expression (compared to 0) that I wish to name for 
reuse.

Now contrast with this example:

Without the walrus:

replay = True
while replay:
play_game()
replay = input("Play again? ") in ['y','Y','yes','Yes']

(I think it silly to ask about playing again at first).

With the walrus:

replay = None
while replay==None or (replay := input("Play again? ") in ['y','Y','yes','Yes']:
 play_game()

To use the walrus operator here, I have to fabricate a value that would
allow me to bypass the input operation, that cannot be otherwise produced.
I do not find this second version any clearer or more intuitive than the first
(and the PEP did emphasize the value of clarity).

Now reading this in terms of the PEP, where I subexpression (the input)
in a larger expression (seeing if it is the list), I do not really seem to have
a compelling reason to name the value of that subexpression, since I am
not using it for any other purpose, so I could keep the input in the while
condition without using the walrus operator:

first_play = True
while first_play or input("Play again? ") in ['y','Y','yes','Yes']:
play_game()
first_play = False

I do not find this particularly clearer or better than my first version
with the test at the bottom, again since it requires me to do some extra
machinery to avoid the undesired input before the first repetition.
But I might also still argue that this is a little bit clearer than the
walrus alternative above.

My claim from these two examples is that the walrus is helpful to
reduce duplicating or recomputing subexpressions, not simply just
to facilitate code movement.   It is not at all useful for a while loop
condition if the subexpression you wish to evaluate depends on
whether or not this is the first iteration of the loop.

Which then gets me back to your own illustrated use-case for
which I had raised a few questions/objections to before:

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

What is the name of the value you wish to test?b
What is this actually testing?   element [1] of a tuple

So already the code is unclear (and was made worse
when you said the existing walrus operator forced you
to make a list of three elements, two assigned with the
walrus, and then using a subscript of [-1] to get what you wanted.
My proposed solution explicitly tested b, since that
seemed to be what was of interest:

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

To which you had replied:
> But AIU the walrus operator was introduced so we no longer needed, to write 
> such code,
> with the calculation of the next candidate at the bottom and the test at the 
> top.
> You just confirmed the walrus operator is not very useful once the next 
> candidate is
> no longer just a name.

Okay, I would be happy to confirm my belief that the walrus is not very useful
when the thing you wish to test is not the same as the thing you with to assign.

But to relate this use case to my earlier loop-and-a-half examples:

(a,b) := next_couple(a,b)

presumes that there is are values for a and b to begin with for that first call 

Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 27/10/2021 om 18:16 schreef Christman, Roger Graydon:

On 27/10/2021 at 12:45  Antoon Pardon wrote:

However with the introduction of the walrus operator there is a
way to simulate a significant number of one and a half loops.
Consider the following:

  >do
  >   a = expr1
  >   b = expr2
  >   while 2 * a > b:
  >  more calculations


We could write that now as

  >while [
  >a := expr1,
  >   b := expr2,
  >   2 * a > b][-1]:
  >  more calculations

Why don't you try this?


Because this is about a general idea, not about the specifics of the example.
 

while 2 * (a := expr1) > (b := expr2):
   more calculations

It seems you are just compelled to create tuple and lists
in all of your use-cases, even when they serve no purpose.


Do you have a procedure that will always eliminate a list and will be
more or less as readable as the one and a half loop?

I know the list serves no purpose, other than to provide a way to
easily write the calculations in the order that seems most natural.

But being able to write calculations in the order that makes them
more understandable is IMO worth more than eliminating the list.
Even if the list serves no real purpose in the calculations.

So suppose I have an arbitrary number of simple statements. The
latter possible using results from previous assignment and at the
end a condition to control the one and a half loop. How do you write
the python code so that the one and a half loop is easy to recognize?

--
Antoon Pardon

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


Re: New assignmens ...

2021-10-27 Thread Christman, Roger Graydon
On 27/10/2021 at 12:45  Antoon Pardon wrote:
> However with the introduction of the walrus operator there is a
> way to simulate a significant number of one and a half loops.

> Consider the following:

 >do
 >   a = expr1
 >   b = expr2
 >   while 2 * a > b:
 >  more calculations

> We could write that now as

 >while [
 >a := expr1,
 >   b := expr2,
 >   2 * a > b][-1]:
 >  more calculations

Why don't you try this?

while 2 * (a := expr1) > (b := expr2):
  more calculations

It seems you are just compelled to create tuple and lists
in all of your use-cases, even when they serve no purpose.

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon



Op 27/10/2021 om 11:59 schreef Chris Angelico:

You can argue the word "need" all you like, but the fact remains that
YOU want a change, so YOU have to convince people of the benefits.


That is true. But there is nothing wrong in asking what might convince
people.

But I'll give you my thought below and you can decide in how far this
is convincing to you.

I regularly come with a problem for which a one and a half loop is very
suited to solve it. Unfortunately python doesn't have a one and a half
loop. However with the introduction of the walrus operator there is a
way to simulate a significant number of one and a half loops.

Consider the following:

do
a = expr1
b = expr2
   while 2 * a > b:
   more calculations

We could write that now as

while [
a := expr1,
b := expr2,
2 * a > b][-1]:
more calculations

Now there is some ugly side on the above and it may not be obvious at first
what is going on, but once you understand it is a rather easy idiom. I certainly
prefer it over writing something like

while True:
a = expr1
b = expr2
if not (2 * a > b):
break
more calculations.

So for me any limitation on the walrus operator that is removed is a plus 
because
it will allow me to write more one and a half loops in more natural way.

Off course should the python developers decide to intoduce a real one and a half
loop all the above is probably a whole let useful.

--
Antoon Pardon

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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Wed, Oct 27, 2021 at 8:20 PM Antoon Pardon  wrote:
>
>
>
> Op 27/10/2021 om 10:49 schreef Chris Angelico:
> > On Wed, Oct 27, 2021 at 7:46 PM Antoon Pardon  wrote:
> >>> So if you want this added, show a use-case that makes it look way
> >>> better than the alternatives (including a generator, a mid-loop break,
> >>> etc).
> >> Way better according to which criteria? IMO to realy make something like
> >> this you would need a one and a half loop. But although at some time there
> >> was a strong indication it would get included, the idea was eventually 
> >> discarted.
> >>
> >> So I'll argue for incremental better if I see a possibility. A few 
> >> incremental
> >> betters can eventually result in something that is way better than the 
> >> original.
> > According to any criteria you like. Remember, the onus is not on the
> > status quo to justify itself; the onus is on someone who wants to make
> > a change.
>
> Then don't answer that I can justify it according to any criteria I like.
> It will have to be done according to criteria that are important to the
> people who like the status quo. That it will be justified according to
> criteria I like, will be totally unimportant.
>
> > Demonstrate that a change is needed by showing the benefits.
>
> Nothing is needed. But the walrus operator wasn't needed either. Asking to
> show something is needed is putting a burden on who wants to advocate for
> this, that isn't put on others.
>

You can argue the word "need" all you like, but the fact remains that
YOU want a change, so YOU have to convince people of the benefits.

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


Re: New assignmens ...

2021-10-27 Thread Peter J. Holzer
On 2021-10-24 11:23:48 +0200, O365 Dict wrote:
> do:
> a, b = calculate_next_couple(a, b)
> while b:
> more calculations

I actually like that syntax.

-- 
   _  | Peter J. Holzer| Story must make more sense than reality.
|_|_) ||
| |   | h...@hjp.at |-- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |   challenge!"


signature.asc
Description: PGP signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-27 Thread Peter J. Holzer
On 2021-10-27 19:05:52 +1100, Chris Angelico wrote:
> On Wed, Oct 27, 2021 at 6:00 PM Antoon Pardon  wrote:
> > while (a, b) := next_couple(a,b)[-1]:
> >  ...
[...]

> I'm not sure that it's much of a use-case; isn't it an infinite loop as 
> written?
> 
> And that's the problem. With multiple-assignment, the overall value is
> going to be the tuple, so you then have to add extra parentheses and
> subscripting to get what you want to check.

Right. I think for that you would want something like what Go does in
if:

if [assignment-statement ;] condition {
statements
}

Then you could write

while a, b = next_couple(a,b); b:
...

That doesn't even need the walrus operator.

hp

-- 
   _  | Peter J. Holzer| Story must make more sense than reality.
|_|_) ||
| |   | h...@hjp.at |-- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |   challenge!"


signature.asc
Description: PGP signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 27/10/2021 om 10:49 schreef Chris Angelico:

On Wed, Oct 27, 2021 at 7:46 PM Antoon Pardon  wrote:

So if you want this added, show a use-case that makes it look way
better than the alternatives (including a generator, a mid-loop break,
etc).

Way better according to which criteria? IMO to realy make something like
this you would need a one and a half loop. But although at some time there
was a strong indication it would get included, the idea was eventually 
discarted.

So I'll argue for incremental better if I see a possibility. A few incremental
betters can eventually result in something that is way better than the original.

According to any criteria you like. Remember, the onus is not on the
status quo to justify itself; the onus is on someone who wants to make
a change.


Then don't answer that I can justify it according to any criteria I like.
It will have to be done according to criteria that are important to the
people who like the status quo. That it will be justified according to
criteria I like, will be totally unimportant.


Demonstrate that a change is needed by showing the benefits.


Nothing is needed. But the walrus operator wasn't needed either. Asking to
show something is needed is putting a burden on who wants to advocate for
this, that isn't put on others.

--
Antoon Pardon.

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon

Op 27/10/2021 om 10:38 schreef dn via Python-list:

On 24/10/2021 22.23, O365 Dict wrote:

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


Found (all of) the above less-than-obvious to read. Putting it in front
of trainees this morning caused only confusion - even the
currently-legal variation.


A lot of python idioms are less than obvious for trainees when they first
encounter them. I don't think "Is obvious for trainess" is a good measure
to evaluate possible future programming constructs.


Accordingly: is this a job for the walrus operator at all? Let's "talk
of many [other] things"*.

...


That all looks simple. What is dn complaining about?


Could we use a data structure to continue to keep things straight-forward?


Yes off course we could. Before the walrus operator was introduced, we could
also introduce extra code so that we wouldn't need the walrus operator at all.



...
Hope the above gives you some ideas/pause for thought!


No they don't. You have taken an example to illustrate an idea and
treated it as if it was some production code you had to review.

What you are suggesting boils downto that if one has a loop in which
one has two work variables, with a condition on those variable to
control a loop. In order to make use of the walrus operator we should
combine those two work variables into some kind of instance no matter
how contrived.

--
Antoon Pardon.


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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Wed, Oct 27, 2021 at 7:39 PM dn via Python-list
 wrote:
> Accordingly: is this a job for the walrus operator at all? Let's "talk
> of many [other] things"*.

+1

> Could we use a data structure to continue to keep things straight-forward?
>
> class my_class():
> def __init__( self, a, b )->None;
> self.a = a
> self.b = b
>
> instance = my_class( a, b )
>
>
> Sorry, you're probably becoming impatient with me. Surely I'm typing
> more code than necessary? Maybe, but there are other measures of
> code-quality/good-practice/etc, and there's likely more to 'it' than
> just these few lines...
>
>
> First consideration: the algorithm needs us to 'feed' the
> while-condition. So let's flesh-out:
>
> def is_more( self )->bool:
> # you know what goes here - I don't, but that's not the issue
> # the return value is all that matters
> return is_there_any_more_data_to_calculate?
>
> In which case, the loop becomes:
>
> while instance.is_more():
> more calculations
>
> and 'readability' improves immeasurably!

I'd be inclined to write all of this as a generator function, yielding
a series of tuples, but YMMV.

> * this gratuitous and somewhat awkward expression is me claiming to be
> clever by quoting Lewis Carroll - if he isn't sick of me
> baiting-the-hook, it might earn extra brownie-points (or another groan)
> from @Chris...

Given that you were talking about a walrus, I think it was quite apt :)

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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Wed, Oct 27, 2021 at 7:46 PM Antoon Pardon  wrote:
> > So if you want this added, show a use-case that makes it look way
> > better than the alternatives (including a generator, a mid-loop break,
> > etc).
>
> Way better according to which criteria? IMO to realy make something like
> this you would need a one and a half loop. But although at some time there
> was a strong indication it would get included, the idea was eventually 
> discarted.
>
> So I'll argue for incremental better if I see a possibility. A few incremental
> betters can eventually result in something that is way better than the 
> original.

According to any criteria you like. Remember, the onus is not on the
status quo to justify itself; the onus is on someone who wants to make
a change.

Demonstrate that a change is needed by showing the benefits.

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 27/10/2021 om 10:05 schreef Chris Angelico:

On Wed, Oct 27, 2021 at 6:00 PM Antoon Pardon  wrote:



Op 26/10/2021 om 00:24 schreef Chris Angelico:

TBH, I don't think there's a lot of value in multiple-assignment,
since it has a number of annoying conflicts of syntax and few viable
use-cases. But if you have great examples of "x.y :=" or "x[y] :=",
then by all means, post on python-ideas to propose widening the scope.

I think you should seperate the costs from the benefits. It is not because
the costs can be high there is little value.

And how do you count use cases? What about the following pattern:

while (a, b) := next_couple(a,b)[-1]:
  ...

Is that one use case or is that a use case for each kind of couple?

And even if the benefits are little per case, they can add up with every
occasion such a case pops up.


I'm not sure that it's much of a use-case; isn't it an infinite loop as written?

And that's the problem. With multiple-assignment, the overall value is
going to be the tuple, so you then have to add extra parentheses and
subscripting to get what you want to check. That makes it far less
clean, far less tempting, far less valuable. You have to parenthesize
the assignment target (otherwise it'll build a tuple out of one value
and the assigned target), then parenthesize again, and subscript at
the end.


That is only a problem if you want to consider it one. This wouldn't be the
only place in python where you have to be careful with parentheses. IMO it
should be the responsibility of each programmer to decide which way to
program will be most clean. Maybe you are completly right and at the
same time it could still be more clean than the other possibilitie python
allows.


So if you want this added, show a use-case that makes it look way
better than the alternatives (including a generator, a mid-loop break,
etc).


Way better according to which criteria? IMO to realy make something like
this you would need a one and a half loop. But although at some time there
was a strong indication it would get included, the idea was eventually 
discarted.

So I'll argue for incremental better if I see a possibility. A few incremental
betters can eventually result in something that is way better than the original.

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


Re: New assignmens ...

2021-10-27 Thread dn via Python-list
On 24/10/2021 22.23, O365 Dict wrote:
> 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


Found (all of) the above less-than-obvious to read. Putting it in front
of trainees this morning caused only confusion - even the
currently-legal variation.


Accordingly: is this a job for the walrus operator at all? Let's "talk
of many [other] things"*.


Is this an algorithmic complexity, or a complicated way to look at (and
manipulate) data?

Well, judging from the code (above), use of the walrus certainly
presumes the former. Instead let's review any possibility of the latter
(if only for academic interest)...


What do we want out of the first line? (in no particular order)

1 use calculate_next_couple() to compute (new) a from an (old) a and b
2 use calculate_next_couple() to compute (new) b from an (old) a and b
3 use (new) b to decide if the loop should execute or terminate

The 'problem' then, has been phrased as these three objectives ask too
much of the (current implementation of the) walrus-operator.


NB after one (or more) cycles, when the loop 'returns to the top', what
I've termed 'new' a and b (above), will become (my reference) the 'old'
pair/tuple.


That all looks simple. What is dn complaining about?


Could we use a data structure to continue to keep things straight-forward?

class my_class():
def __init__( self, a, b )->None;
self.a = a
self.b = b

instance = my_class( a, b )


Sorry, you're probably becoming impatient with me. Surely I'm typing
more code than necessary? Maybe, but there are other measures of
code-quality/good-practice/etc, and there's likely more to 'it' than
just these few lines...


First consideration: the algorithm needs us to 'feed' the
while-condition. So let's flesh-out:

def is_more( self )->bool:
# you know what goes here - I don't, but that's not the issue
# the return value is all that matters
return is_there_any_more_data_to_calculate?

In which case, the loop becomes:

while instance.is_more():
more calculations

and 'readability' improves immeasurably!

NB for extra credit, turn the boolean function into a "property", and be
able to omit the (unsightly?) parentheses from the 'call'!


But, not so fast - what about the calculation itself, currently embedded
in calculate_next_couple()?

Well, those details are out of my sight, and I'm assuming include
reasonable complexity - otherwise you wouldn't propose this as a
good-example. Allow me to muddle-through with:

def calculate_next_couple( self )->None:
self.a = calculation of 'new' a
self.b = calculation of 'new' b

To avoid an 'extra' call against the instance from the while-loop,
execute the 'calculate' method from either __init__() or is_more(), as
appropriate (given that it likely needs to precede the return from the
latter - particularly if the computation is 'expensive'). The choice may
be subject-dependent ...


Now within "more calculations", one assumes, references to "a" and "b"
will need to be amended to become 'instance.a' and 'instance.b'. More
typing! What about preserving our fingers?


Readability will further improve when "a" and "b" (etc) are replaced by
'real names'.

The processing steps within "more calculations" could be reviewed. Some
may be candidates for inclusion as my_class methods - which would even
enable further simplifications and/or encapsulation of code-suites
relevant to the application, and/or "a" and "b" and the processes around
them.

If the "calculation" of 'next_couple' currently involves looking-up
another data-structure, eg a list of data-points, then combining such
with/into my_class may well yield further simplifications,
encapsulations, and benefits - but all in-theory and complete ignorance
of your application...


Hope the above gives you some ideas/pause for thought!


* this gratuitous and somewhat awkward expression is me claiming to be
clever by quoting Lewis Carroll - if he isn't sick of me
baiting-the-hook, it might earn extra brownie-points (or another groan)
from @Chris...
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 27/10/2021 om 10:05 schreef Chris Angelico:

On Wed, Oct 27, 2021 at 6:00 PM Antoon Pardon  wrote:



Op 26/10/2021 om 00:24 schreef Chris Angelico:

TBH, I don't think there's a lot of value in multiple-assignment,
since it has a number of annoying conflicts of syntax and few viable
use-cases. But if you have great examples of "x.y :=" or "x[y] :=",
then by all means, post on python-ideas to propose widening the scope.

I think you should seperate the costs from the benefits. It is not because
the costs can be high there is little value.

And how do you count use cases? What about the following pattern:

while (a, b) := next_couple(a,b)[-1]:
  ...

Is that one use case or is that a use case for each kind of couple?

And even if the benefits are little per case, they can add up with every
occasion such a case pops up.


I'm not sure that it's much of a use-case; isn't it an infinite loop as written?




And that's the problem. With multiple-assignment, the overall value is
going to be the tuple, so you then have to add extra parentheses and
subscripting to get what you want to check. That makes it far less
clean, far less tempting, far less valuable. You have to parenthesize
the assignment target (otherwise it'll build a tuple out of one value
and the assigned target), then parenthesize again, and subscript at
the end.

So if you want this added, show a use-case that makes it look way
better than the alternatives (including a generator, a mid-loop break,
etc).

ChrisA


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


Re: New assignmens ...

2021-10-27 Thread Chris Angelico
On Wed, Oct 27, 2021 at 6:00 PM Antoon Pardon  wrote:
>
>
>
> Op 26/10/2021 om 00:24 schreef Chris Angelico:
> > TBH, I don't think there's a lot of value in multiple-assignment,
> > since it has a number of annoying conflicts of syntax and few viable
> > use-cases. But if you have great examples of "x.y :=" or "x[y] :=",
> > then by all means, post on python-ideas to propose widening the scope.
>
> I think you should seperate the costs from the benefits. It is not because
> the costs can be high there is little value.
>
> And how do you count use cases? What about the following pattern:
>
> while (a, b) := next_couple(a,b)[-1]:
>  ...
>
> Is that one use case or is that a use case for each kind of couple?
>
> And even if the benefits are little per case, they can add up with every
> occasion such a case pops up.
>

I'm not sure that it's much of a use-case; isn't it an infinite loop as written?

And that's the problem. With multiple-assignment, the overall value is
going to be the tuple, so you then have to add extra parentheses and
subscripting to get what you want to check. That makes it far less
clean, far less tempting, far less valuable. You have to parenthesize
the assignment target (otherwise it'll build a tuple out of one value
and the assigned target), then parenthesize again, and subscript at
the end.

So if you want this added, show a use-case that makes it look way
better than the alternatives (including a generator, a mid-loop break,
etc).

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 26/10/2021 om 00:24 schreef Chris Angelico:

TBH, I don't think there's a lot of value in multiple-assignment,
since it has a number of annoying conflicts of syntax and few viable
use-cases. But if you have great examples of "x.y :=" or "x[y] :=",
then by all means, post on python-ideas to propose widening the scope.


I think you should seperate the costs from the benefits. It is not because
the costs can be high there is little value.

And how do you count use cases? What about the following pattern:

while (a, b) := next_couple(a,b)[-1]:
...

Is that one use case or is that a use case for each kind of couple?

And even if the benefits are little per case, they can add up with every
occasion such a case pops up.

--
Antoon Pardon.

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 26/10/2021 om 19:46 schreef Schachner, Joseph:

Why force unpacking?   Why not assign a tuple?  That would look like a simple 
assignment: x := (alpha, beta, gamma)
And you could access x[0],  x[1] and x[2].

I think asking := to support x, y := alpha, beta  is a request to address an 
unnecessary, easily worked around, issue.  And as previously pointed out you 
can still just use = .


Because the names usually have meaning, while the tuple has not.

And you just confirmed my point that the walrus operator isn't very useful here
by suggesting that I should abandon it and use an assignment.

--
Antoon Pardon.

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


Re: New assignmens ...

2021-10-27 Thread Antoon Pardon




Op 25/10/2021 om 18:47 schreef Christman, Roger Graydon:

Message: 8
Date: Mon, 25 Oct 2021 11:20:52 +0200
From: Antoon Pardon 
To: python-list@python.org
Subject: Re: New assignmens ...
Message-ID: <5761dd65-4e87-8b8c-1400-edb821204...@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)


But AIU the walrus operator was introduced so we no longer needed, to write 
such code,
with the calculation of the next candidate at the bottom and the test at the 
top.
You just confirmed the walrus operator is not very useful once the next 
candidate is
no longer just a name.

--
Antoon.

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


RE: New assignmens ...

2021-10-26 Thread Schachner, Joseph
Why force unpacking?   Why not assign a tuple?  That would look like a simple 
assignment: x := (alpha, beta, gamma)
And you could access x[0],  x[1] and x[2].

I think asking := to support x, y := alpha, beta  is a request to address an 
unnecessary, easily worked around, issue.  And as previously pointed out you 
can still just use = .

--- Joseph S.


Teledyne Confidential; Commercially Sensitive Business Data

-Original Message-
From: Chris Angelico  
Sent: Monday, October 25, 2021 6:25 PM
To: Python 
Subject: Re: New assignmens ...

On Tue, Oct 26, 2021 at 9:19 AM dn via Python-list  
wrote:
> Back on-topic, I am slightly curious:-
>
> aside from 'starting small' with an option to widen/'open-up' later, 
> is there a particular reason why 'the walrus' has not been made 
> available (could not be ...?) for use with object-attributes?

I can't think of any other reasons. But the one you cite is quite an important 
one. In order to get real-world usage examples, the feature was rolled out in 
the restricted form, because threads like this are
*exactly* how the value can be judged. So I do not in any way regret that 
assignment expressions were accepted in their current form, but also, don't be 
afraid to propose an opening up of the syntax. Be specific, and cite usage 
examples that would benefit.

TBH, I don't think there's a lot of value in multiple-assignment, since it has 
a number of annoying conflicts of syntax and few viable use-cases. But if you 
have great examples of "x.y :=" or "x[y] :=", then by all means, post on 
python-ideas to propose widening the scope.

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


Re: New assignmens ...

2021-10-26 Thread Antoon Pardon
Op 25/10/2021 om 23:03 schreef Chris Angelico:
> On Tue, Oct 26, 2021 at 7:18 AM Antoon Pardon  wrote:
>> Op 25/10/2021 om 20:39 schreef Chris Angelico:
>>> On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon  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()]:
>> ...
>>
> And does it unpack what foo returns?
>
> Should it?

1) No it doesn't.

2) I don't care. This is IMO not a question of what should or should not, but 
just a
question of deciding how you want to treat this. I guess that since it doesn't 
unpack
already, this behaviour is more or less fixed for futere releases. Should the 
python
developers in the future decide that de walrus operator can unpack things. The 
above
code will not unpack in order to not break already existing code and if you want
to unpack one will have to write something like:

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

But the answer to that second question has very little relevance to how 
complicated the
parser will be. It is just deciding which of , or := has a higher precedence. 
Since that
decision has already been more or less made, there is not much to decide here 
either.

-- 
Antoon Pardon.

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


RE: New assignmens ...

2021-10-25 Thread Avi Gross via Python-list
Stefan,

Yes, I often pass even fairly trivial functions like "add" or "+" or
whatever the language makes me say, to other functions in various forms of
functional programing. My point is that my example may seem trivial and not
necessary as an EXAMPLE of the greater point that may be easier to
understand than something complex. A sum() is often a generalization  of
adding two things by allowing a second addition to the sub-sum and so on.
But in a straightforward program where I am asking to add exactly two
things, few would use sum(a,b) versus just a+b. On the other hand, in
agreement with you, if I have two vectors or matrices or some other such
data holder and I want to add each position to a corresponding position,
then some kind of call to a function where I pass the two objects and the
name of a function that adds two things, is a decent way to go. But it need
not be a souped-up generalized_sum() function when a simple one will do and
be faster when invoked so many times.

And note often what is used is a temporary lambda anonymous function that
may look like \(x,y) x+y ... or whatever syntax your language uses.


-Original Message-
From: Python-list  On
Behalf Of Stefan Ram
Sent: Monday, October 25, 2021 12:57 PM
To: python-list@python.org
Subject: Re: New assignmens ...

"Avi Gross"  writes:
>Now, yes, nobody needs a function to just add two numbers.

  If one uses a framework like "functools.reduce", the only
  way to reduce an iterable to its sum, is to do just that:
  Write a function to add two numbers.

  Of course, one can circumvent "functools.reduce" (or use
  "operator.add"), but in other cases there are frameworks
  that need to be used and where one sometimes does need to
  write functions (callbacks) as simple as "lambda: None".


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

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


Re: New assignmens ...

2021-10-25 Thread Chris Angelico
On Tue, Oct 26, 2021 at 9:19 AM dn via Python-list
 wrote:
> Back on-topic, I am slightly curious:-
>
> aside from 'starting small' with an option to widen/'open-up' later, is
> there a particular reason why 'the walrus' has not been made available
> (could not be ...?) for use with object-attributes?

I can't think of any other reasons. But the one you cite is quite an
important one. In order to get real-world usage examples, the feature
was rolled out in the restricted form, because threads like this are
*exactly* how the value can be judged. So I do not in any way regret
that assignment expressions were accepted in their current form, but
also, don't be afraid to propose an opening up of the syntax. Be
specific, and cite usage examples that would benefit.

TBH, I don't think there's a lot of value in multiple-assignment,
since it has a number of annoying conflicts of syntax and few viable
use-cases. But if you have great examples of "x.y :=" or "x[y] :=",
then by all means, post on python-ideas to propose widening the scope.

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


Re: New assignmens ...

2021-10-25 Thread dn via Python-list
On 26/10/2021 10.45, Chris Angelico wrote:
> On Tue, Oct 26, 2021 at 8:42 AM Avi Gross via Python-list
>  wrote:
>> Personally, I don't care what is done and suspect I will rarely feel much
>> need to use the current walrus operator, let alone an enhanced Odobenus
>> rosmarus operator like ::== ...
>>
> 
> . wait what?
> 
> Ah. Had to look that one up. :)


Each year I assist friends who own one of local orchards, at harvest
time. I usually run the sealing machine, to preserve fruit which will be
 transported refrigerated. It is such a novelty to be asked to fill-out
a time-sheet. Under "name" it asks for "position", so I entered
"Erignathus barbatus" (bearded seal), which caused similar
consternation, and for some days, until someone thought to look it up...


Back on-topic, I am slightly curious:-

aside from 'starting small' with an option to widen/'open-up' later, is
there a particular reason why 'the walrus' has not been made available
(could not be ...?) for use with object-attributes?
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: New assignmens ...

2021-10-25 Thread Chris Angelico
On Tue, Oct 26, 2021 at 8:42 AM Avi Gross via Python-list
 wrote:
> Personally, I don't care what is done and suspect I will rarely feel much
> need to use the current walrus operator, let alone an enhanced Odobenus
> rosmarus operator like ::== ...
>

. wait what?

Ah. Had to look that one up. :)

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


RE: New assignmens ...

2021-10-25 Thread Avi Gross via Python-list
We have had discussions debating if Python is a good language for teaching.
The short answer is NO unless you only teach a small subset and the students
know there is more they can learn as needed. The language is too rich and
has too many ways to do seemingly anything and that is before you add more
functionality. But that can make it a great language for developers.

Assignments in middle of expressions are often syntactic sugar that may be
re-arranged internally to similar code  than what could be done other ways
without it. It can lead to ambiguities. And it can make it harder for anyone
other than the programmer that wrote it (or them a day later) to understand.

So, while we are at it, why not add the ++ and --- operators that were
deliberately NOT included in Python? Why not throw back pointers?

The short answer is that there are plenty of programming languages to choose
from and some of those do have the features you want and some do not want
them. Sure, you might push in what you want but have you considered all the
places it might be tried? Can you do it in a comprehension where an
assignment is implicitly being done?

[ var := 5  in range(10) ]

The old adage is that some people will be given a finger and take a hand. I
had NOTHING to do with the process but others here know more. Chris suggests
that there was a compromise of sorts here and a choice to implement a
limited subset of fuller functionality for NOW without ruling out doing some
more later. So those wanting more, feel free to petition for it as an
ADDITION but I suggest a more polite tone than trying to say the people who
did it were idiots who did it badly.

Personally, I don't care what is done and suspect I will rarely feel much
need to use the current walrus operator, let alone an enhanced Odobenus
rosmarus operator like ::== ...

-Original Message-
From: Python-list  On
Behalf Of Christman, Roger Graydon
Sent: Monday, October 25, 2021 12:48 PM
To: python-list@python.org
Subject: Re: New assignmens ...

Message: 8
Date: Mon, 25 Oct 2021 11:20:52 +0200
From: Antoon Pardon 
To: python-list@python.org
Subject: Re: New assignmens ...
Message-ID: <5761dd65-4e87-8b8c-1400-edb821204...@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 s

Re: New assignmens ...

2021-10-25 Thread Chris Angelico
On Tue, Oct 26, 2021 at 7:18 AM Antoon Pardon  wrote:
>
> Op 25/10/2021 om 20:39 schreef Chris Angelico:
> > On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon  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()]:
> ...
>

And does it unpack what foo returns?

Should it?

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


Re: New assignmens ...

2021-10-25 Thread Antoon Pardon
Op 25/10/2021 om 20:39 schreef Chris Angelico:
> On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon  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


Re: New assignmens ...

2021-10-25 Thread Chris Angelico
On Tue, Oct 26, 2021 at 5:35 AM Antoon Pardon  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 ...

2021-10-25 Thread Antoon Pardon
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 ...

2021-10-25 Thread Chris Angelico
On Tue, Oct 26, 2021 at 3:07 AM Avi Gross via Python-list
 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 ...

2021-10-25 Thread Christman, Roger Graydon
Message: 8
Date: Mon, 25 Oct 2021 11:20:52 +0200
From: Antoon Pardon 
To: python-list@python.org
Subject: Re: New assignmens ...
Message-ID: <5761dd65-4e87-8b8c-1400-edb821204...@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 ...

2021-10-25 Thread Avi Gross via Python-list
jects, 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  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 ...

2021-10-25 Thread Antoon Pardon

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

2021-10-24 Thread Avi Gross via Python-list
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  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 ...

2021-10-24 Thread Chris Angelico
On Mon, Oct 25, 2021 at 2:13 AM Alan Bawden  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 ...

2021-10-24 Thread O365 Dict
Op 23/10/2021 om 03:22 schreef Stefan Ram:
> Paulo da Silva  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 ...

2021-10-24 Thread Alan Bawden
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 ...

2021-10-23 Thread Chris Angelico
On Sun, Oct 24, 2021 at 7:48 AM Jon Ribbens via Python-list
 wrote:
>
> On 2021-10-23, Chris Angelico  wrote:
> > On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
> > wrote:
> >> On 2021-10-23, Chris Angelico  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 ...

2021-10-23 Thread Ethan Furman

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

2021-10-23 Thread Jon Ribbens via Python-list
On 2021-10-23, Chris Angelico  wrote:
> On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
> wrote:
>> On 2021-10-23, Chris Angelico  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 ...

2021-10-23 Thread Chris Angelico
On Sun, Oct 24, 2021 at 4:39 AM Jon Ribbens via Python-list
 wrote:
>
> On 2021-10-23, Chris Angelico  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 ...

2021-10-23 Thread Jon Ribbens via Python-list
On 2021-10-23, Chris Angelico  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 ...

2021-10-22 Thread dn via Python-list
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 ...

2021-10-22 Thread Chris Angelico
On Sat, Oct 23, 2021 at 12:24 PM Paulo da Silva
 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
> >  wrote:
> >>
> >> On 2021-10-22, Stefan Ram  wrote:
> >>> Paulo da Silva  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 ...

2021-10-22 Thread Paulo da Silva
Às 20:34 de 22/10/21, Chris Angelico escreveu:
> On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
>  wrote:
>>
>> On 2021-10-22, Stefan Ram  wrote:
>>> Paulo da Silva  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 ...

2021-10-22 Thread Greg Ewing

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

2021-10-22 Thread dn via Python-list
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
>>  wrote:
>>>
>>> On 2021-10-22, Stefan Ram  wrote:
 Paulo da Silva  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 ...

2021-10-22 Thread dn via Python-list
On 23/10/2021 08.34, Chris Angelico wrote:
> On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
>  wrote:
>>
>> On 2021-10-22, Stefan Ram  wrote:
>>> Paulo da Silva  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 ...

2021-10-22 Thread Chris Angelico
On Sat, Oct 23, 2021 at 6:24 AM Jon Ribbens via Python-list
 wrote:
>
> On 2021-10-22, Stefan Ram  wrote:
> > Paulo da Silva  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 ...

2021-10-22 Thread Jon Ribbens via Python-list
On 2021-10-22, Stefan Ram  wrote:
> Paulo da Silva  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