[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)