6 ms·
This is why I like the ability to define your own operator symbols. I think this is a good compromise between the C++/Python approach and the Java approach. Th
by tikhonj 14y ago
This is why I like the ability to define your own operator symbols. I think this is a good compromise between the C++/Python approach and the Java approach.
The C++ approach has the problems you outlined. A single operator name (like +) gets overloaded with far too many different--and often completely unrelated meanings. Particularly, this violates reasonable expectations about how certain operators behave; for example, + should be commutative. Python's + for lists, very clearly, isn't.
The Java approach of not allowing operator overloading or custom operators is also patently untenable. Just look at the BigInteger class! There are plenty of other cases when using an infix symbol makes for much clearer code.
With a language like Haskell, you can just come up with new operators as you need them. In fact, they act exactly like normal function names: the only difference is in how they're parsed. This also means they're overloaded like normal functions. So while there is a + operator for a bunch of different types, it always represents some notion of addition. This feature can be abused--it's relatively easy to write confusing operator names--but I've found it to be a net benefit in practice. If used correctly, it makes the code much clearer; you just have to be a little careful.
For example, in Haskell you use ++ to concatenate lists. So you can't mistake list concatenation for addition, which is important because they behave in very different ways.
As an aside, if you're willing to use Unicode symbols--and I think you should be!--then you can define cross as × and write a.cross(b) as a × b. In a small expression this does not seem like much of an advantage, but if you are doing more complicated math it makes the code easier to follow. It's also roughly as easy to type: with the right input mode, it's just a \times b.
- mercurial 14y ago> With a language like Haskell, you can just come up with new operators as you need them. In fact, they act exactly like normal function names: the only difference is in how they're parsed. This also means they're overloaded like normal functions. So while there is a + operator for a bunch of different types, it always represents some notion of addition. This feature can be abused--it's relatively easy to write confusing operator names--but I've found it to be a net benefit in practice. If used correctly, it makes the code much clearer; you just have to be a little careful. I found that in practice it is often abused and leads to code full of .+:, >>> and other operators which certainly make a lot of sense to the author of the library, but don't do much for intuitive understanding of a piece of code without reading the documentation for each imported library.
- tikhonj 14y agoThis can be a problem, but it is entirely a matter of library design. In most cases, I haven't found this to be a problem. It helps to follow certain conventions--for example, a name like <|> can be read as "a different version of |" (which represents alternation). I think it's still better than what you get with C++ and Python. I would much rather have a relatively inscrutable <+> operator that does something vaguely like addition than having + do multiple completely different things on different types. Also, for many of these operators, the clarity of having an infix version trumps the fact that you'd have to look it up. Take >>> as an example. Even if it was called something like next, you'd still have to read the Arrow documentation to understand exactly what it did (it's fairly abstract). And compare how the code would look: actionA >>> some complicated action >>> actionB next actionA (next (some complicated action) actionB) Ultimately, it is impossible to design a language that does not allow any bad code. I think having custom operators is better than the main alternatives (C++ and Java styles).
- tehwalrus 14y agoIf compilers supported proper unicode as code not just in strings (like, I believe, Go does) then you could use A ⊗ B for outer products and A ⋅ B for inner products. (a quick google implies that Haskell supports this (http://www.haskell.org/haskellwiki/Unicode-symbols http://www.haskell.org/haskellwiki/Unicode-symbols). Good!)
- mercurial 14y agoYou mean, Unicode symbols. Quite a few languages, including Java, support Unicode letters as identifiers. But frankly, I'd rather stay with cryptic :+: (see the answer to this question [1] for why) 1: http://stackoverflow.com/questions/2793792/is-it-a-good-idea-to-use-unicode-symbols-as-java-identifiers http://stackoverflow.com/questions/2793792/is-it-a-good-idea...
- tehwalrus 14y agoGo has unicode symbols, but I meant just for operators. The reasons listed are important some of the time, but for example when you're a bunch of Chinese developers working on a project it seems sensible to use chinese identifiers in the code (especially if you all only have basic english.) In this situation, everyone is going to have a computer set up to use the character set, so the ����� + ��� situation shouldn't arise. In terms of confusing things at linking / runtime stage, I didn't think of that - maybe you're right! Go gets away with it by being completely compiled down to binary (and requiring the source of all the libraries locally, IIRC.)