Interesting Swift Features
mikeash.com
mikeash.com
Operator overloading, as mentioned, is something that seems fantastic when you're banging out a bunch of code. When you return to that code a month later, however, with no context, it leads to mystery code with completely undefined behavior without tracing back through every constituent. We constantly see people make the (unsupported) claim that scientific coding simply needs operator overloading, and while I can't speak specifically to that industry, in the financial industry operator overloading is how you end up with terrible, mystery-meat code.
I'm starting to wonder, however, whether the horror stories are continuing to propagate long after anyone has seen a real, living monster.
If I'm browsing someone else's code today in a modern development environment and I encounter a function I don't know it's generally pretty easy to navigate to the definition (if it's in the codebase) or documentation (if it's not).
If operator overloading is just a function with a name that happens to be a string of symbols and with infix application at the call site, can't I find out about it just as easily?
What's the difference between
myMysteryFunction(a,b)
and a + b
…if I know that the type of a and b isn't something ordinary like an int or a float?The former is at least potentially self-documenting. And even if it's a badly named function, at least you know it's a special function, and you know you'll have to go look up its behavior.
[Edit: Clarity]
I want the ability to do 'a == b' regardless of whether it's a built-in or user-defined type. That's abstraction.
Flash forward one year, you're long gone, and new developers on your team are left wondering which aspect of a Tire is used in comparisons with ">". Everything works, but it's easy to see how the ambiguity could lead to subtle submarine bugs; incorrect developer assumptions about the behavior of ">" may produce mostly -- coincidentally -- working code.
http://stackoverflow.com/questions/1783912/java-how-to-use-b...
There's a decent case for not having operators at all. Lisp being a fine example of this. Everything is a function, end of story.
But once you have operators, what's the rationale for restricting them to built-in types? This, to me, fundamentally makes no more sense than, say, banning user-created types altogether.
Clearly nothing needs operator overloading, but if you have operators at all, why should "a + b" be valid if and only if a and b are certain language primitives? If you think + should only be used for numeric addition, I'd totally agree, but numeric types don't have to be restricted to built-in ones.
I hate operator overloading myself, but at the same time I'm also certain there are use cases where it is a big win. (I assume it is in Swift because it could be motivated well.)
You'll have to specify coding standards anyway -- and make certain that they are followed. Just add a paragraph about having to get a senior developer's signature on any use of operator overloading, on pain of needing to update the CV.
The simple example I always come back to is how hard it is to find the bug in the following code:
divide(add(multiply(-1,b),multiply(-1,sqrt(add(multiply(b,b),multiply(multiply(-3,a),c))))),multiply(2,a))
versus finding the same bug operator overloaded version (-b-sqrt(b^2-3*a*c))/(2*a)I know that overloading << or || can lead to some confusing code, but offering the basic arithmetic operators would end 90% of the whining by the people who do scientific code and need this functionality.
After all, Java allows statements like "string3 = string1 + string2;", which is much more ambiguous than C's "strcpy( string3, string1 ); strcat( string3, string2 );" (or a modern equivalent where those functions are namespaced in a string class).
I work on 3D games. Sometimes I work in languages (c++, c#, shader languages) that allow me to use operator overloading (and thus infix notation) for 3D vectors and matrices. And sometimes I work in languages (actionscript, java, javascript) that don't allow me to use operator overloading and infix notation for vector and matrix math.
The code in the latter set of languages is much, much, much less readable by nearly any reasonable measure.
Math.DivideToFloat(myInt1, myInt1) or Math.DivideToInteger(myInt1, myInt2)
The problem with operator overloading isn't a lack of descriptiveness, but using them for things they don't describe. If you overload / to perform network IO or something, the problem isn't that / is an undescriptive name, the problem is that it means "numeric division". It's no different than if you wrote a function called "divide" that did network IO.
And beyond that, you're just making things up. '<<' for input/output?
We spent thousands of years developing the written word just so we wouldn't have to rely on primitive pictographs to vaguely get our points across.
If you've been paying attention, I hold up << for IO as an excellent example of operator overloading gone wrong. But it's not because << is undescriptive, it's because << means "bit shift".
"<<" does not mean "bit shit." Several languages use it to mean "bit shift," but many do not, and even in those languages the usage is ambiguous. C uses two operators that, visually, could refer to six different operations: arithmetic shift left/right, logical shift left/right, rotate left/right (on x86: shr, shl, sar, sal = shl ror, rol). As a result, the C standard leaves right-shifts of signed negative numbers implementation defined.
Seems like you're just talking about operators, not overloading. If << doesn't have a distinct meaning then it shouldn't be used. If it's OK to use << it should be OK to use it both for built-in types and custom types.
Just because C++ ruined operator overriding with their moronic << doesn't mean that every other language should live without perfectly reasonable operator behavior. I've been dealing with Java instead of C# and not being able to use simple obvious equality checks with the "==" operator is agonizing.
You see the vast majority of cases not needing operator overloading and see it as useless, while I see the small number of cases where it's really, really good and see it as important.
The << operator was just using symbols for the sake of symbols and would have been much more semantically clear with Shift(value, nBits) and would've avoided temptation to overload this meaningless operation.
Ruby lets you do far worse things if you dig deep enough, but nobody ever complains about that.
Objective-C allows much the same monkey-patching craziness as Ruby, but the feature is almost always used to just add additional convenience methods to system classes in a fairly safe and sane manner.
You can do much worse (and I certainly have), but it's pretty rare.
I assume Stroustrup et al took a look at the meaningless "<<" and decided it was available for whatever use they saw fit.
Well, people _used_ to, but we developed cultural tendencies to reduce those kinds of issues. The last time I was bit by a bug like this was years ago.
For features which just allow cryptic code, it's basically the fear that you won't be able to resist it, or that other people won't. People who want to write cryptic code will figure out how to do it no matter what language they use and what features it has. The solution is to either educate them or not work with their code, not try to restrict languages in a vain attempt to make it impossible to write bad code in them.
There has been "use English;" since at least Perl 5.8, which is about a decade old iirc.
Edit: Another popular one is the ScalaTest unit testing framework: http://www.scalatest.org
https://developer.apple.com/library/prerelease/ios/documenta...
According to the documentation you can declare an operator composed by an arbitrary list of this characters "/ = - + * % < > ! & | ^ . ~". You can recreate C++ stream operators (<<, >>), Ruby combined comparison (<=>), and so on.
For example one can define operators called <>, =<, =>, and !=
You can do interesting stuff with pre- and suffix operators, too. For example, the XML comments <!-- and --> could be a prefix- and suffix operator pair.
Also, you could define operators that look conspicuously like comments, at least to some of your readers.
[disclaimer: I don't have access to the code; I just read the documentation. That documentation seems to imply that // starts a comment _and_ can be used to implement a custom operator. Even if that isn't possible (fairly likely, I would say, you can still try using --- or /// as your operator]
I checked: neither // nor /// can be used as operators (syntax error: they both just start a comment). All your other examples work, but I would say those mean the author is intentionally trying to trick me. Or he’s writing a clever DSL, but that line is very fine and treacherous.
Some other food for thought:
a = b-- // !z
x = y--// ! z
The first does a = b - 1
and has a comment, the second calls suffix --// on y, then infix ! On the result and z.A variation:
x+ - 3
x + -3
I think it is fair to say that Swift introduces a new variant of whitespace sensitivity.Also, the docs do not seem to discuss line breaks inside statements. If they are legal, you can do:
x+
-3
vs x+{space}
- 3
I think I would find it fun to stress test this language.It is both a blessing and a curse, as far as potential for abuse is concerned.
You pointed out the downside of arbitrary operator names. The downside of operator overloading on fixed operator names is that you are limited in your choice of operators, so instead of choosing a more distinct operator, you sometimes have to go with things that are kind-of-the-same, or maybe not close at all. And instead you also have the problem of misleading people, for example by using the +-operator for set union, while the reader thinks you are adding together numbers.
> Operator symbols are formed from one or more symbol characters, as defined above …
where 'above' is:
symbol -> ascSymbol | uniSymbol<special | _ | : | " | '>
ascSymbol -> ! | # | $ | % | & | * | + | . | / | < | = | > | ? | @
| \ | ^ | | | - | ~
uniSymbol -> any Unicode symbol or punctuation> (--|) = (+)
When I talk to myself while coding, I have no name to say out loud.
I have nothing but a picture, when I try to remember the operator.
http://stackoverflow.com/questions/7746894/are-there-pronoun...
http://stackoverflow.com/questions/3242361/haskell-how-is-pr...
I got to this by Googling for the 'fish' operator, to which I vaguely remembered seeing a reference:
http://www.reddit.com/r/haskell/comments/c262b/the_fish_oper...
In languages that don't allow you to overload operators at all, the alternative is to use explicit function syntax. That can sometimes be a short path unreadable to code that's littered with pyramids of doom.
In languages that only allow you to overload existing operators, you end up with monstrosities like C++'s << and >> operators, which overload the bit-shift operators with new and completely unrelated semantics. It's that kind of shenanigans that give operator overloading such a bad name.
Maybe you mean that people should write some types as some kind of assertion in case the code changes (and it compiles again, coincidentally because the change produced valid but different types, somehow)? I guess the same could be said for always putting certain assertions in the code in order to make sure that assumptions are sound, for example putting "@Override" on all methods that are intended to be overrided methods in Java. And again, since types are inferred, I guess it is conceivable that it can be automated like a code-style thing as a hook, since the compiler knows the type.
var myVariable = S()
when changed to
var myVariable = C()
will not cause any compiler error in rest of the code. Still, it may be a logical requirement for myVariable to hold instances of type S only. Yes, the programmer can explicitly declare type if s/he wants to, but I guess apple APIs will promote the culture of using type inference. Though hopefully apple will set the best tone possible of swift coding style in their APIs.
var employee = employeeRepository.Get(12345);
return employee.Name;
they'll see the code as untrustworthy because without an explicit type name, you've got no idea what kind of thing 'employee' is.I suppose there's also the 'making excessive generics too easy' issue, though personally I'm not certain that excessive generics are necessarily so terrible. Oftentimes the alternative is to litter your codebase with a bunch of one-off classes that bloat the codebase without adding any value. I think I side with the camp that cites that practice as one of the things that used to really suck about working in Java.
The real work of modernizing the libraries probably began only after WWDC.
There was a job listing posted to llvm-dev after the keynote that gives a few clues.
http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-June/073669....
Also, at least for Swift 1.0, they won't be. Swift does not guarantee a stable ABI right now or for 1.0. They guarantee binary compatibility with the OS, and ABI compatibility with any application frameworks that are compiled alongside the application (because, well, those can't change), but no compatibility between frameworks and applications. The only way to get that compatibility is to stick to Obj-C APIs (or, well, pure C APIs, but that's no better).
What this means is system frameworks will not be able to take advantage of things like generics or multiple return types until sometime in the future, past Swift 1.0. Of course, they couldn't justify doing that today anyway, because they need to maintain Obj-C compatibility for all of the Obj-C code that still exists.
The main "aha" point of this article for me was the way optional values eliminate a whole class of programming errors that are pervasive in the "C family" of languages, and does so in a rather elegant way. (Apparently Scala has a similar capability, but I'm not familiar with Scala.)
I agree Optional's should booster safety (in the iOS/OS X world) if Swift can convince everyone to start using them.
Or just simply "Maybe" ;)
https://groups.google.com/forum/#!topic/elm-discuss/1acyOfxv...