On 4/23/2018 1:01 PM, Ethan Furman wrote:
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.

You need to borrow the time machine, and get with those early mathematicians that first said:

Let x be the sum of y and z

and convince them that what they should have said was:

Let the sum of y and z be called x.

:)
_______________________________________________
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