[Python-ideas] Inline assignments using "given" clauses

Angus Hollands goosey15 at gmail.com
Fri May 11 17:12:05 EDT 2018


I'd like to address Steven D'Aprano's reply earlier in the list concerning
"given" vs ":=" clauses.

My stance on the PEP is that the general ability to assign locally within
an expression is undesirable. I gave several reasons, but in general, it
means processing lines becomes more complex, and it makes refactoring more
difficult. I don't think that there are enough cases where it would be
useful to justify its negatives. I can recall but several occasions
(writing regexes, mainly) that I've wanted something like this.

However, if we were to assert that PEP 572 was mandatory, and then dispute
its implementation, then I would argue as follows:

*Cost:*
A lot of people seem quite fixed upon the character cost of "given" vs
":=". I think this is a straw man. Most people spend longer reading than
writing code, so if you agree with that observation, then it's the line
length that you are concerned with. While it is true that overly long lines
are not desirable, it's also true that incredibly short lines are equally
difficult to understand. I don't think that keyword length can be
independently taken too seriously as support for any proposal. Once you
have to include grouping parentheses, this length difference quickly
diminishes anyway.

*Repetition of variable:*
In addition, several people seem unhappy that the "given" keyword approach
sees a repetition of the state variable in question. I think this is
actually a benefit for two reasons. Firstly, you can save the expression in
question to the intermediate variable, and then access a sub expression in
a condition
e.g

while value.in_use given value = get_next_pool_item():
    print(value.refcount())

Instead of

while (value:=get_next_pool_item()) and value.in_use:
    print(value.refcount())

Secondly, it reads in the order that matters. When reading the first line,
one encounters what the condition is evaluating *first*, and then the
implementation details (m=p.match) second. It reads as one would describe a
mathematical equation in a paper, and clearly separates *what you're
interested in* from *what it depends upon*. This is what I particularly
dislike about the ":=" operator approach, the value, and name it is bound
to, are unrelated at the point of evaluation, yet are right next to each
other. It's visual noise. In the example above, the reader has to read the
entire line when trying to find the loop condition.

Someone earlier suggested this was a bad thing, that the expression was far
to the right of the line. I disagree. In cases where you might want to
assign an expression to a variable, it is going to be used at least twice
(otherwise just use the expression directly). At this point, the target
name should be explicit in what it represents. This depends upon context
slightly, such as what is happening in the local region of code. An
example; when matching regexes, the match conditions (if x.group(2) == ...)
are more important than what you matched on, usually.

In addition, the two cases are not identical - if the API is such that
get_next_pool_item should not return None values, this wouldn't be caught
in the ":=" approach, unless you add more conditions. Yes, you could argue
that I've cherry picked an example here. Actually, I haven't; I observed
this after writing the example.

What am I getting at here? In effect, the "given" keyword provides a
superset of use cases to that of ":=". Dare I say it, but *explicit is
better than implicit*.

*Readability:*
A smaller point is that I don't feel that ":=" is very readable. If we had
to use an operator, I think $= is better, but me reasoning for this is
weak. I think it derives from my observation that ":=" is slow to
distinguish from "=".

Regards,
Angus Hollands

On Fri, 11 May 2018 at 17:45 <python-ideas-request at python.org> wrote:

> Send Python-ideas mailing list submissions to
>         python-ideas at python.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://mail.python.org/mailman/listinfo/python-ideas
> or, via email, send a message with subject or body 'help' to
>         python-ideas-request at python.org
>
> You can reach the person managing the list at
>         python-ideas-owner at python.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Python-ideas digest..."
>
>
> Today's Topics:
>
>    1. Re: Inline assignments using "given" clauses (Steven D'Aprano)
>    2. Re: Inline assignments using "given" clauses (Guido van Rossum)
>    3. Re: Inline assignments using "given" clauses (Guido van Rossum)
>    4. Re: Inline assignments using "given" clauses (Steven D'Aprano)
>    5. Re: Inline assignments using "given" clauses (Tim Peters)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 12 May 2018 02:17:24 +1000
> From: Steven D'Aprano <steve at pearwood.info>
> To: python-ideas at python.org
> Subject: Re: [Python-ideas] Inline assignments using "given" clauses
> Message-ID: <20180511161724.GX9562 at ando.pearwood.info>
> Content-Type: text/plain; charset=us-ascii
>
> On Fri, May 11, 2018 at 12:37:43PM +0100, Rhodri James wrote:
>
> > Consider:
> >
> >   while (cmd := get_command()).token != CMD_QUIT:
> >     cmd.do_something()
> >
> > vs:
> >
> >   while cmd.token != CMD_QUIT given cmd = get_command():
> >     cmd.do_something()
>
> Okay, considered. I think the first is preferable.
>
> Much earlier in the PEP 572 discussion, I strongly argued in favour
> of the
>
>     expr as name
>
> syntax on the basis that the most important part of the overall
> expression is "expr", not the assignment target, and therefore that
> should come first. Even though I have accepted that "as" is not viable,
> I still believe that it is preferable to have the expression first, or
> if not first, at least as close to the left as we can get it.
>
> This "given" syntax puts the expr part all the way to the far right of
> the line. A line which is made all the longer for needing to use "given"
> and redundantly state the target name.
>
> It's like we're trying to maximize the distance the eye has to travel
> back and forth when reading.
>
> I have to read to the end of the line before I have any idea where cmd
> has come from or what it is. The fact that it comes from a "given"
> expression comes as a surprise at the end of the line.
>
> Now obviously this doesn't matter if I'm reading lines of code in
> careful detail, but I don't do that all the time. I skim code far more
> than I read it in careful detail, and the closer things are to the left,
> the more likely I am to see them while skimming. The further out they
> are, the easier they are to miss.
>
> I think that "given" will *literally* make reading harder, in that the
> eye has to travel further to spot the relevant expression while skimming
> over code. As I said, I don't think it makes any difference when reading
> closely in detail. But most of my reading of code is skimming to find
> the relevant line or section, and then read closely. I would probably
> skim a hundred lines for every one I read closely.
>
> We read more code than we write, but writing is important too. I think
> the verbosity of "given" (six chars versus two) and the redundancy of
> needing to repeat the name of the target even if you only use it once
> will soon make using this syntax seem like a chore.
>
>
>
> --
> Steve
>
>
> ------------------------------
>
> Message: 2
> Date: Fri, 11 May 2018 12:25:46 -0400
> From: Guido van Rossum <guido at python.org>
> To: Greg Ewing <greg.ewing at canterbury.ac.nz>
> Cc: python-ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] Inline assignments using "given" clauses
> Message-ID:
>         <CAP7+vJLR9N4N1g4U3T-DgYGMHAM_a=
> inDi7dFiF7s5R7DrAQXw at mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> Maybe you could propose some kind of syntax using "whereas"? (It can be
> used as a preamble.)
>
> On Fri, May 11, 2018 at 3:05 AM, Greg Ewing <greg.ewing at canterbury.ac.nz>
> wrote:
>
> > Guido van Rossum wrote:
> >
> >> I'd need well-reasoned explanations
> >>
> >
> > My reasoning is essentially the same as what I've already
> > said about "where". To summarise, "given" sounds like
> > something an English-speaking mathematician would write,
> > whereas ":=" doesn't even have an obvious pronunciation.
> > Some variation on "given" just seems greatly more pythonic
> > to me.
> >
> > --
> > Greg
> >
> > _______________________________________________
> > Python-ideas mailing list
> > Python-ideas at python.org
> > https://mail.python.org/mailman/listinfo/python-ideas
> > Code of Conduct: http://python.org/psf/codeofconduct/
> >
>
>
>
> --
> --Guido van Rossum (python.org/~guido)
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
> http://mail.python.org/pipermail/python-ideas/attachments/20180511/d6443de1/attachment-0001.html
> >
>
> ------------------------------
>
> Message: 3
> Date: Fri, 11 May 2018 12:33:10 -0400
> From: Guido van Rossum <guido at python.org>
> To: Greg Ewing <greg.ewing at canterbury.ac.nz>
> Cc: Python-Ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] Inline assignments using "given" clauses
> Message-ID:
>         <CAP7+vJJ-yEyOnO8N4kmyyxs3qAjFyPFv=
> 7SU3GT3TWjZkRTqpg at mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> On Fri, May 11, 2018 at 3:33 AM, Greg Ewing <greg.ewing at canterbury.ac.nz>
> wrote:
>
> > Most people's short-term memory is good enough to remember
> > that "m" refers to the match object while they read the
> > next couple of lines. IMO, using a longer name would serve
> > no purpose and would just clutter things up.
>
>
> Indeed.
>
> A thought just occurred to me. Maybe we need to instigate a cultural shift
> where people think about style guides as less dictated by hard-coded rules
> that were "passed down from the mountain" and more as derived from research
> that we can all understand about usability. A lot more is known about how
> human perception and various types of memory and learning work than it was
> when the "7 things plus/minus 2" rule was invented (
> https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two
> ).
>
> It would be fascinating to imagine a future where language designers could
> talk about such topic with as much confidence as they talk about the
> efficiency of hash tables.
>
> --
> --Guido van Rossum (python.org/~guido)
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
> http://mail.python.org/pipermail/python-ideas/attachments/20180511/808769ad/attachment-0001.html
> >
>
> ------------------------------
>
> Message: 4
> Date: Sat, 12 May 2018 02:43:14 +1000
> From: Steven D'Aprano <steve at pearwood.info>
> To: python-ideas at python.org
> Subject: Re: [Python-ideas] Inline assignments using "given" clauses
> Message-ID: <20180511164314.GY9562 at ando.pearwood.info>
> Content-Type: text/plain; charset=iso-8859-1
>
> On Fri, May 11, 2018 at 03:47:05PM +0200, Jo?o Santos wrote:
>
> > How do you read something like " while (cmd := get_command()).token !=
> > CMD_QUIT:" in plain english?
>
> I wouldn't if I could avoid it. I hardly ever program by talking about
> code in plain English. Often the lines are gobblydegook:
>
>     zreplace = '%c%02d%02d' % (sign, h, m)  # datetime.py
>
> and even when they are technically pronouncable English:
>
>     # subprocess.py
>     (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) =
>             self._get_handles(stdin, stdout, stderr)
>
> my brain would glaze over by the second "p2c". I prefer to read and
> write code than speak it, and if I need to discuss it, I prefer to use a
> whiteboard so I can write things down.
>
> But if I really needed to, I'd probably start by reading it as:
>
>     while open bracket command defined as get-command close bracket dot
>     token is not equal to command-quit
>
> and then I'd probably drop the "defined" and swap the order around.
>
> Actually, that's not true. I probably wouldn't say that, not in a
> real conversation. What I'd probably say is,
>
>     So, like, I've got this command object, see, which I get
>     from calling get-command, right, and so I get the, um,
>     token attribute, okay, and if that's not equal to the
>     quit value, I loop until it is. Right?
>
>
> (And this is why I prefer *writing* code than *saying* code.)
>
>
> --
> Steve
>
>
> ------------------------------
>
> Message: 5
> Date: Fri, 11 May 2018 11:45:13 -0500
> From: Tim Peters <tim.peters at gmail.com>
> To: Nick Coghlan <ncoghlan at gmail.com>
> Cc: Greg Ewing <greg.ewing at canterbury.ac.nz>, Python-Ideas
>         <python-ideas at python.org>
> Subject: Re: [Python-ideas] Inline assignments using "given" clauses
> Message-ID:
>         <CAExdVNnm0AG4KyjWg-w8CHkoVMh4iPbJtFzO4eApTKLK23=
> qEw at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> [Gustavo Carneiro]
> >>> IMHO, all these toy examples don't translate well to the real world
> >>> because they tend to use very short variable names while in real world
> [good
> >>> written code] tends to select longer more descriptive variable names.
>
> [Greg Ewing]
> >> I don't believe that's always true. It depends on the context.
> >> Sometimes, using long variable names can make code *harder*
> >> to read.
> >>
> >> I don't think there's anything unrealistic about this
> >> example:
> >>
> >>    if m given m = pattern.match(the_string):
> >>       nugget = m.group(2)
> >>
> >> Most people's short-term memory is good enough to remember
> >> that "m" refers to the match object while they read the
> >> next couple of lines. IMO, using a longer name would serve
> >> no purpose and would just clutter things up.
>
> [Nick Coghlan]
> > I've been thinking about this problem, and I think for the If/elif/while
> > cases it's actually possible to allow the "binding is the same as the
> > condition" case to be simplified to:
> >
> >     if command =  pattern.match(the_string):
> >         ...
> >     elif command =  other_pattern.match(the_string):
> >         ...
> >
> >     while data = read_data():
>
> Unless there's some weird font problem on my machine, that looks like
> a single "equals sign".  In which case we'd be reproducing C's
> miserable confusion about whether:
>
>     if (i = 1)
>
> was a too-hastily-typed spelling of the intended:
>
>     if (i == 1)
>
> or whether they were thinking "equals" and typed "=" by mistake.
>
> If so, that would get an instant -1 from any number of core devs, who
> have vivid painful memories of being burned by that in C.  That's not
> just speculation - it came up a number of times in the PEP 572
> threads.
>
>
> > Allowing this would be part of the definition of the if/elif/while
> statement
> > headers, rather than a general purpose assignment expression.
> >
> > The restriction of the LHS to a simple name target would need to be in
> the
> > AST generator rather than in the grammar, but it's hardly the only case
> > where we do that kind of thing. Switching to the given expression form
> would
> > then only be necessary in cases where the condition *wasn't* the same as
> the
> > binding target.
> >
> > A similar enhancement could be made to conditional expressions (adjusting
> > their grammar to permit "EXPR if NAME = EXPR else EXPR") and filter
> clauses
> > in comprehensions (allowing "EXPR for TARGET in EXPR if NAME = EXPR"). In
> > essence, "if", "elif", and "while" would all allow for an "implied given"
> > clause in order to simplify the 90% case where the desired condition and
> the
> > bound expression are the same.
>
> Spell it ":=" (colon equals) instead, and a few core devs would stop
> objecting ;-)
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
>
>
> ------------------------------
>
> End of Python-ideas Digest, Vol 138, Issue 90
> *********************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180511/37cc2ce4/attachment-0001.html>


More information about the Python-ideas mailing list