Mailing List Archive

1 2 3  View All
Re: New assignmens ... [ In reply to ]
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 ... [ In reply to ]
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 <python-list-bounces+avigross=verizon.net@python.org> 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 ... [ In reply to ]
On Thu, Oct 28, 2021 at 4:03 AM Antoon Pardon <antoon.pardon@vub.be> 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 ... [ In reply to ]
On Thu, Oct 28, 2021 at 4:34 AM Christman, Roger Graydon <dvl@psu.edu> 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 ... [ In reply to ]
I no longer track the threads on the subject ... Many simultaneous ones
ongoing!

Kind Regards,

Abdur-Rahmaan Janhangeer
about <https://compileralchemy.github.io/> | blog
<https://www.pythonkitchen.com>
github <https://github.com/Abdur-RahmaanJ>
Mauritius
--
https://mail.python.org/mailman/listinfo/python-list
RE: New assignmens ... [ In reply to ]
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 <python-list-bounces+avigross=verizon.net@python.org> 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 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

--
https://mail.python.org/mailman/listinfo/python-list
Re: New assignmens ... [ In reply to ]
On Thu, Oct 28, 2021 at 11:08 AM Avi Gross via Python-list
<python-list@python.org> 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 ... [ In reply to ]
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 ... [ In reply to ]
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 ... [ In reply to ]
On 2021-10-28, Paul Rubin <no.email@nospam.invalid> wrote:
> Chris Angelico <rosuav@gmail.com> 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 ... [ In reply to ]
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 <antoon.pardon@vub.be>
Sent: Thursday, October 28, 2021 3:03 AM
To: Avi Gross <avigross@verizon.net>; 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 ... [ In reply to ]
On Fri, Oct 29, 2021 at 4:37 AM Avi Gross via Python-list
<python-list@python.org> 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 &var)
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 ... [ In reply to ]
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 ... [ In reply to ]
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 ... [ In reply to ]
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 <python-list-bounces+avigross=verizon.net@python.org> 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

1 2 3  View All