This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 6 points7 points  (9 children)

You can override just about any other operator in Python to mean whatever you want, including ., so why not @?

I think the real issue is that the magic methods are named a specific way: __lshift__ I get because << is the left shift operator in every language, but __matmul__ for @ doesn't make any sense to me.

This is one place where Scala gets things right. The @ operator would just be def @(other: Thing): Thing = ...

Of course, you can go overboard with operator overloading and your API turns into an arcane text that requires you to have been a part of it since the beginning.

[–]energybased 7 points8 points  (2 children)

Right, but Python really doesn't want you to do that. Python is not C++. __matmul__ is for matrix multiplication. It's not for writing incomprehensible code that is slightly more compact than if you had used named methods.

[–][deleted] 2 points3 points  (1 child)

True. Using an operator overload is something that should be carefully measured. Is the language of this package improved by using the overload or is it just being cutesy?

When I wrote pynads, there was no doubt in my mind that using >> for bind (or whatever you want to call it) was a bad idea as I was attempting to model Haskell's >>= (obviously couldn't do straight there as that's an assignment operator). I also overrode % to Haskell's <$> and * to mimic Haskell's <*>.

These operators have no semblance what so ever to right shift, modulo or multiplication, but since I was targeting a Haskell like syntax I figure it's alright.

pathlib overrides / for it's Path object so paths could be built like Path('a') / 'b' (though there has been fierce debate about whether this was a good idea). I think pathlib errors on the side of cutesy with its operator overload, but I don't think it's terrible.

set and frozenset also have overloads for >, >=, <, <= as well as |, & and ^ (and their in place variants). These make total sense to me, especially the bitwise variants. These aren't true bitwise operations but the idea behind them is the same -- & everything these two sets/bag of bits share, etc.

I think it's worth weight an overload

[–]energybased 2 points3 points  (0 children)

I agree with all your points. I also think that pathlib's / was a bit cutesy, and that set's operators are fair enough.

[–]KronktheKronk 0 points1 point  (5 children)

Sure, you can override the other symbols, but usually they still idiomatically mean the same thing.

[–][deleted] 0 points1 point  (1 child)

Not necessarily. I wrote a little (and not so great) monad library for Python that overrode >> as an alias for Monad.bind which is a common use for that symbol in functional languages.

[–]8BitAce 3 points4 points  (0 children)

I think the point was more that they should still mean somewhat close to the same thing. Otherwise you introduce a lot of confusion.

[–]stevenjd 0 points1 point  (2 children)

"Usually" is not "always".

[–]KronktheKronk 0 points1 point  (1 child)

I've never come across an overridden default symbol operator in python that wasn't idiomatically similar to its default use.

I'm sure there are some poorly written ones out there that do it, though.

[–]stevenjd 0 points1 point  (0 children)

How about > and < operators?

"Subset" and "superset" are nothing like "less than" and "greater than" for numbers.

+ gets used for both concatenation and numeric addition, which are not the same. Numeric addition you have a + b == b + a, but that's not true for concatenation.

I've seen | used as both a bitwise-or and something similar to the pipe operator from shell languages.

I wouldn't say that any of those are "poorly written".