Article Discussion
The Origins of Scala
Summary: Martin Odersky talks with Bill Venners about the history that led to the creation of the Scala programming language.
77 posts on 6 pages.      
« Previous 1 2 3 4 5 6 Next »
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: May 21, 2009 4:21 AM by
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
The Origins of Scala
May 3, 2009 9:00 PM      
In this Artima interview, Bill Venners talks with Martin Odersky about the history that led to the creation of the Scala programming language:

http://www.artima.com/scalazine/articles/origins_of_scala.html

What do you think of Odersky's reasons for wanting to break source compatibility with Java?
Carson
Posts: 18 / Nickname: cgross / Registered: October 16, 2006 3:21 AM
Re: The Origins of Scala
May 4, 2009 10:30 AM      
Heh. Well, here's an interesting tweak on the generics reasoning: in our internal programming language we've actually gone the other way. Covariance, for all it's faults, is pretty simple to understand and use. Therefore we have covariance of generic types.

It isn't sound but it is simple. You get 90% (95%? 99%? 30%?) of the benefits of generics with almost no mental costs. Given that java development was trucking along just fine without generics, it seems like the type-safety argument for them isn't as strong as is often suggested.

Worse is better?

Cheers,
Carson
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: The Origins of Scala
May 4, 2009 10:43 AM      
> It isn't sound but it is simple. You get 90% (95%? 99%?
> 30%?) of the benefits of generics with almost no mental
> costs. Given that java development was trucking along
> just fine without generics, it seems like the type-safety
> argument for them isn't as strong as is often suggested.

I think it comes down to theory over practice. In theory, covariance is not adequate. In practice, it's only potentially an issue when your covariant types are mutable and even then only in rare cases does it become an issue and I'm fairly sure there's always a workaround. You get most of the value without all the extra complexity. The real problem with more complicated variance is that it's often hard to see that the declarations you use now will limit you later and unwinding them is difficult.
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
Re: The Origins of Scala
May 4, 2009 3:25 PM      
> Heh. Well, here's an interesting tweak on the generics
> reasoning: in our internal programming language we've
> actually gone the other way. Covariance, for all it's
> faults, is pretty simple to understand and use. Therefore
> we have covariance of generic types.
>
> It isn't sound but it is simple. You get 90% (95%? 99%?
> 30%?) of the benefits of generics with almost no mental
> costs. Given that java development was trucking along
> just fine without generics, it seems like the type-safety
> argument for them isn't as strong as is often suggested.
>
> Worse is better?
>
I can't actually remember a specific instance where I actually got an ArrayStoreException in Java, though I have a vague feeling I saw one once or twice. But that's in over decade of relatively regular Java programming. So in the Java array case at least, the type unsoundness of array covariance didn't seem to be a very costly hack for me in practice. (Except perhaps for the "original sin" problem Martin pointed out of making it hard to do generics well in Java later.)

I'm curious what the implication of assuming covariance for type parameter is in practice? Do you have to occasionally to casts if you need contravariance for example? Or how would that even work? I guess my question is, since you are actually using this approach, what is the practical downsides, and are there upsides aside from conceptual simplicity?
Martin
Posts: 15 / Nickname: modersky / Registered: September 14, 2003 9:46 PM
Re: The Origins of Scala
May 4, 2009 3:35 PM      
> I think it comes down to theory over practice. In theory,
> covariance is not adequate. In practice, it's only
> potentially an issue when your covariant types are mutable
> and even then only in rare cases does it become an issue
> and I'm fairly sure there's always a workaround.

Theory says this is wrong :-) Here's why:


class Function[A, B] {
def apply(x: A): B
}

class Adder extends Function[Int, Int] {
def apply(x: Int): Int = x * x
}

object Test {
def testWithString(f: Function[Any, Any]) {
f("hi")
}
testWithString(Adder) // boom! we multiply a string
}

No mutability anywhere, yet if you let Function be covariant (which Scala does not do, I hasten to add),
you get a runtime error. I claim this is relevant in practice because otherwise all your higher-order functions are potential type holes.

So, sometimes, theory has a thing or two to teach to practice :-)
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
Re: The Origins of Scala
May 4, 2009 3:39 PM      
> > It isn't sound but it is simple. You get 90% (95%?
> 99%?
> > 30%?) of the benefits of generics with almost no mental
> > costs. Given that java development was trucking along
> > just fine without generics, it seems like the
> type-safety
> > argument for them isn't as strong as is often
> suggested.
>
> I think it comes down to theory over practice. In theory,
> covariance is not adequate. In practice, it's only
> potentially an issue when your covariant types are mutable
> and even then only in rare cases does it become an issue
> and I'm fairly sure there's always a workaround. You get
> most of the value without all the extra complexity. The
> real problem with more complicated variance is that it's
> often hard to see that the declarations you use now will
> limit you later and unwinding them is difficult.
>
Are you talking primarily about Java's wildcard variance annotations? If so, I can see your point. For a long time I ignored them, and didn't try and learn or understand them, mostly because we just didn't have time to generify our app, even though we wanted to. There were just always more important things to do with our limited resources. So I didn't really tackle Java wildcards until I started learning Scala's variance stuff, and I do find wildcards confusing myself.

Josh Bloch tried to make it easier by providing a mnemonic in his Effective Java 2nd edition book. He talked about it at Devoxx last December, and had a picture of our (Californian's) Governer, Arnold Schwarzenegger, as a younger, bare-chested man. Because the mnemonic was PECS, for Provide Extends Consumer Super. That might make it easier, but frankly I think it is a terribly big complexity burden to require anyone using any generic type in a method signature to try and figure out what the variance should be. So regardless of how you value the benefit of type soundness, the cost with wildcards seems high. And as you say, if someone gets this wrong, it can be difficult to unwind it and change it later, because any code that uses that method signature or subclasses, overrides it, etc., can break.

I think declaration site variance that Scala uses is much easier on users, but I don't have enough experience to know how much easier. In other words, the cost is much lower than Java's wildcards, and I think also the cost of change is also mitigated. If a library designer tries to make something covariant or contravariant that isn't by nature covariant or contravariant, the program won't compile. Any nonvariant type will compile (absent other problems), but you can always change a nonvariant type parameter into a covariant or contravariant one without breaking any client code.

I also think that nonvariant and covariant will not be too hard for most programmers to grasp. Only contravariance is counterintuitive, but hopefully with a bit of study and head scratching, most people will be able to grok it. But is Scala's variance simple enough to reduce the cost and make it worth the benefit? I'd be curious to hear what people who have actually used Scala think on that question.
Stephen
Posts: 1 / Nickname: scolebourn / Registered: February 10, 2007 9:48 AM
Re: The Origins of Scala
May 4, 2009 3:39 PM      
This article and discussion emphasises the key debate over generics and arrays, and which approach works best. I've had a variety of conversations with language designers down the years, and one thing I've noticed is that there is often a strong emphasis on proving the type system. As part of this, there is often a extremely strong dislike of arrays because of their 'unsound' covariant nature.

However, in the real world, I find that all the developers I talk to have no problem whatsoever with the covariant nature of arrays, and even find it more intuitive than the restrictions imposed when its done 'correctly' (generics). I can only conclude that this is just a difference in how (academic) language designers and developers think about the languages they write/use.

If you want to see what a JavaNG language looks like where you can freely switch between a List of Numbers and a List of Integers, take a look at Fan - http://fandev.org . Where Scala takes Java's type system and strengthens it, Fan goes the opposite direction, and takes a slightly more dynamic approach. Given the success of fully-dynamic languages over the past few years, it seems to me that Scala's super-static typing isn't the way for the industry to go.
Martin
Posts: 15 / Nickname: modersky / Registered: September 14, 2003 9:46 PM
Re: The Origins of Scala
May 4, 2009 4:11 PM      
Slightly edited example, to make it less confusing:

class Function[A, B] {
def apply(x: A): B
}

class Squarer extends Function[Int, Int] {
def apply(x: Int): Int = x * x
}

object Test {
def testWithString(f: Function[Any, Any]) {
f.apply("hi")
}
testWithString(Squarer) // In Scala, this is a variance error. Otherwise: boom! we square a string
}
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
Re: The Origins of Scala
May 4, 2009 4:16 PM      
> This article and discussion emphasises the key debate over
> generics and arrays, and which approach works best. I've
> had a variety of conversations with language designers
> down the years, and one thing I've noticed is that there
> is often a strong emphasis on proving the type system. As
> part of this, there is often a extremely strong dislike of
> arrays because of their 'unsound' covariant nature.
>
> However, in the real world, I find that all the developers
> I talk to have no problem whatsoever with the covariant
> nature of arrays, and even find it more intuitive than the
> restrictions imposed when its done 'correctly' (generics).
> I can only conclude that this is just a difference in how
> (academic) language designers and developers think about
> the languages they write/use.
>
I suspect the dislike is on array covariance, not arrays per se. Is that correct? Because I'd expect nonvariant arrays in a language with generics wouldn't bother anyone, academic or otherwise.

> If you want to see what a JavaNG language looks like where
> you can freely switch between a List of Numbers and a List
> of Integers, take a look at Fan - http://fandev.org .
> Where Scala takes Java's type system and strengthens it,
> Fan goes the opposite direction, and takes a slightly more
> dynamic approach. Given the success of fully-dynamic
> languages over the past few years, it seems to me that
> Scala's super-static typing isn't the way for the industry
> to go.
>
I've been curious about Fan's approach. My understanding is users can't make generic types, but that three built in types (Map, List, and Func) take type parameters. I assume Map takes 2, List 1, and Func a return type plus 0 to many parameter types.

First, are these type parameters on Map, List, and Func treated as nonvariant, covariant, contravariant? Or some combination? I see no mention of variance in their documentation.

Also, what do people usually do when they want to make some other collection besides List or Map? Do they cast, or perhaps use the -> to invoke mehods dynamically on objects pulled out of collections?
Daniel
Posts: 3 / Nickname: 56653 / Registered: July 4, 2008 9:51 PM
Re: The Origins of Scala
May 4, 2009 11:25 PM      
> ...
> If you want to see what a JavaNG language looks like where
> you can freely switch between a List of Numbers and a List
> of Integers, take a look at Fan - http://fandev.org .
> Where Scala takes Java's type system and strengthens it,
> Fan goes the opposite direction, and takes a slightly more
> dynamic approach. Given the success of fully-dynamic
> languages over the past few years, it seems to me that
> Scala's super-static typing isn't the way for the industry
> to go.

I think this is a common misconception. This is what an average programmer "sees":
- Java types are restrictive and the syntax is horrible
- Scala types look scary, especially the generics (with all that +, -, <:, <%...)
Of course this leads to the "conclusion" to avoid that kind of trouble.

However:
- Scala solved the syntax problem so well that still some people think it is a dynamic language
- Statical correctness can give you a confidence you'll never get with unit tests. This is even more true when using functional style. I found myself thinking "if it compiles, it is correct" in several situations, and so it was.
- When you're not able to express your ideas using types, your ideas are usually "fuzzy" - which *might* still work, but doesn't scale well
Andrew
Posts: 18 / Nickname: 55548 / Registered: May 16, 2008 6:33 AM
Re: The Origins of Scala
May 4, 2009 11:35 PM      
> I'm curious what the implication of assuming covariance
> for type parameter is in practice?

Eiffel allows covariant input parameters for methods. This approach is often "beaten up" by academic researchers, but it always seemed to be intuitive to me.

I remember reading the excellent treatment of contra/covariance in A Theory Of Objects (Abadi, Cardelli) and thinking this only applies to the single record type dispatch model. As demonstrated in http://portal.acm.org/citation.cfm?id=203096 the conflict goes away with generic functions.
Brian
Posts: 2 / Nickname: brianfrank / Registered: December 16, 2008 1:56 AM
Re: The Origins of Scala
May 5, 2009 3:53 AM      
> I assume Map takes 2, List 1, and Func a return type plus 0 to many parameter types.

That is correct - each one uses a custom syntax. For example Fan's List parametrization looks like the Java array syntax. Because generics are used with only built-in types, it allows Fan to easily maintain the parametrization at runtime for reflection. For example given a list of Str, the type signature would be Str[], and you could reflect this type from the list at runtime. That becomes important for meta-programming and serialization.

> First, are these type parameters on Map, List, and Func treated as nonvariant, covariant, contravariant? Or some combination? I see no mention of variance in their documentation.

Technically they are covariant similar to Java arrays (although from the setter method perspective that allows contravariance). But it is sort of moot issue in Fan. Fan is mostly statically typed, however the compiler only flags type errors which are guaranteed to be never be correct - for example passing a Str where an Int is expected. However any type check which could pass at runtime will generate a synthetic cast to keep the JVM/CLR happy. For example passing a Num where an Int is expected doesn't require an explicit cast.

It seems sort of crazy, but it turns out to be a great compromise. Almost all type errors still end up getting caught at compile time, we get Java-like performance, yet it avoids all the nasty syntax that clutters up Java code. So Fan's philosophy has been to use the type system as a useful tool whenever it makes sense, but break out of it whenever it gets into the way.

> Also, what do people usually do when they want to make some other collection besides List or Map? Do they cast, or perhaps use the -> to invoke mehods dynamically on objects pulled out of collections?

I actually have seen it done very much - most all the code I've seen just uses the built-in types. But you would basically design it to work with Obj just like the pre-generics Java collections. The difference is you don't actually do the casting (it gets done for you). Although I use -> for duck typing things myself too.
James
Posts: 128 / Nickname: watson / Registered: September 7, 2005 3:37 AM
Re: The Origins of Scala
May 5, 2009 6:08 AM      
> No mutability anywhere, yet if you let Function be
> covariant (which Scala does not do, I hasten to add),
> you get a runtime error. I claim this is relevant in
> practice because otherwise all your higher-order functions
> are potential type holes.

I see my error. I said mutability but what I really mean is that as long as you are not calling methods with covariant parameters and only using return values or otherwise only doing pulls instead of pushes, there are no issues with covariance. Of course, you might be able to show an example of such an issue that I am unaware of but my main point it is the unchanged.

There's no doubt that the kind of situation you show in your example can come about but it's just not worth introducing the extra complexity over. It's a really drastic case of diminishing returns. The initial return of covariant types is huge with very little complexity. Adding soundness adds a lot of complexity for very little benefit.
Jules
Posts: 2 / Nickname: jules2 / Registered: March 4, 2006 9:24 AM
Re: The Origins of Scala
May 5, 2009 6:30 AM      
Here's a link to the paper for those who do not have an ACM account: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.56.2799
James
Posts: 11 / Nickname: jiry / Registered: November 15, 2007 2:29 AM
Re: The Origins of Scala
May 5, 2009 7:02 AM      
> However, in the real world, I find that all the developers
> I talk to have no problem whatsoever with the covariant
> nature of arrays, and even find it more intuitive than the
> restrictions imposed when its done 'correctly' (generics).
> I can only conclude that this is just a difference in how
> (academic) language designers and developers think about
> the languages they write/use.


Then allow me to be your one counter data point. I have no graduate degrees. My undergraduate schooling was at a state college. I have 17 years of programming experience varying in "enterprise" systems, web startups, shrink wrap commercial software, and open source projects. The vast majority of my code has been in languages like Java, C++, SQL, and Javascript. I'm a "real world" programmer, not an academic.

I find Java's covariant arrays irritating and problematic. They interact poorly with the rest of Java. If used extensively for non-primitives I do get ArrayStoreExceptions. If I could wave a magic wand and fix this one aspect of Java I would. In practice I just mostly avoid using arrays.

Making everything covariant is deeply unintuitive and confusing to me. It violates Liskov substitution. It violates the old protocol guideline "be strict in what you send, be lenient in what you accept." It's counter to the way method calls work.

So, please, for the love of all that is good, please stop trying to make things into academic vs real world debates. It's disgusting. You don't see electrical engineers running around saying "we don't use Ohm's law here, it's too academic."
77 posts on 6 pages.
« Previous 1 2 3 4 5 6 Next »