为什么在使用 >>= 运算符时出现语法错误?

Why am I getting a syntax error when using the >>= operator?

注意:我正在导入parsec library, which overloads the >>= (i.e. - __irshift()__) operator

以下Python代码:

#! /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"))

产量:

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

但是,如果我将违规行更改为:

testp = digit().bind(id)

然后我得到:

$ ./irshift_debug.py
5

符合预期。

我认为 >>=bind() 的中缀等价物; 这不正确吗?

因为>>=是语句,不是表达式。它不会计算出可以分配给 testp.

的结果

也许您正在寻找这个?

testp = digit >> id

我既没有使用过 Parsec 也没有使用过 Haskell,所以我无法说明在这个库的上下文中的预期用途。但是,我相信您在这里感到困惑的主要原因是 Python 中的 augmented assignment statements work differently than operators, and therefore reimplementing them works slightly differently as well. (Unlike in C and many other languages, 。)

所以你已经看到了这段代码:

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

不是很明显的是,因为这是覆盖扩充赋值,而不是运算符,returned 值用于重新分配左侧的原始项目。也就是说,这段代码:

a >>= b

不是与简单的相同:

a.bind(b)

相反,它(基本上)等同于:

a = a.bind(b)

中所述,生成的赋值是一个语句,而不是一个表达式,最终 return 根本不是一个值(甚至 None 也不是)。赋值语句的右半部分必须是一个表达式;它不能是另一个赋值语句1。就像在 Python 中一样,你不能做 2:

这样的事情
a = b += c

所以你也做不到:

a = b >>= c

...即使您重新实现了 >>=.


1 唯一的部分例外是最近添加的 assignment expression,但它(有意)在使用上受到限制,在这里不会帮助你。

2 另一方面,“chained assignment”,例如a = b = c 有效。这是一种特殊情况,因为它不仅仅是 return 它们的值的一系列运算符; a = (b = c) 仍然是语法错误。相反,它都被解析为一个赋值语句。

这是一个设计错误。

我转而使用 >= 作为 bind() 的运算符并弃用了 >>=。 parsec.py 的新版本已上传到 pypi。