Live data from Hacker News

Why Operators Are Useful

neopythonic.blogspot.com

51–60 of 173 posts

Re: Why Operators Are Useful

#51
post #32

Earlier quoted context omitted.

If this is so obviously preferable, why have mathematicians so obdurately not adopted this style? Mathematical notation is not an archaic practice that is followed out of a respect for tradition, or a doctrine that has been developed from first principles, it is something that has evolved (and continues to do so) because it has been useful.

Mathematics uses infix notation literally everywhere. Just because you prefer some notation doesn't mean people who have used infix notation since they were 5 years old will like it. Also, I avoid lisp mostly because S-expressions are almost unreadable to me.

> Mathematics uses infix notation literally everywhere.

Mathematics uses prefix, infix, suffix, circumfix, and some more complex notations; basically any pattern any computer language uses probably is inspired from math even if math doesn't use the notation for the same operation or operator symbol.

Re: Why Operators Are Useful

#52
post #34

Earlier quoted context omitted.

The sensible thing is to throw on conflicting keys.

What? Have you never had two dicts and wanted vals from one dict override the other?

That’s semantically not an “add”, it’s a “merge” or “update”

Re: Why Operators Are Useful

#53

The dict example given is exactly why operators wouldn't be useful to me. Presumably d1 + d2 != d2 + d1 for some d1, d2. If you're going to use the + operator then it should behave like it does in other contexts.

this is equally untrue true for strings, of course.

  “foo”+”bar” != “bar” + “foo”
there are valid non-commutative additions.

Re: Why Operators Are Useful

#54
But, this argument defeats itself. At least, in practice.

If I look at how 'operator overloading' is used in practice, _rarely_ do you get commutativity, or even anticommutativity, associativity, or distributivity.

Take list addition, where operator overloading often shows up:

    someList += someElement
is shorthand for:

    someList.add(someElement)
add is not commutative; the elements used in the operation aren't even the same type.

The point being, the manipulation and simplification that is, according to GvR, much easier to spot if operators are used aren't even relevant here.

If we're talking about, say, introducing a class 'Complex', representing complex numbers, and wishing that the language is such that one can add the ability to use mathematical operators here, observing that it is both [A] common in the domain of complex numbers to use, say, the symbol `+` to indicate addition, and [B] these properties of operations such as commutativity apply to many mathematical operations one might want to perform on complex numbers, I'd agree: Yeah, the language kinda sucks if you can't write `Complex(a, b) + Complex(c, d)`.

But how often does that actually occur?

Separately, if you go down this route, the abstraction should be as complete as it can be. Therefore, this:

    `Complex(2, 3) + 5`
Should work, and should evaluate to `Complex(7, 3)`. But.. this:

    `5 + Complex(2, 3)`
should also work. Which requires either scala's `implicit` system or python's take on this, involving `__rplus__`. These operations introduce their own complications.

Thus, the debate on operator overloading boils down, as language feature debates usually do, as a cost v. benefits analysis. The costs are heavy: There is a lot of proof out there that even experienced coders just insist on abusing operator overloading (or, to be a bit less judgemental: That opinions are rather divided on how they ought to be used, given the amount of complaints about `cout Are the benefits worth it? Possibly.

But I don't think GvR's article takes the cost side seriously, and the benefits stated, at least in my experience, tend not to apply at all there where op overloading tends to end up.

Re: Why Operators Are Useful

#55

But, this argument defeats itself. At least, in practice. If I look at how 'operator overloading' is used in practice, _rarely_ do you get commutativity, or even anticommutativity, associativity, or distributivity. Take list addition, where operator overloading often shows up: someList += someElement is shorthand for: someList.add(someElement) add is not commutative; the elements used in the operation aren't even the…

`someList += someElement` raises an exception. It's `someList += someSequence` which just does the same as `list.extend`, that is, `someList = someList + list(someSequence)`

Re: Why Operators Are Useful

#56
post #34

Earlier quoted context omitted.

The sensible thing is to throw on conflicting keys.

The even more sensible thing is to take an optional argument: a function that is passed the conflicting keys and their values, and must resolve the conflict. If `None` is passed, then a documented default is taken.

It’s an operator, there are no optional arguments. Though it’s OK to also have a function like you propose.

Re: Why Operators Are Useful

#57

But, this argument defeats itself. At least, in practice. If I look at how 'operator overloading' is used in practice, _rarely_ do you get commutativity, or even anticommutativity, associativity, or distributivity. Take list addition, where operator overloading often shows up: someList += someElement is shorthand for: someList.add(someElement) add is not commutative; the elements used in the operation aren't even the…

I mostly get stuck using Javascript because I want to target people’s web browsers. I write a pretty good amount of numerical code. The lack of operator overloading for number-like objects is extremely annoying for me.

There are always hacky workarounds, e.g. https://github.com/enkimute/ganja.js#the-inline-function but in this particular case the code to make it work ends up a bit confusing, and the hack is somewhat brittle and inflexible.

Re: Why Operators Are Useful

#58
post #2

This is much less confusing than (2), and leads to the observation that the parentheses are redundant, so now we can write "x + y + z" This is a non-problem if you're using Lisp. (+ x y z) accepts an arbitary number of arguments and the operator precedence problem does not exist since there is no operator precedence.

If this is so obviously preferable, why have mathematicians so obdurately not adopted this style? Mathematical notation is not an archaic practice that is followed out of a respect for tradition, or a doctrine that has been developed from first principles, it is something that has evolved (and continues to do so) because it has been useful.

We do have f(x, y) in mathematics notation, as well as notations like { a, b, c }, ( 1, 2 ). The inventor of vector and matrix notation finally had the brilliant idea of dropping the silly commas [ i j k ]. Think of how ugly matrices would look with commas.

Now in mathematics, there is no equivalent of a 200,000 line piece of software. The number of identifiers a mathematician works with in any given work is small, even if the work is large (many pages of derivation).

Mathematics notation is ambiguous and inconsistent. One letter names are preferred so that xy can denote the product of x * y. So much so that mathematicians reach for other scripts like Greek rather than make a multi-letter name. Then, inconsistently, we have things like sin(x).

Consider that xy(z + w) is likely interpreted as the product of x, y and z + w. It has the same syntax as ln(z + w), the natural logarithm of z + w, not the product of l and n.

Professionally printed mathematics resorts to the use of special fonts to visually resolve these things. This problem is so serious that everyone who is anyone in mathematics goes to the trouble of professional typesetting, even in minor papers.

In software, the program-defined functions form vast vocabularies. They cannot all be assigned to infix operators without creating mayhem. Many functions have 3 arguments. Seven argument functions are not uncommon. Those also cannot be infix.

In spite of what the author may say, real Python code is chock full of "import foo" and "foo.bar.baz(this.or.that(), other.thing())".

Re: Why Operators Are Useful

#59

But, this argument defeats itself. At least, in practice. If I look at how 'operator overloading' is used in practice, _rarely_ do you get commutativity, or even anticommutativity, associativity, or distributivity. Take list addition, where operator overloading often shows up: someList += someElement is shorthand for: someList.add(someElement) add is not commutative; the elements used in the operation aren't even the…

In my opinion, requiring commutativity from a +-operator is maybe too much. Associativity and a neutral element seem to be enough (i.e. forming a monoid).

Re: Why Operators Are Useful

#60
post #2

This is much less confusing than (2), and leads to the observation that the parentheses are redundant, so now we can write "x + y + z" This is a non-problem if you're using Lisp. (+ x y z) accepts an arbitary number of arguments and the operator precedence problem does not exist since there is no operator precedence.

Lisp is pretty ugly :) (eql (* x (+ y z)) (+ (* x y) (* x z))) I wonder if its famed sense of enlightenment is partly just overcoming the mental hurdle of it's syntax. Edit: typo fix, had x/z mixed up

tbh, if you're writing a lot of equations like this in a program, the Lisp version should probably be something like

    (eqn x * (y + z) = x * z + y * z)
where you write and test an `eqn` macro that rewrites everything in the correct syntax.
Post reply on HN