-1

Note: I am importing the parsec library, which overloads the >>= (i.e. - __irshift()__) operator.

The following Python code:

#! /usr/bin/env python

# irshift_debug.py

from parsec import *

def id(x):
    """Identity parser."""
    return string("").result(x)

testp = digit() >>= id

print(testp.parse("5"))

yields:

$ ./irshift_debug.py
  File "./irshift_debug.py", line 9
    testp = digit() >>= id
                    ^
SyntaxError: invalid syntax

But, if I change the offending line to:

testp = digit().bind(id)

then I get:

$ ./irshift_debug.py
5

as expected.

I thought that >>= was the infix equivalent of bind(); is that incorrect?

dbanas
  • 1,707
  • 14
  • 24
  • 2
    >> in python is a bit operator... what are u trying to do exactly? – Srishruthik Alle Jan 08 '22 at 00:34
  • @SrishruthikAlle, I'm trying to use the infix operator that is a shortcut for the bind() function in the parsec library. – dbanas Jan 08 '22 at 00:56
  • 1
    Python is not C++: Assignment is not an operator and therefore has no resulting value. Note that limited support for an assignment expression was added to Python 3.8 in [PEP 572](https://www.python.org/dev/peps/pep-0572/). – martineau Jan 08 '22 at 01:04
  • “bind” is the name of `>>=` in Haskell, but it’s not a Python operator. – Ry- Jan 08 '22 at 05:00
  • 1
    @Ry-, the (>>=) operator gets overloaded in the parsec library. Please, see the newly added note at the top of the original question. – dbanas Jan 09 '22 at 15:09
  • 2
    `>>=` isn't an operator; it's part of the syntax for augmented assignments. It can only be used in a *statement*, never in an *expression*. – chepner Jan 09 '22 at 18:11
  • 2
    The fact that you get a syntax error is a hint that whatever you've done wrong is independent of the definition of any dunder method, because Python hasn't even gotten to the point where dunder methods are relevant. The parser couldn't even generate a syntax tree, let alone one that the code generator can use to produce something that needs to find the appropriate definition of a dunder method to implement. – chepner Jan 09 '22 at 18:15

3 Answers3

4

Because >>= is a statement, not an expression. It doesn't evaluate to a result that can be assigned to testp.

Perhaps you were looking for this?

testp = digit >> id
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • 2
    More properly, `>>=` is what is called an [augmented assignment statement](https://docs.python.org/3/reference/simple_stmts.html#augmented-assignment-statements) in Python. – martineau Jan 08 '22 at 01:09
1

I have used neither Parsec nor Haskell, so I can't speak to the intended use in the context of this library. However, I believe the main root of your confusion here is that augmented assignment statements work differently than operators, and therefore reimplementing them works slightly differently as well. (Unlike in C and many other languages, assignment is not an operator in Python.)

So you've seen this code:

def __irshift__(self, other):
    '''Implements the `(>>=)` operator, means `bind`.'''
    return self.bind(other)

What isn't immediately obvious is that, because this is overriding augmented assignment, not an operator, the returned value is used to reassign the original item on the left. In other words, this code:

a >>= b

is not the same as simply:

a.bind(b)

Instead, it is (essentially) equivalent to:

a = a.bind(b)

As mentioned in Alexander's answer, the resulting assignment is a statement, not an expression, and can't ultimately return a value at all (not even None). The right half of an assignment statement has to be an expression; it can't be another assignment statement1. Just as in Python you can't do things like2:

a = b += c

So you also can't do:

a = b >>= c

...even when you've reimplemented >>=.


1 The only partial exception is the recently added assignment expression, but it is (intentionally) limited in use, and won't help you here.

2 On the other hand, "chained assignment", e.g. a = b = c, does work. It's something of a special case, in that it's not simply a series of operators that return their values; a = (b = c) is still a syntax error. Instead, it's all parsed as one assignment statement.

CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
1

It is a design mistake.

I have turned to use >= as the operator for bind() and deprecated >>=. A new release of parsec.py has been upload to pypi.

sighingnow
  • 791
  • 5
  • 11