On 04/22/2018 10:44 PM, Tim Peters wrote:
[Guido]
In reality there often are other conditions being applied to the match for
which `if expr as name` is inadequate. The simplest would be something like

   if ...:
       <something>
   elif (m := re.match('(.*):(.*)', line)) and m.group(1) == m.group(2):
     <whatever>

And the match() call may not even be the first thing to check -- e.g. we
could have

     elif line is not None and (m := re.match('(.*):(.*)', line)) and 
m.group(1) == m.group(2):

I find myself warming more to binding expressions the more I keep them
in mind while writing new code.  And I think it may be helpful to
continue showing real examples where they would help.

Today's example:  I happened to code this a few hours ago:

diff = x - x_base
if diff:
     g = gcd(diff, n)
     if g > 1:
         return g

It's not really hard to follow, but two levels of nesting "feels
excessive", as does using the names "diff" and "g" three times each.
It's _really_ an "and" test:  if the diff isn't 0 and gcd(diff, n) >
1, return the gcd.  That's how I _thought_ of it from the start.

Which this alternative expresses directly:

if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
     return g

So I really like being able to make the assignment in the expression, but I have a really hard time parsing it with the name first.

Attempting to read just the names first:

  if
    diff
      scan for ending right paren
      found
  and
     g
      scan for ending right paren
        oops, found opening left paren
        scan for ending right paren
        found
      resume scanning for final right paren
      found
     > 1:
         return g


Attempting to read expressions first:

  if
    x - x_base
  and
    gcd(diff, n)
      what's diff?
        scan backwards
          diff is x - x_base
    > 1:
        return g
          what's g?
            scan up and backwards
            g is gcd(diff, n)


Attempting to read interleaved:

  if
    skip diff
      x - x_base
      back to diff
    as diff
  and
    skip g
      gcd(diff, n)
      back to g
    as g
  > 1:
      return g


On the other hand, if it were using the "as" keyword:

if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
    return g

I would parse as:

  if
    x - x_base
    as diff
  and
    gcd(diff, n)
    as g
  > 1:
      return g

For me at least, the last is much more readable. Thinking about it some more, the problem (or maybe just my problem) is that I see an "if" or "while" and the I look for the thing that is True or False, and using the ":=" syntax the first thing I see is a placeholder for a result that doesn't exist yet, making me constantly scan backwards and forwards to put all the pieces in the correct place.

With "as", it just flows forwards.

--
~Ethan~
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to