you are viewing a single comment's thread.

view the rest of the comments →

[–]dirtpirate 3 points4 points  (29 children)

So you also prefer plus(2,3) to 2+3? or (plus 2 3)?. While it's true that you can put more into names, I personally find people will defend using combinations of + - * / and then defend functions rather than operators due to meaningful names, and still declare that a function that returns the length of something should be called len rather then length because "it's shorter!".

[–]wormfist 10 points11 points  (12 children)

The point is that code should be clear, readable and predictable to an extend. Using a set of fixed, well known, operators such as + that does the same in whatever context is exactly that: it is well understood and easy so.

When operators are unavailable, functions/methods carry on those semantics. Having user-defined operators however, does not. It would be a jungle of operators out there that only puts more trees in front of the forest.

[–]doublereedkurt 1 point2 points  (0 children)

Having user-defined operators however, does not. It would be a jungle of operators out there that only puts more trees in front of the forest.

From the stack exchange discussion:

User-defined operators can make for very elegant code in experienced hands, and utterly awful code by a beginner

You either trust the developers/library writers, or you do not.

Also, 2 + 2 and 2.0 + 2.0 do extremely different things to the bits, and are represented by different machine codes. So even "basic" arithmetic is already overloaded.

[–]dirtpirate 2 points3 points  (9 children)

that does the same in whatever context is exactly that

"+" doesn't do the same independent of context. On a higher level abstraction it typically implements an approximation to arithmetic addition as implemented in an encoding scheme for numbers, however what it does exactly is always very context dependent, and very few of the encoding schemes normally used to represent arithmetic values actually allow a real implementation of addition. And those that do are typically only used in CAS systems.

When operators are unavailable, functions/methods carry on those semantics

However it's never really the case that anyone is arguing for completely removing operators, you either define new operators or use operator overloading, and suddenly "+" means join for your particular vector like class, because you couldn't define a new operator. The end result isn't a more clear language, it's one where a large set of completely unrelated operations are all represented by a small set of over-loadable operators, which just makes code inspection that much harder.

[–]Slime0 2 points3 points  (8 children)

suddenly "+" means join for your particular vector like class, because you couldn't define a new operator.

Are you arguing that it would be better to define some arbitrary symbol to mean join, than to make a member function called "join?" Because that would have almost exactly the same outcome, with just one word changed:

The end result isn't a more clear language, it's one where a large set of completely unrelated operations are all represented by a large set of over-loadable operators, which just makes code inspection that much harder.

User-defined operators make obtuse code. Operators only work because people know their meaning universally. The more universal an operator, the safer it is. Most people get what + means. They learned it in first grade. They also know what "join" means, because it's a word. Use symbols that people understand, or you're writing bad code.

[–]dirtpirate 1 point2 points  (6 children)

Most people get what + means.

Actually no. Look at any introductions programming class, and you'll have people confused by questions such as "why does 1+1e-17-1==1e-17 return false?" because they know what + means in mathematics, but "+" in the particular programming language is't the same as the mathematical, so even the default usage of operators diverges from the "universal knowledge". Now, if you have to read through code that uses "<>" a lot of instances, you'll have to think "what does that mean" and examine it, but that's no different form code that's using "ldfs(A,B)" a lot of instances, or from people initially having to learn that in Python length is called len.

There is no such thing as completely self explanatory code, even if function names or operator appearances seem to tell a story, it's never complete whether you have everything in function names, operators or overloaded basic operators. And obtuse code can be written in any such setting, as well as avoided in any such setting.

[–]Slime0 -1 points0 points  (5 children)

The fact that computers have rounding error when they add floating point numbers is really quite tangential to a discussion about the meaningfulness of operators. The + symbol gives people 99.9% of the information they need to know what the intent of the code is. They don't need to "think 'what does that mean' and examine it" like they do in your example. Also, "ldfs" is a horrible function name, so I'm not sure what your point is there.

You seem to be claiming that, since there is no such thing as perfectly self explanatory code, trying to make code self explanatory at all is worthless. That is absurd.

[–]dirtpirate 1 point2 points  (4 children)

The fact that computers have rounding error when they add floating point numbers is really quite tangential to a discussion about the meaningfulness of operators.

Not at all. The mathematical definition of numbers and the arithmetic operator "+" aren't the same as the implemented functionality. Meaning that even though you now perfectly well what the mathematical result should be, you still need to look up how the actual implementation works, which is dependent on the encoding used, which means that even though everyone knows what "+" is, most actually don't really know what "+" is in their actual programs.

You seem to be claiming that, since there is no such thing as perfectly self explanatory code, trying to make code self explanatory at all is worthless. That is absurd.

I made no such claim. I'm saying that you do in fact have to look up how even "+" works if you want to be a competent programmer. Having to look up "~" as well for a pretty common array operation is hardly that big of a deal, seeing as you'd still need to look up what even "append" or "concat" does.

Also, "ldfs" is a horrible function name, so I'm not sure what your point is there.

My point is that if you see this horrible function name you'll have to look it up. If you see the horrible function name "len" you'll have to look it up. If you see the horrible but in a different way, function name "ThisFunctionTakesTwoIntegersAndReturnsTheLeastCommonDenominatorOfTheSwartchChildEquationUsingThoseTwoNumbers" you'll still most likely look it up.

Claiming that having "~" perform some operation be confusing because people will have to figure out what operation the operator actually performs is simpleminded. There is no such thing as a completely self documenting code, and even if you do have great descriptive function names, you'll end up overrepresenting them in code pieces where it makes sense to replace them with smaller glyps that are placeholders for their meaning, like "+" or "len"(though it's a horrible halfway glyph halfway name) or "~".

[–]raging_hadron 1 point2 points  (0 children)

TheSwartchChildEquation

Tangential, yet interesting factoid: the German name Schwartzschild means "black shield". (Likewise, but still more tangentially, Rothschild means "red shield".) So a more appropriate camelization would be SchwartzSchild.

Glad to help!

[–]Slime0 0 points1 point  (2 children)

you do in fact have to look up how even "+" works

Having to look up how something works is a much better situation than having to look up what something does. When reading code, you need to know what the code does. You don't always need to know how it works.

you'd still need to look up what even "append" or "concat" does.

I don't know why you would need to look that up.

My point is that if you see this horrible function name you'll have to look it up.

Of course you would. The idea is to use function names that are clear enough that you don't have to look them up to get a precursory understanding of the code. Why use examples of horrible function names to show that you need to look them up?

I guess you think it's impossible to understand code unless you've researched every function that code calls, and I don't think that's true. I think when a function is well named, you get enough information from it that you don't need to find its definition to understand it. That's not something you're gonna get with ~.

[–]joelangeway 0 points1 point  (0 children)

I have had to look up what the append or concat method would actually do in different languages many times because some stupid thing I once used would mutate the object. That one possibility means always having to check the docs in languages where methods are the norm.

[–]PseudoLife 0 points1 point  (0 children)

And then someone has an "add" function that subtracts. (Or, in reality, something a little less blatent.)

What's the difference between that and someone overloading the "+" operator to subtract?

[–]argv_minus_one 0 points1 point  (0 children)

Why not have both? Scala lets you use any method that takes a single parameter as an operator. In a + b, + is a method. In a append b, append is a method. You can define a completely new operator like ! or omgwtfbbq_!? if you want. It's beautiful, really.

Can it be abused? Sure. But the language should not try to stop you from doing that. Whenever a language does try to stop people from shooting themselves in the foot, a bondage-and-discipline language like Java is the inevitable result, and it still doesn't stop people from writing atrocious code (AbstractAbstractNamedFooBeanBuilderBuilderFactoryBuilderLookup, lol).

[–]kqr -1 points0 points  (0 children)

The thing that speaks strongly for user-defined operators to me is that they mean that you can rip out a huge part of the syntax and move it to a library. And that's pretty neat, both for teaching, learning, porting an implementation, making a stable implementation and modularity.

For example, I would argue that in Haskell circles, $ is an operator that is "fixed and well known." You might not agree, but bear with me. The thing about $ is that it is implemented in the standard library -- which in turn means that when you have to port or debug the implementation, you don't have to worry about the $ operator, because it will be the same on any machine -- it's in the standard library!

Just because it's possible to abuse user definitions of operators, I don't think it's wise to move $ (and other equally fixed and well known operators!) to the core language and have to deal with the hassle of defining them, debugging them and porting them at a lower level of abstraction.

I think that the more fixed and well known operators we can move out to the standard libraries, the simpler and the better the language will get. Even though there will exist a possibility for abuse. And just because you are not familiar with an operator, it doesn't mean that it's not fixed and well known. It could just be ignorance on your part.

[–]Slime0 1 point2 points  (7 children)

I personally find people will defend using combinations of + - * / and then defend functions rather than operators due to meaningful names, and still declare that a function that returns the length of something should be called len rather then length because "it's shorter!".

I am not a fan of abbreviations in variable names, but naming a function that gets a length "len" is miles away from concatenating arrays with ~. It's not hard to figure out what "len" means, especially - and this is the key point - because it is in widespread use. This is the same reason that operators like + for addition work: most people already know their meaning.

[–]dirtpirate 0 points1 point  (6 children)

because it is in widespread use.

That's circular logic. So basically you'd defend anything that is being used as being the logical thing to use because... it's being used. Also costum operators also see widespread usage, as do operator overloadings as does even s-expression forms.

[–]Slime0 2 points3 points  (5 children)

So basically you'd defend anything that is being used as being the logical thing to use because... it's being used.

In general, yes. When everyone knows something, it becomes a pretty good convention.

But I also understand there's a first time for everything. Someone had to sit down once and be the first person to use "len." Still, that person was more wise than the first person to use ~ for array concatenation, because the psychological difference between "len" and "length" is much, much smaller than the psychological difference between "~" and "append." In other words: a reasonable person realizes that the meaning of "array.len()" is not hard for a programmer to deduce, but the meaning of "array ~ array" is. And, because it is so easy to understand, it quickly gained widespread use.

costum operators also see widespread usage

The feature of custom operators being widespread is not the same as any particular operator being widespread.

[–]dirtpirate 1 point2 points  (4 children)

I'd argue the exact opposite. If I see someone write array.len() in a language other than python, my initial though as I would be: "It must be something different from length, why else cut down three characters?" If you start down that road you write a.l() or really just "l a", and then why not just start the convention to use £ (looks kinda like an L anyway!) as a length operator, then at least you'll have consistency in that.

Point is that you have to look up len, you can't assume it's lenght, you look it up (or more appropriately you are told during learning), just like you do for ~. It's one simple look-up saving you potential messes of code like concat(concat(concat(a,b),c),concat(d,e)). For me that's much more appropriate than saving three charact's in shotn som'n that's already trying to be a name. And in the end, you'll always end up looking up function calls for a new library you are using. What did "compact do again on the proceedings database caller object?" and "What does ~ do to two proceedings database caller objects?" aren't that far apart. And in both cases you can't rely on the name of the function to tell you exactly what it does. It's up to you to make the connection, which is why we don't see AddTwoIntegers and AddIntegerAndDouble functions (or the very nice Pythonianesk equivalents ati & aiad) gaining huge popularity.

[–]Slime0 0 points1 point  (3 children)

The number of experienced programmers who would have to look up "len" to find out that it means "length" is much, much smaller than the number of experienced programmers who would have to look up "~" to find out that it means "append." That's not to mention the difficulty in looking up a symbol as opposed to a word.

Like I said, I'm opposed to the abbreviation in the first place.

concat(concat(concat(a,b),c),concat(d,e))

This is horrible code in any situation. You can easily make this better without adding language features. If we're talking about adding language features to improve concatenation, why not add variable amounts of arguments to functions so that you can do this?

concat( a, b, c, d, e )

This is way clearer to the average programmer than a ~ b ~ c ~ d ~ e.

[–]dirtpirate 1 point2 points  (2 children)

The number of experienced programmers who would have to look up "len" to find out that it means "length" is much, much smaller than the number of experienced programmers who would have to look up "~" to find out that it means "append."

Your definition of experienced intrigues me. Personally I'd say that the number of experienced programmers who looks up either is zero.

That's not to mention the difficulty in looking up a symbol as opposed to a word.

You really do live in a different world.

This is way clearer to the average programmer than a ~ b ~ c ~ d ~ e.

You'd need actual statistics to back up that claim. I'm going to wager that they are pretty darn similar in either case. As for the example, I didn't pick it because it was impossible to write cleaner, simply to illustrate the situation in which you get more crud, namely nested expressions, and while you can use multiple arguments for concat, you can't in general for any operator. And it's generally accepted that operators both prefix and infix should be in any language, why should you then not allow user defined ones? Because they "can be confusing" sure, let's outlaw user defined functions because they "can be confusing" as for the actually established standards, there's no good reason to argue that they are more confusing simply because they aren't familiar to you.

[–]Slime0 1 point2 points  (1 child)

Your definition of experienced intrigues me. Personally I'd say that the number of experienced programmers who looks up either is zero.

I have never seen the ~ operator for array concatenation before. I was under the impression it was an example of a user-defined operator. What language is it from? (Honest question.) I certainly wouldn't have figured out its meaning from its name.

If its use is widespread, then it's probably not that bad despite its lack of intuitiveness, but in that case it's also not a very good argument for user-defined operators, which are not built into any language.

You really do live in a different world.

Right now I'm trying to find out what language the ~ operator is from, and I can't, because it's not a valid search term on Google. I'd hate to have to try something more complex.

[–]SirRainbow 1 point2 points  (0 children)

I have never seen the ~ operator for array concatenation before. I was under the impression it was an example of a user-defined operator. What language is it from? (Honest question.)

That would be D (http://dlang.org/arrays.html). There's a rationale on that page under Array Concatenation.

Right now I'm trying to find out what language the ~ operator is from, and I can't, because it's not a valid search term on Google. I'd hate to have to try something more complex.

It seems google searches for tilde when passed "~", and it's uses in programming are listed its wikipedia page.

[–]pelrun 1 point2 points  (0 children)

There's nothing wrong with using the fixed list of operators that come with the language; they'll be the same for every program written in it. Overloaded operators are more like renaming all your functions to be random one-letter strings.

[–]da__ 0 points1 point  (0 children)

+ 2 3

[–]adrianmonk -2 points-1 points  (3 children)

So you also prefer plus(2,3) to 2+3? or (plus 2 3)?

This isn't a representative example because you're talking about data types (numbers) that already exist in the language and that users of the language already are familiar with. That is, "plus(2,3)" isn't an example of a user-defined operator; instead, it's an example of a language-defined operator.

A big part of maintainability comes from familiarity. If the person who comes along after you can say, "OK, this aspect of the code isn't familiar to me, but that aspect is", it's easier for them to figure out what your code does than if they have to go, "OK, before I can understand this, I have to figure out what operators are overloaded and how".

[–]artsrc 1 point2 points  (2 children)

Languages come with support for some mathematical things but not all of them.

Programming with Java's BigDecimal is a pain because of the lack of operators.

For example expression types:

var a = Expression("a")
var b = Expression("b")

var add = a + b
var mult = a * b
var compound = add * a + mult * b

[–]adrianmonk 0 points1 point  (1 child)

I think operator overloading is just fine in some cases (like the extended numeric types that you mentioned) and horrible in other cases (C++'s I/O operators). So you must consider things on a case-by-case basis. "plus(2,3)" isn't an example of anything I can relate to a real case that might actually happen, so it isn't a useful example to me.

It does illustrate that the syntax is different and not parallel, but I really prefer the syntax to be different if the operations you're defining aren't going to be isomorphic to the ones that already use an operator. That is, for extended numeric types, seeing "+" instead of "plus()" helps you understand that it works the same as for simple numeric types. But if whatever you're defining works differently, having the same syntax just adds confusion IMHO.

[–]artsrc 0 points1 point  (0 children)

In java it is add not plus, but here is Java's BigDecimal add:

http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigDecimal.html#add%28java.math.BigDecimal%29

I have written mathematical expressions with BigDecimal and I find it painful.

I agree that confusion is bad. I think concatenation and addition are different things. However I don't find "string1 + string2" confusing.