Thursday, October 23, 2008

Types and other virtues

Here's a thought. Why do Java Generics attract so much bad vibes? If we're talking about types again, gotta visit our old friends - ML, Haskell. They are doing fine, they've got it all figured out. Hindley-Milner etc., they've proved themselves to be right.

But them and Java, it's apples and oranges. So to bring them to the same arena with object oriented languages, let's see how are they doing on the front of extensibility? Well, there are some recent advancements, polymorphic variants in OCaml, extensible records in Haskell, but it's not like the other stuff they've figured out ages ago, there's a slight hint of hesitation here.

So having types and being object oriented at the same time - maybe it's just, hm, non-trivial. If Martin Odersky says it's hard for the compiler (and he's a genius!) - then it really must be. Now look at it as a reverse Turing test - if the machine can't figure it out, how the **** are we supposed to? Which means we need an escape route. If declaring the right type is hard, we need an easy way out.

Pre-generics Java didn't bother itself too much with complex static types, the trick was to fall back on the dynamic types whenever in doubt: arrays - ArrayStoreException, collections - ClassCastException. Some say it's broken. It's a hole in a fence, but it's a way out . "Oops"

Then Generics came and fixed the hole in the fence. But, without realizing, they violated the status-quo, the eco-system, they stepped on a butterfly. Suddenly, the brain hurts, and the only way out is dumping all the angle brackets and jumping over the fence. It's a "No Exit"!

What does Scala do? Ah! First of all Scala has a much more advanced type system to start with. But the real trick is implicits. If it's too hard to declare the right type, just imperatively describe the conversion. Done deal, here's your way out. It's pretty cool, but implicits have their share of bad vibes too. Can't live with them, can't live without them, I guess.

So how about implicits for Java 7? No, actually how about Scala for Java 7? It's been done before, you know...

10 comments:

Paul Beckford said...

Hi Yardena,
Now you are speaking my language. Static types and Objects don't go. In Smalltalk a Class is an Object. An Object is something that you can send a message to and will respond with an answer. Thats it period. A Class is an Object that answers with another object when you send it the message "new". What is the type of the instance Object? I would say Object. Now from the identity (name) of the factory Object (Class) I can make a good guess about the kinds of messages my instance Object will understand, but that isn't the same as its type. Instance Objects can mutate after construction so the name of the factory does not fix an objects type.

This idea of opaque objects that tell you nothing until you send them a message is central to OO IMO. The Objective-C guys get it.

In Objective-C by default all objects are of type "id". A single generic type.

When you try to add a static type system to a pure OO system you get into hot water pretty quickly. You either have to restrict the polymorphic/dynamic nature of your Objects or you need to opt out of your static type system and use a generic type for your Objects when needed. Java does a bit off both (well at least it use to before generics :)).

The right solution is to build your OO language around unrestricted, dynamic Objects and use optional static types where they are useful (if you so choose). ActionScript does this, Objective-C does this, Strongtalk does this.

The fact that Objective-C worked this out years before Java was invented shows that this issue is well understood. Some people just choose to sweep it under the carpet.

Paul.

Unknown said...

I have mixed feelings about Scala. I thought it is wonderful. Then I thought it is too complicated to be useful. At the next phase I realize that the whole notion of OO also seemed complicated back then (late 60's, 70's, even 80's). So maybe it's just an issue of climbing up the learning curve?

Ultimately, I arrived at the conclusion that a stronger static-type-system will not buy you half as much as testing. Scala's compiler can cover more grounds than Java's, but it can never cover everything (otherwise, Turing is dead wrong).

Once I became test-infected, the static type safety of the program stopped being an issue. I stopped caring about bulletproofing my design. I guess this is what the dynamic-typing guys were saying for years.

Finally, let me conclude with Steve Yegge's opinion on Scala. Go to this post and look for the "Static Typing's Paper Tigers" section.

Yardena said...

Itay,

I have read Steve Yegge's Paper Tigers (I've been following his blog for a while now) and I largely agree. Still, for those seeking improvement to Java, but not willing to give up OO, static typing or the JVM, Scala is the best option, probably the only real option. There's another heated debate that started recently over Guido Van Rossum's comment on Scala. I found myself puzzled at the same examples that Guido mentions while learning Scala, and have couple of friends who independently reached the same opinion. Scala has problems, mainly too many ways to do the same thing, and it becomes apparent even in simplest examples (ironically there are even 2 HelloWorld's) which scares people off. If one gets past that, there are actually a lot of great ideas in Scala and even though I have been mainly playing around, rather than doing actual development in it, I think it's a descent and useful language.

As for static vs. dynamic typing, I have been doing stuff in Smalltalk recently, and it's an amazing experience. It's way beyond Scala and other languages I've been looking at. But it is worth a full fledged blogpost sometime.

Unknown said...

(Let me start with a short apology: The tone of my comment was a bit blunt. Sorry, didn't mean it).

I agree with you in that Scala has a lot very good ideas and that it is currently the best lang. in a certain arena. I am just not sure as to the future appeal of this arena (Judging from your posts, so are you...).

BTW, what dialect of Smalltalk are you using?

Yardena said...

The tone of my comment was a bit blunt.

I didn't think it was - if anything in my response made you think so - I apologize too, it wasn't intentional.

I agree with you in that Scala has a lot very good ideas and that it is currently the best lang. in a certain arena. I am just not sure as to the future appeal of this arena (Judging from your posts, so are you...).

You got it!

BTW, what dialect of Smalltalk are you using?

I am actually zipzapping between Strongtalk and Squeak, but Newspeak is the reason for it all :-)

Paul Beckford said...

Itay,

You make a good point about unit tests. The real issue is feedback. As a programmer you want instant feedback that your program works. In Eclipse those little red lines in your editor indicating errors are feedback. With Lisp using the REPL command prompt and running your code gives you instant feedback (no compile phase needed). With XUnit that little green bar when you run your tests is instant feedback. The difference between static feedback and dynamic feedback is that dynamic feedback tells you whether your code actually works, whilst with Eclipse the red line is the compilers best guess that your code may not work.

By combining Objects and REPL together you end up with live objects that give you instant feedback. So in the words of David Ungar, you end up with Objects that when you bang on them they bang back. Giving you instant feedback. This idea is taken to its ultimate expression in Self but can be seen in Smalltalk too.

The trouble with Scala is that it is a functional language trying to masquerade as an OO language. If you make everything immutable and remove state then the compiler can do a much better job at checking for type safety. This is why functional languages like Haskell are a lot better at static typing then say Java.

Unfortunately Object Orientation is an imperative approach to programming which relies on encapsulated state which is at odds with the functional idea of "no state". Take a look at generics in Scala. What they do there is use immutable collections. So there is no "add" for a Scala collection only "append", which in true functional style gives you a new collection.

As for all the other stuff like implicits etc. It goes way over my head. If the solution starts to get more complicated then the problem then its a sure sign that you are barking up the wrong tree.

As for me I'd rather suck it and see, either using something like Rspec and Ruby or just by refreshing my browser in good old REPL style and seeing whether my code works.

I guess my point is that static typing is no silver bullet and there are alternatives.


Paul.

Yardena said...

Hey, nice to see such a lively discussion. Paul, Itay - thanks for commenting. :-)

Regarding tests - I once in a while make some silly mistake, one that static type checker would have caught. But because I had tests anyway, and any serious test caught stupid errors before it got to the "real" stuff - it is not entirely true that one needs to write more tests. Now, I completely agree with Paul that it's all about feedback cycle. When I got the error, the method editor was there, couple keystrokes, save, proceed - that's it. Whereas in Eclipse it would have been - go to the file, recompile, restart the whole test suite - a whole ritual. So even cautiously put - it looks to me that cost of correcting a mistake is overall not much higher than in statically checked env, maybe even lower. On the other hand, I must admit that Strongtalk type annotations helped readability. I could see what a method does quicker. Even though I find Smalltalk code very readable in general - having the annotations, regardless of compiler checking them, helped. Of course if they remain only for beauty, people will stop updating them, so they should emit at least warnings. That's my 2c, anyway.

Regarding Scala, it's not implicits that bother me so much. I don't know if it's full-monty functional plus full-monty OO that sums up in too much, or something else... I went over the whole language spec at one point, and some papers. But every time I think I "got it" with Scala, I see another example on the web which looks totally "WTF?". Yeah, I admit I am still weak with currying and monads. But I think that if I would go Haskell all the way, that's what I would focus on learning. But then that would be mainly it - no OO or Java-interop stuff, while in Scala it all adds... I don't know. Maybe cutting some features off Scala and enforcing stricter coding conventions would improve it... then again judging from the responses on the mailing list it's not gonna happen.

Unknown said...

Paul, Yardena,

My feeling, WRT Scala, is that it is a "clever" language - in the bad sense of the word. Too many esoteric tricks whose impact on the type system is marginal. I first tried Scala more than three years ago, and this impression just gets stronger over the years.

On a more philosophical note, It seems that the relative dominance of statically-typed languages in previous decades, resulted in many misconceptions that found their way into the mainstream.

Examples: The overrated importance of static typing; underestimating the importance of testing (luckily, most programmers got over this one); the assumption that a program's complexity can be measured by traversing its static structure; the underestimated REPL; the assumption that serious application cannot be written in a dynamically typed language; and so on ...

Paradoxically, despite the lack of formal mathematical proofs in this area, people are *less* inclined to accept new ideas. Too bad.

Yardena said...

Hi Itay,

I am curious - what are you developing in?

Unknown said...

Static: Java
Dynamic: Javascript

(And I am using Javascript for more than just checking the correctness of a form field on an HTML page...)