[HN Gopher] Not Growing a Language
       ___________________________________________________________________
        
       Not Growing a Language
        
       Author : todsacerdoti
       Score  : 51 points
       Date   : 2021-04-03 16:54 UTC (6 hours ago)
        
 (HTM) web link (kevingal.com)
 (TXT) w3m dump (kevingal.com)
        
       | mrkeen wrote:
       | I wish it weren't referred to as 'operator overloading'. I don't
       | want to think of them as 'operators' and I don't want to
       | 'overload' anything.
       | 
       | Is putting a method on a class called 'method overloading'?
       | 
       | I want to be able to define `plus` on my datatypes and I want to
       | be able to define `+` on my datatypes.
       | 
       | `+` on my datatype overloads `+` on `Integer` no more than
       | `get()` on my datatype overloads `get()` on someone else's
       | datatype.
       | 
       | I am _not_ taking an existing Integer type and giving it a new
       | definition of `+`, which is what  'operator overloading' would
       | be.
        
         | rzwitserloot wrote:
         | > Is putting a method on a class called 'method overloading'?
         | 
         | It most certainly is.. _if_ the method you are adding has the
         | name of a functionality that is either inherently part of its
         | spec or effectively so if by community conventions.
         | 
         | e.g. when you make a method with signature `boolean
         | equals(Object other)` in java, it is literally, as in the very
         | spec itself calls it this, 'overloading'.
         | 
         | The term is appropriate. `*` is commonly understood to be some
         | sort of numeric operation with the properties that it is
         | reflective, commutative, etc. If you decide to add a definition
         | for a class you're writing, the term 'overloading' is entirely
         | appropriate.
        
         | tlb wrote:
         | Julia is like this. a+b is just syntactic sugar for (:call :+ a
         | b). There's a function + for various type pairs. The fact that
         | the compiler can optimize it to 1 instruction is an
         | implementation detail.
        
         | Kototama wrote:
         | According to wikipedia it's also sometimes called _operator ad
         | hoc polymorphism_. Better?
        
           | clhodapp wrote:
           | It's not any better. Ad hoc polymorphism is a defined _thing_
           | just as overloading is a defined _thing_ (in fact, it 's a
           | superset of OO-style "overloading"). When you allow operators
           | to be defined for user-authored datatypes, these are features
           | that you _might_ choose to support for operators, but that
           | doesn 't mean that all user-defined operators are inherently
           | using these features.
           | 
           | Concretely, in defining a + operator on your BigInt class
           | that can only accept another BigInt, you haven't overloaded
           | the + operator. It would only be overloading if you defined a
           | second form that accepted some other type of object.
        
         | AnimalMuppet wrote:
         | But when you overload '+', it overloads it _as an operator_ ,
         | keeping things like "operator precedence". Overloading
         | functions doesn't do that.
        
       | ModernMech wrote:
       | The problem with operator overloading is that it introduces a
       | degree of ambiguity into the language. You can say what you will
       | about the dot notation for math, and I agree it's unwieldy, but
       | at least it's consistent. And at any rate, the mess can be solved
       | with a comment. If every library I use has its own definition of
       | what + is in different contexts, now I have to consult the
       | library for all the ways they use + and keep that straight in my
       | head. This complexity is a nontrivial constant cost for
       | developers.
       | 
       | The real reason people seem to like operator overloading is that
       | it's a feature that scratches a certain itch. We all love our
       | code to look elegant and simple, and often times this need
       | inspires developers to set down the path of language design. This
       | is a long dark path that's not for the feint of heart. Many who
       | start down this road dabble for a bit and then turn back quickly
       | when things get rough.
       | 
       | Operator overloading is a low barrier of entry to language
       | design, so developers looking to make simple elegant code reach
       | for it in the name of aesthetics. They get to feel like language
       | designers by playing with syntax, while staying within the safety
       | of a language they know and love. But in my opinion, the
       | aesthetic gains are not worth the increase in complexity for the
       | language. Both for writers and readers of code.
        
         | kpgiskpg wrote:
         | That's a question of interface design. You can also create
         | ugly, ambiguous interfaces with functions (10 arguments, it
         | mutates some of them, etc), or any other language feature. If a
         | library designer uses operator overloading well, then it should
         | be obvious what "a+b" is doing if you know the types involved.
         | 
         | On one hand it's a question of philosophy -- do you provide the
         | user with tools to better express themselves, if they might
         | possibly shoot themselves in the foot and create a crappy
         | interface?
         | 
         | On the other hand, it could be an engineering issue. Maybe it's
         | not worth the technical challenge or the increase in complexity
         | for the language designers. I'd be more sympathetic to this
         | reason. Then again, Python and C++ manage it.
        
         | ducharmdev wrote:
         | I think you have a good point when it comes to the public API
         | exposed to users of a module or library; it's one thing if you
         | are just using operator overloading in your internal
         | implementations, but I'd imagine it'd be pretty confusing not
         | seeing docstrings or being able to search for specific methods.
         | Not sure how you would easily find that in the docs without
         | peering into the object whose methods are overloaded.
        
         | gumby wrote:
         | > The problem with operator overloading is that it introduces a
         | degree of ambiguity into the language.
         | 
         | How is it any different in any way from any other overloading
         | (i.e. generic functions or allowing two classes to have methods
         | with the same name?)
        
           | GoOnThenDoTell wrote:
           | It's much easier to grep for function names
        
             | gumby wrote:
             | These days even emacs users can use LSP.
             | 
             | Nevertheless I agree with your point.
             | 
             | But shouldn't overloading be used where its results are
             | intuitive thus lookup should rarely be needed? /s
        
         | karmakaze wrote:
         | It's not that complicated--other languages typically define
         | precedence levels and grouping (left/right) for operators. Any
         | symbols not in the predefined set can all have the same
         | precedence level and group left-to-right.
        
         | pjmlp wrote:
         | Really consistent, how can you ensure that _sum(a, b)_ actually
         | does what it states without looking at the implementation?
        
       | Asooka wrote:
       | > Take a look and see. What do you think this BigInteger math
       | does?
       | 
       | The problem for me is it's not clear if a.add(b) is "a+b" or
       | "a+=b". With the regular operators it's always obvious which
       | mutate the value and which return a new value, whereas the
       | methods can do whatever they want. Yes, the operator is a method
       | call and can do anything, but in practice everyone makes them do
       | the obvious thing and follows the convention. There is no
       | convention that "add" should return a new value - it's a verb,
       | verbs usually mutate the object.
        
       | hinkley wrote:
       | I recall an early conversation on operator overloading in Java
       | and the other people were almost but not quite putting a thought
       | together:
       | 
       | Limit operator overloading to classes that extend Number and 90%
       | of the excesses of operator overloading are impossible.
       | 
       | You probably shouldn't be using += for your concatenation code
       | anyway (interpolation is often more powerful). The only other
       | place you will "miss" it is in data types that are vector values,
       | and you could probably figure out a rule for that in a later
       | iteration.
        
         | zokier wrote:
         | What would be the definition of such "Number" class? How would
         | it prevent any abuse?
        
           | 6gvONxR4sf7o wrote:
           | A ring [0] might be too general, but I can't think of
           | anything that isn't a ring that I'd want to call a "number"
           | class. A field [1] is less general and might be a better fit.
           | It probably depends whether you want a matrix to be able to
           | be a "number," which I'd be inclined to do.
           | 
           | [0] https://en.wikipedia.org/wiki/Ring_(mathematics)
           | 
           | [1] https://en.wikipedia.org/wiki/Field_(mathematics)
        
             | klyrs wrote:
             | The type systems underlying computer algebra systems like
             | Sage, GAP, etc. are immensely more complex than this. Read
             | the source of Sage (lots of python/cython) and the source
             | of GAP (pure c; everything is basically a void *). Operator
             | overloading is immensely helpful for entire classes of
             | objects -- groups, rings, fields, categories, combinatorial
             | objects... some of them are kinda number-like, but for
             | example groups can support multiplication and division but
             | not addition/subtraction (unless it's an abelian group and
             | you'd rather represent it that way). I've been writing C
             | for nearly 30 years, and GAP is a slog to read. Sage makes
             | this stuff way easier.
             | 
             | In short... math isn't just arithmetic, isn't even
             | arithmetic of complex tensors. Math is way bigger than most
             | programmers seem to comprehend. I'm on the other side of
             | the DK curve; I know that I've only scratched the surface
             | despite a decade of dedicated study
        
             | red_trumpet wrote:
             | Natural numbers don't form a ring, and integers don't form
             | a field.
        
               | 6gvONxR4sf7o wrote:
               | Good callout. What would you use if you had to restrict
               | operator overloading to an appropriate "number"
               | abstraction?
        
           | phoe-krk wrote:
           | As for definition, it already exists: https://docs.oracle.com
           | /javase/8/docs/api/java/lang/Number.h...
           | 
           | As for abuse prevention: it would be impossible to use the
           | common operators like +, -, +=, <<, >> and so on for anything
           | that is not numbers, and therefore prevent C++ levels of
           | overloading abuse.
        
             | zokier wrote:
             | But any class can inherit that Number, there is nothing
             | enforcing that the subclass is particularly number-like.
             | You can do just stuff like                   class MyString
             | extends Number
             | 
             | and you get access to operator overloads. Only thing that
             | makes this annoying is Javas lack of multiple inheritance,
             | but that is pretty minor thing.
        
               | hinkley wrote:
               | There is a level of stupid that is deniable, and a level
               | that is not. MyString extends Number is going to lead
               | more swiftly to words with your coworkers.
        
         | mrmr1993 wrote:
         | Where possible, I prefer making the syntax opt-in, and
         | explicitly so. For example, stealing OCaml's syntax:
         | 
         | let check_exp (g : Elliptic_curve_pt.t) (x : int) (y : int) =
         | let xy = x * y in let open Elliptic_curve_pt.Num_syntax in (g ^
         | x) ^ y = g ^ xy
         | 
         | This lets you avoid making hard decisions about what can be
         | added/multiplied/etc. at the language level -- can a list of
         | numbers representing the coefficients of a polynomial be added?
         | -- without jumping to the extreme of allowing anything
         | implicitly. This also lets the typechecker catch more of your
         | mistakes by having stricter types, and means you know exactly
         | where to go to find out what the syntax is encoding.
        
         | WalterBright wrote:
         | > You probably shouldn't be using += for your concatenation
         | code
         | 
         | I agree. That's why D uses a separate operator for
         | concatenation, ~=
         | 
         | That removes the temptation to overload +=.
        
       | zabzonk wrote:
       | I disagree with all of the preconditions this article suggests
       | (and don't see why they are needed in the article)but I do agree
       | that it is better to be able to say:                  a = b + c
       | 
       | rather than                  a.assign( b.add(c))
        
         | gumby wrote:
         | As a Lisp programmer I never felt the need for syntactic
         | operators. The case you cite doesn't look any worse to me.
         | 
         | Metasynactic operators (like quotes) are a different matter but
         | you need so few it's no big difference.
         | 
         | I do write `c = a + b` in c++ but simply as it's the local
         | convention. `=` is a non-intuitive assignment operator and no
         | more natural than `assign`.
        
           | zabzonk wrote:
           | So you don't do:                  (+ 1 2)
           | 
           | Also, I don't think that                   a.assign(
           | something )
           | 
           | is particularly natural or understandable. Am I assigning
           | something to a, or assigning a to something?
        
             | gumby wrote:
             | I usually use a dialect that allows me to use `plus` but
             | the symbols `plus` and `+` are just names to me -- just
             | stuff you learn. As I mentioned the use of `=` for
             | assignment is counterintuitive, but if you simply learn it
             | as yet another name it's no big deal.
             | 
             | > Am I assigning something to a, or assigning a to
             | something?
             | 
             | Seems to me that it would be causing a side effect on a,
             | but as I said these are just arbitrary labels that you have
             | to learn.
             | 
             | I find operator precedence weird and in 40+ years of
             | continuous programming _and_ doing math I have never been
             | able to develop an intuition about them. But it 's a thing
             | you learn.
        
       | nikeee wrote:
       | When looking at C#, which has operator overloading, did things
       | really go that bad? What makes Java people think it would be
       | worse than that?
        
         | legulere wrote:
         | Implicit casts can be a bit dangerous in C#, but the bigger
         | problem is that you cannot generically use operators like you
         | can with type classes in Haskell.
        
         | wvenable wrote:
         | C++ overdid operator overloading in their libraries, etc. This
         | is what Java developers saw at the time and decided not to
         | include it.
         | 
         | But I agree that C# proves that we all learned our lesson and
         | operator overloading is now just mostly used for numbers.
        
       | compumike wrote:
       | The article suggests a use case for operator overloading in a
       | Complex or BigInteger class.
       | 
       | My programming experience is that that these "mathy" objects are
       | about the _only_ unambiguous use case for operator overloading.
       | Given the limited use case, I 'm not sure whether it's worth the
       | added complexity for language designers.
       | 
       | I wrote the simulator engine code for CircuitLab
       | (https://www.circuitlab.com/). We have complex numbers, sparse
       | matrices, and extended-precision (more than a 64-bit double)
       | floating point classes, all of which we use extensively within
       | the simulation engine. Yes, it can be a bit annoying and verbose
       | to do X.add(Y) instead of X+Y, but I tend to just leave an end-
       | of-line comment to aid readability later. And this mathematical
       | core code tends to be infrequently changed and well covered by
       | tests.
        
         | edflsafoiewq wrote:
         | Well of course, if you look at "mathy" operators like +. If you
         | look at operator[], the use cases are all "collectiony" objects
         | instead.
        
           | AnimalMuppet wrote:
           | I could even see + on collections: "Add all the elements of
           | this collection to that collection."
        
         | dkersten wrote:
         | While in most of my code, I don't really care about operator
         | overloading (ie not having it would not make my life any
         | worse), but when I write shader code (or a C++ library like
         | GLM) to do mathy stuff, but including vectors and matrices, I
         | am _very_ glad to have overloaded operators and dread the idea
         | of having to work around the language to express what I want. I
         | 'm not thrilled about having to duplicate the code (once using
         | X.add(Y) and a comment to show a clearer version) here, but its
         | better than nothing.
         | 
         | Of course, if we just use s-expressions, then there's no
         | difference between operators and functions and this whole thing
         | becomes moot. Although, with the caveat that your nice infix
         | math expressions are still not nice infix math expressions.
         | Then again, if we are using sexps, then we're likely using a
         | language with macros and writing an infix macro for those mathy
         | parts wouldn't be such a bad idea... ;-)
        
           | tsimionescu wrote:
           | Isn't operator overloading usually a bad idea for high-
           | performance maths? It limits you to binary operations (unless
           | you go down an even deeper rabbit hole of template meta-
           | programming), when many oprimized algorithms are ternary or
           | even higher arity (e.g. optimized matrix multiply-and-add).
        
         | Animats wrote:
         | _These "mathy" objects are about the only unambiguous use case
         | for operator overloading._
         | 
         | Yes. Most other uses for operator overloading are really chains
         | of functions. There's better syntax for that.
         | 
         | I once wrote some overloads for C++ so that you could write
         | result = fileobject | item | item | item | item;
         | 
         | and then apply either "read" or "write" to "result". This
         | allowed marshalling without writing the item list more than
         | once. Bad idea.
         | 
         | Python is notorious for problems that stem from combining
         | operator overloading and implicit conversions. "+" is
         | arithmetic for some types and concatenation for others.
         | [1,2,3] + [4,5,6]
         | 
         | is
         | 
         | [1,2,3,4,5,6]
         | 
         | which you might not expect. If you add arrays from numpy, those
         | add arithmetically. You can add a numpy array to a built-in
         | array. Trouble comes when you pass a numpy array to a function
         | that expects a built-in array, and the wrong semantics of "+"
         | are applied.
         | 
         | Rust has operator overloading without implicit conversions.
         | That avoids such ambiguities, at the cost of requiring many
         | explicit conversions.
        
           | samatman wrote:
           | Conflating concatenation and addition is just a terrible
           | mistake, this is one illustration among many of that.
           | 
           | In Lua, `+` is always addition, and can be overloaded with an
           | `__add` metamethod, while `..` is concatenation, overloaded
           | with a `__concat` metamethod. `..` is also right associative,
           | which means that `a .. b .. c .. d`, a normal enough string-
           | building pattern, can be optimized into a single allocation
           | for the new string, without having to create `a ..b` and then
           | `ab .. c` and so on.
           | 
           | So I don't see this as a problem of operator overloading, I
           | see it as a problem of a missing operator. Implicit
           | conversion makes that problem worse, but `"12" .. 13` in Lua
           | will give you "1213", as you would expect, and `"2" + 3`
           | gives you 5, again, as you would expect.
        
             | Animats wrote:
             | What to use for concatenation is a problem. PL/1 used "|",
             | which was originally drawn with a break in the middle. But
             | C took that over as "or", and that's now the accepted
             | standard. ".." is accepted as a range operator now.
             | 
             | Moving deeper into Unicode is probably not the answer.
             | Although, if a language needed a concatenate symbol, [?]
             | (Squared Plus) might be a good choice. It's not used for
             | much else.
        
               | nicoburns wrote:
               | Perhaps ++, and just use += 1 for incrementing. Rust
               | already doesn't have an increment operator, and my
               | JavaScript linter forbids it.
        
               | Someone wrote:
               | If it didn't cause problems (ones I can think of in
               | seconds: it complicates parsing, mathematicians will
               | think it signals multiplication, and it makes it hard to
               | insert spaces), using a single space for concatenation
               | would make sense to me.
               | 
               | (Aside: C (or the C preprocessor?) is the only piece of
               | software that I know that supports that , but only for
               | string literals)
        
               | lifthrasiir wrote:
               | As a binary operator `~` seems pretty unambiguous.
        
             | fiddlerwoaroof wrote:
             | Concatenation is just addition, though: addition is the
             | monoid operation on numbers with the identity of 0,
             | concatenation is the monoid operation on lists with
             | identity of [].
             | 
             | The problem is almost always not the overloading of + but
             | the implicit type coercion rules
        
         | samatman wrote:
         | I know of at least one other use of operator overloading which
         | is quite pleasant to use. In Lua's PEG engine, Lpeg, operator
         | overloading is used to express combinators, so `P"a" * P"b"`
         | matches "ab" and `P"a" + P"b"` tries to match "a", then tries
         | to match "b".
         | 
         | It's a little bit of a kludge! But a clever one, which uses the
         | precedence of the existing operators to match the expected
         | precedence of concatenation and the `/` ordered choice operator
         | from PEG grammars.
         | 
         | In general I'm suspicious of arguments that boil down to
         | "people might use this language feature badly". I'm not sure I
         | want the full ability to add my own infix and postcircumfix
         | operators, the way e.g. Raku allows, but there's no denying
         | that being able to write `if foo [?] test_set` is expressive
         | and cool.
         | 
         | Maybe expressive and cool isn't a terminal value for language
         | design, maybe `if test_set.element(foo)` is good enough. I
         | kinda like it though.
        
         | kpgiskpg wrote:
         | (Author here).
         | 
         | Here's a not-so-mathy application that I had recently. I was
         | implementing a units system in Python. Operator overloading
         | allowed me to define joules like so: `J = KG * M**-1 * S**-2`.
         | Then I could define grays (a radiation-related unit) like `Gy =
         | J/KG`. Repeat for hundreds of units. If I had to do it in Java,
         | I'd be frustrated by the verbosity and it would be easier to
         | make mistakes.
         | 
         | My point -- Guy's point, actually -- is that if you don't give
         | people the ability to grow a language, then their expressive
         | power will be limited. And you can't anticipate ahead of time
         | all the ways they'll want to express themselves.
         | 
         | Admittedly, my application is kinda mathy under the hood,
         | because the units exist in a vector space. I guess that's to be
         | expected when the operators come from maths.
        
           | schoen wrote:
           | > Operator overloading allowed me to define joules like so:
           | `J = KG * M*-1 * S*-2`. Then I could define grays (a
           | radiation-related unit) like `Gy = J/KG`. Repeat for hundreds
           | of units.
           | 
           | Presumably exponentiation rather than multiplication by a
           | constant, right?
           | 
           | This is cool and reminds me of how the Python Z3 binding uses
           | operator overloading to let you express arithmetic and
           | logical constraints                 >>> import z3       >>> s
           | = z3.Solver()       >>> a, b, c, d = (z3.Int(x) for x in
           | "abcd")       >>> s.add(a*b == c+d)       >>> s.add(a+b ==
           | c+d)       >>> s.add(a!=0,b!=0,c!=0,d!=0)       >>> s.check()
           | sat       >>> s.model()       [d = 6, c = -2, b = 2, a = 2]
           | >>> s.reset()       >>> s.add(a>1, b>1, c>1)       >>>
           | s.add(a*a + b*b == c*c)       >>> s.check()       sat
           | >>> s.model()       [c = 17, b = 8, a = 15]
           | 
           | (It's limited in some ways for some reasons, like for some
           | types and relations you may have to use a Z3 function to
           | express a relation even though Python has syntax for it --
           | the example that I know of is that you have to use z3.Or(),
           | z3.And(), etc., with boolean variables instead of Python's
           | builtin boolean operators. Not sure why.)*
        
             | kpgiskpg wrote:
             | Oh wait, Hackernews seems to have removed one of the
             | astericks symbols. It should be Python's exponentiation
             | operator (2 astericks symbols), ya. (edit: fixed now).
             | 
             | That's cool too! How do you define the variables?
        
               | schoen wrote:
               | Oh wait, I left that part out! I'll edit my post.
               | 
               | ... there we go.
               | 
               | You use Z3 objects that represent unknowns of particular
               | types, like Z3.Int, Z3.Bool, etc. Each one returns an
               | object representing a variable of that type, which can
               | then be used in (Python-formatted!) expressions that you
               | give to a solver.
        
         | kd5bjo wrote:
         | > My programming experience is that that these "mathy" objects
         | are about the only unambiguous use case for operator
         | overloading.
         | 
         | Rust's ability for smart pointers to overload the dereference
         | operator works pretty well, though there is still some
         | potential for abuse.
         | 
         | Part of what makes it reasonable is the required function
         | signature: It can only ever produce a reference to some other
         | type, which rules out some of the crazier possibilities.
        
         | WalterBright wrote:
         | I agree that operator overloading should be restricted to math
         | objects. D tries to make it unpleasant to do it for non-math
         | objects. For example, < <= > >= are not overloadable
         | separately, just one function `opCmp` does all of them. Non-
         | math operators are not overloadable.
         | 
         | The D community has generally agreed, and we haven't had much
         | trouble with people overloading operators to do a regular
         | expression DSL, for example.
        
         | Someone wrote:
         | I think many somewhat mathy DSLs can benefit from it.
         | 
         | For example, there's boost Spirit, a library to write parsers.
         | You describe a grammar in something that looks a lot like a
         | EBNF grammar (https://www.boost.org/doc/libs/1_67_0/libs/spirit
         | /doc/html/s...)
        
       | tormeh wrote:
       | If you want this, just use Scala.
       | 
       | Full interoperability with Java, all the flexibility you could
       | ever want.
        
       | cletus wrote:
       | I actually like how conservative Java has been with making
       | language changes.
       | 
       | People go nuts with language features because they can, not
       | necessarily because they have a good reason. this it the big
       | problem I have with Scala, for example.
       | 
       | Sure arithmetic operator overloading with numeric types makes
       | sense. Even the parenthesis operator overloading in C++ for
       | functors makes sense.
       | 
       | Then you have the Scala SBT build system and percent operator
       | overloading.
       | 
       | I actually like how Rust does this. You don't overload the
       | operators per se. You implement traits with named methods like
       | Add that will allow you to use the operators. This, to me, is the
       | best of both worlds.
       | 
       | I personally think Java has been just fine without operator
       | overloading so there's no pressing need to add it now but, if
       | they do, please follow the Rust model.
        
         | aardvark179 wrote:
         | I mostly agree, but I think value types are likely to put
         | pressure on this area. I think C++ style overloading would be a
         | mistake, but maybe a monoid interface and some language changes
         | to turn operators in to method calls could work. The thing that
         | Java does well on is that it is easy to read and you wouldn't
         | want to break that property. Understanding the types of
         | expressions can be hard enough without operators doing weird
         | things, but having a system that doesn't allow adding two
         | different numerical types would also feel poor.
        
         | lmm wrote:
         | > Then you have the Scala SBT build system and percent operator
         | overloading.
         | 
         | SBT is a fractal of bad design, the funny function names are
         | just the most superficial of its problems.
         | 
         | > I actually like how Rust does this. You don't overload the
         | operators per se. You implement traits with named methods like
         | Add that will allow you to use the operators. This, to me, is
         | the best of both worlds.
         | 
         | It's still just an extra unnecessary indirection where you have
         | to remember which is which. What Scala does is much simpler -
         | the + method is called +, the / method is called /, and so on.
         | Yes, defining a function called %++< is probably a bad idea,
         | but defining a function called YqqZ is probably a bad idea too,
         | and few programming languages feel a need to ban that.
        
         | winter_squirrel wrote:
         | As someone who has to often work exclusively with bigdecimal /
         | ... type code, not having operator overloading a thing makes
         | code so much more verbose and hard to follow when doing
         | mathematical expressions using them
        
       | zokier wrote:
       | Is there anything in the articles arguments for operator
       | overloading that would not also apply equally for allowing
       | arbitrary user-defined operators (i.e. infix functions) instead
       | of the small limited set that is built-in to the language?
       | 
       | Personally I'm starting to lean more towards the opinion that
       | infix operators/functions are not worth their complexity even for
       | primitives.
        
       | abeppu wrote:
       | I think we get into fuzzy territory when we use one term to refer
       | to a complex feature, without having good terms for constituent
       | parts of that feature. If java offered the ability to call
       | methods in infix position, and give methods non-alphanumeric
       | names, and maybe express something about precedence order, that
       | would support a good share of uses for operator overloading
       | without actually overloading anything. `x :+: y` would be easy
       | enough to read as "an addition-like operation which is not the
       | inbuilt addition" and would still closely resemble the math, and
       | might be fine in a context where x and y are complex numbers or
       | whatever. It would come at the obvious cost of requiring changes
       | to a bunch of the supportive tooling surrounding the language.
       | 
       | I think the messy part added by overloading specifically is that
       | if `Complex`, `RealVector`, `List` etc all override addition,
       | then there's some common class or interface which provides the
       | declaration which they all override, and same for subtraction,
       | multiplication, etc, and soon you have a large pile of
       | interacting abstract definitions, which some language users will
       | find daunting.
        
         | capitalsigma wrote:
         | Sounds like re-inventing Haskell.
        
           | abeppu wrote:
           | Or maybe this is just scala. I guess the issue is, is it
           | possible to add "operator overloading" and get something
           | sensible without adding a whole pile of other definitions?
        
         | zokier wrote:
         | That sounds still like overloading unless you'd require the
         | infix function names to be globally unique. And if you require
         | global uniqueness then that gets pretty nasty pretty quickly
         | with libraries that might use same names.
        
       | catlifeonmars wrote:
       | I wonder if it makes sense to add operator overloading to a
       | language, but in a way that requires that closure under each
       | overloaded operator and the existence of identities/annihilators.
       | The operating principle here is to ensure that principle of least
       | surprise for library consumers (sometimes at the cost of making
       | life harder for library authors).
        
         | jmull wrote:
         | That's not a bad idea, but I think the problem is essentially
         | solved.
         | 
         | C++ introduced operator overloading to the wide world, and it
         | was promptly abused (with the stream operators, among other
         | things).
         | 
         | But I believe the lesson was learned.
         | 
         | Few libraries hoping to achieve general usage will abuse
         | operator overloading too badly, and if they do, potential users
         | will resist adopting it widely.
         | 
         | There's an interesting class of language features, of which
         | operator overloading is one, that are tempting to abuse which
         | should really mostly only be used for what are essentially
         | language extensions provided by a library.
         | 
         | I think what is more useful than even more language features to
         | restrict the usage of these, is strong documentation and
         | evangelism/marketing around the feature to help ensure it will
         | be used appropriately.
        
       | ajkjk wrote:
       | I'm surprised that every comment so far is about operator
       | overloading. All I thought after reading this is: saying what
       | words mean up front sure is tedious and unnecessary.
        
         | throwaway894345 wrote:
         | Especially to get to the conclusion which is basically "I hope
         | Java gets operator overloading" without much actual support for
         | that position. The one interesting bit of support they gave was
         | that it's hard to identify the quadratic formula on BugIntegers
         | without operator overloading and that this unfamiliarity might
         | yield bugs, but I think the inverse is true. Math notation
         | tends to be (IMO, obviously) horrible--it's optimized for
         | quickly scrawling on a blackboard and for elitist gatekeeping,
         | not for understanding or maintenance. At least it violates many
         | of the software industry's rules about what constitutes
         | readability, approachability, and maintainability.
        
       ___________________________________________________________________
       (page generated 2021-04-03 23:01 UTC)