On Feb 3, 2020, at 21:14, Random832
If we are going to have a general binary operator mechanism, maybe it should be something more haskell-like,
That’s exactly what I suggested—but more to argue that we don’t want a general binary operator mechanism at all. (The right way to do it would be like Haskell, we don’t want anything like whet Haskell does, therefore we shouldn’t do it.)
with an open-ended set of binary operator names [`identifier` as haskell, perhaps? and/or maybe the unicode math ops section, with stuff like circled plus] and a way to define precedence before the point of use for the parser.
Well, in Haskell, it’s any _string_ of symbol characters, not just any one symbol character. And I think you’d want that even if you open it up to all of Unicode Sm. Not just because most of the non-ASCII characters are hard to type in most environments, but because for an awful lot of operations there’s no obvious single character. For example, what Unicode character would be as good as >> for rshift even to read, much less to type? How could you distinguish |<, <|, |>, >|, and the other map insert/update operators by using single characters for each? And so on. And operator strings don’t work in Python, where things like 2+-3 are perfectly valid sequences of two operators (and 2-=3 is valid and not even an operator). Also, without sectioning, it would be hard to refer to operators—Python has the operator module for all the builtin ones, and operator.add looks just as nice as (+), but that doesn’t help if you need a Python equivalent to (|<>) or a non-ASCII character. Even the backticked names thing, while I don’t think it has any syntactic ambiguity, I don’t think it would be readable in Python, because you don’t read Python in terms of curried functions. For example, in Haskell, if I write odd `dropwhile` xs, that makes sense, because you think of it as the partially applied function (dropwhile odd) being applied to xs, but in Python nobody would think of it as partial(dropwhile, odd)(xs). So it would at best look backward and at worst incomprehensible. But anyway, even if there weren’t any problems with either one, I think the odds of convincing the Python community to add it would be pretty close to nil. That being said, somewhere or other I have a hacky import hook that I could dig up if you want it that lets you do something like this. (Hacky not just in the way that it’s implemented, but also in what it does and doesn’t allow—basically an operator is any string of Sm characters that happens to generate a single ERRORTOKEN when tokenized as normal Python, IIRC.) I can’t imagine using it in real life code, but it was fun to implement.
Perhaps it would also be useful to provide a utility function for performing the __op__/__rop__/NotImplemented/most-derived-class binary operator execution rules on an arbitrary pair of method names, without *any* syntactical support [in order to, say, allow evaluation of custom ASTs for non-python languages on python objects]
That part is not too hard to write, and doesn’t change from version to version, and if we don’t add custom operators (or encourage people to do so with import hooks) I think it will come up very rarely. So I think it’s probably not needed in the stdlib. (If you’ve got an idea for the opposite problem, though, a tool to make it easier to implement __op__ and __rop__ pairs on your types without having to go through the whole mess seen in fractions.Fraction, that would be pretty handy in the stdlib…)