top | item 8456802

Scala: the Case for Correctness

56 points| artgon | 11 years ago |arthur.gonigberg.com | reply

60 comments

order
[+] joegaudet|11 years ago|reply
Having jumped back into some green field work in Scala in the past few days, I will say I'm quite impressed with the improvements to the SBT, IntelliJ, universe. Compile time seems to be improved considerably (though the project is still quite small so time will certainly tell).

One problem, which is also one of the advantages of scala is that the interop with Java often means that all your Option[] etc code can still get NPEed by some offending Java Lib you've decided to use.

As the fidelity and ubiquity of pure scala libs improves this will hopefully go away to a some extend.

[+] fedesilva|11 years ago|reply
You can always use Option() as in:

scala> Option(System.getProperty("kaboom"))

res1: Option[String] = None

then map, getOrElse or fold at will.

(edited format)

[+] jakozaur|11 years ago|reply
Scala gets a lot of things right by default. Also it got a lot of flexibility and power. Almost "a framework" to write other languages within the language.

Use it every work day for over two years... Like a lot, but sometimes wishes it would be a bit simpler and more aesthetic.

[+] rld|11 years ago|reply
What do you mean by "more aesthetic"? As in syntax?
[+] joegaudet|11 years ago|reply
Fair Warning, I worked with the other for some time, and have been having an out of band convo with him.

One of the things I absolutely HATE about scala is operator overloading - and the excessive abuse of it. I ran into it just now using some library that used ==.

A Case:

List(1,2) == List(1,2); true Array(1,2) == Array(1,2); false

The reason for this is obvious, list implements equals and does a deep compare. While Array.equals is a pointer compare (like how java do).

This would be obvious in Java because that would look like.

ArrayList<> a = ArrayList<Int>(); ArrayList<> b = ArrayList<Int>(); a.equals(b); // equal because it's a value compare

versus

int[] a = new int[5] int[] b = new int[5] a == b; // obviously false because it's a reference compare.

The lack of a universal idea about what == means is pretty dangerous IMO.

*edited for spelling

[+] frowaway001|11 years ago|reply
> The lack of a universal idea about what == means is pretty dangerous IMO.

There is an universal idea what == means, it's quite simple and more consistent then the mess Java has.

It's just that the JVM's idea cannot be brought in line with it consistently.

If you look at the history of Scala, you'd see that they tried to make Arrays work this way for 5+ years.

The blood being shed just wasn't worth the quirks it caused in other parts and in the end trying to fix the JVM's idea of arrays was abandoned.

[+] jghn|11 years ago|reply
This is absolutely my #1 complaint about Scala, and really it's more a complaint about the community. It's not just the operator overloading, but the overuse of operator characters instead of meaningful function names.

All of this leads to potential newcomers thinking Scala is some inscrutable mess of a language, and even old fogeys will have to scratch their heads.

[+] sinwave|11 years ago|reply
I would pay good money to see Paul Philips' reaction to the sentence

> "the biggest benefit with Scala is correctness."

...before the author goes on to say

> "When I say correctness, I mean the ability to easily and consistently write code that works as inteded (not the academic definition of correctness)"

[+] Animats|11 years ago|reply
As someone who used to work on automatic proof of correctness systems, that irked me too.

It's quite reasonable to have a language where certain classes of errors cannot be generated from the source code. There are languages which can reliably detect or prevent subscript out of range errors, null pointer errors, dangling pointer errors, and race conditions. (C and C++ detect and prevent none of the above, which is the cause of most of the troubles in computing.) That's not full correctness; it's just language safety. It means you can't break the language model from inside the language. Most of the "scripting languages" have this property, or at least are supposed to.

Scala takes the null pointer issue a bit more seriously than most languages. That's good, but not enough to justify a claim that it offers "correctness".

[+] rld|11 years ago|reply
Not mentioned here: pattern matching. It certainly goes a long way to ensure all cases are being handled, since the compiler lets you know when your patterns are non-exhaustive.
[+] apoorvai|11 years ago|reply
It is.

"Yes, you can write more concise code; yes, you have a more advanced type system; yes, you can pattern match. There are hundreds of other reasons that Scala makes a great language. When a language can offer me constructs to write more correct code, I'll always be willing to deal with the learning curve."

I think the point was that these are the things that he thinks are of more value to developers than the other good things that Scala offers.

[+] eranation|11 years ago|reply
I see Scala as an alternative to Java/Go for Ruby web developers who want a statically typed language that feels more dynamic. Yes, you can go crazy with Scala, but if you are responsible, I would say that migrating from Ruby to Scala is easier than to Java or Go. (I use Scala at work commercially for 3 years now and I have my issues with it, but I don't have an alternative, tried Kotlin and Java 8, and some Go, couldn't give up Scala)
[+] aikah|11 years ago|reply
> Yes, you can go crazy with Scala, but if you are responsible

The problem is not so much the code you write but the one you have to read/use.Languages that are more rigid are often easier to work with,they are predictable,as you wont have to deal with strange apis.

I believe Java8 or Kotlin are good enough. Scala is sometimes just unreadable when you have to read other people's source code.

but maybe it's just me.

[+] ddossot|11 years ago|reply
Interestingly, the Ruby developers I know seem more inclined towards Clojure than Scala. One stated he was more attracted by immutability than type safety, hence Clojure over Scala.
[+] zaptheimpaler|11 years ago|reply
Another thing I like about Scala is its support for duck-typing like python, except it is actually enforced at compile time via traits and magic methods.

e.g you can define your own methods to sugar and desugar for pattern matches, define an apply method to treat a class like a function, or map() on an Option type - it simply behaves as a list of size 0 or 1 and that is all you need to map.

[+] danellis|11 years ago|reply
Apart from pattern matching, your example isn't like duck typing: it's all entirely statically typed. Scala does have structural types, which is a bit like duck typing.
[+] andolanra|11 years ago|reply

    When I say correctness, I mean the ability to easily and
    consistently write code that works as inteded (not the academic
    definition of correctness).
I'm curious as to what the author believes the academic definition of 'correctness' actually is. Is it something other than code "working as inteded [sic]"?
[+] artgon|11 years ago|reply
Thanks for pointing out the typo, I fixed it.

By academic correctness, I mean the formal definition in computer science, i.e. for an algorithm. More here: http://en.wikipedia.org/wiki/Correctness_(computer_science)

By this measure, it's hard to say any language is more or less "correct" than another.

[+] emergentcypher|11 years ago|reply
Been working with Scala for 1.5 years and loving it. sbt feels easy to work with, compile times have improved (and you can improve it further by modularizing your app). Scala gets a lot right. Type inference makes it feel dynamic while still being safely typed at the compiler. Pattern matching and everything-is-an-expression are really the killer features for me that makes my code much more expressive.

The one thing that does bother me, as mentioned elsewhere, is operator overloading. There is a veritable soup of operators and you're never quite sure what an operator is actually doing. Worse, there aren't any plaintext equivalents. scala.collection.List doesn't have any "prepend/unshift" or "append/push" methods... all you have are ::, :::, +:, :+, /:, :\, :::, ++:, :++, ++ and so on.

[+] StefanKarpinski|11 years ago|reply
I don't get the business of marking variables as const in local scope (aka "val" aka "final" for local variables). It's easy for a parser or a person to scan the local scope and see if a variable is ever possibly mutated or not. This is very different from the situation with globals where it's generally intractable to prove that something is never mutated. In local lexical scope you can see all possible mutations by the definition of "lexical scope": a const variable is one that is assigned only once, a non-const variable is one that may be assigned multiple times – this is a straightforward syntactic property. Is there some benefit to marking local lexical variables as constant that I'm missing?
[+] rld|11 years ago|reply
At least in Java, non-final variables can't be used inside anonymous inner classes. Also, it's easier for me as a developer to read "final" and know that (referential) immutability is guaranteed by the compiler instead of having to read the local scope, which likely contains method calls that may or may not modify that variable.

val and final have stronger meanings when your objects are immutable. True immutability makes reasoning far easier than just referential immutability.

[+] mzl|11 years ago|reply
When it comes to helping a programmer understand code, every little bit helps. Humans are not good at parsing and keeping complex state in our minds, computers are. The less clutter I need to keep track of, the more interesting stuff about the code I can concern myself with.

As for marking local variable bindings as non-changing, I think it is tremendously helpful. In the (mostly Java) code base I work in daily we use this throughout. The net result is that I can just assume that property for everything, and whenever I see a variable not marked as non-changing I immediately know that something less than obvious is happening.

Given the above, I am naturally a big fan of making non-changing variable bindings (final/cons/val/...) the default and updatable variable bindings the case that should be marked. I would also like to work in a language where immutability of not just the variable binding but also the values themselves was better handled by the language.

[+] ma_mazmaz|11 years ago|reply
In Scala, most variables should be val (i.e. constant) from a design perspective. That is, it is better, in Scala, to write code that does not have changing variable. Thus, using val instead of var is simply a check on the code, much in the same way that static typing provides a benefit over dynamic typing.
[+] hrjet|11 years ago|reply
Purely from a reader's perspective, yes, an IDE can probably parse and highlight mutable variables automatically.

But from a writer's, modifier's or refactorer's perspective, what counts is the intent. Was a particular local variable meant to be mutable or immutable? Everytime I write a line of code, I need to watch out whether I mutated a variable which was not meant to be mutated. Or even the case where I myself mutate it unintentionally (by a typo, for example).

In a non-trivial project having a code-base with 100K lines of code, the time and effort spent in this manual analysis can be an overhead that might be well worth avoiding.

[+] frowaway001|11 years ago|reply
> It's easy for a parser or a person to scan the local scope and see if a variable is ever possibly mutated or not.

"what the parser figured out" != "what the author intended"

> this is a straightforward syntactic property

Not for the reader.

[+] joegaudet|11 years ago|reply
The main issue at the end of the day is compile time. They are working hard to address this, and from the first day we started using Scala to now, it's improved dramatically - but definitely lots of room for improvement where that's concerned.
[+] virtualwhys|11 years ago|reply
> The main issue at the end of the day is compile time

For deployment, sure, but for daily dev the vast majority of one's time should be spent taking advantage of sbt's incremental build feature; there the compile hit is pretty neglible (particularly when you break out your application into sub projects/modules).

Even after the proposed Scala overhaul (i.e. Dotty in around 4 years time) it's unlikely that clean builds will be blazing fast.

To put in perspective, right now scalac is roughly 10X slower than javac. Scala compiler team is banking on getting a speed up by generating Java 8 closures under the hood with Scala 2.12; that will mean less code for scalac to generate.

Beyond that, trimming down language features and streamlining the type system will provide further compile time reduction. As you say, lots of room for improvement ;-)

[+] defpan|11 years ago|reply
I totally agree with the author. The one's mentioned in the article are really the key benefits. I really wish scala didn't have implicits. People go crazy with implicits resulting in very difficult to read code. Sometimes I feel like going back to java just for the readability and then I remember these nice features of scala. We need a scala minus implicits.
[+] frowaway001|11 years ago|reply
> We need a scala minus implicits.

I don't find the idea of programming without typeclasses appealing – at all.

[+] rld|11 years ago|reply
Just out of curiosity, which libraries or frameworks do you feel abuse implicits?
[+] skybrian|11 years ago|reply
It seems like these points are true of other Java alternatives as well. What about Ceylon, Fantom, and Kotlin?
[+] frowaway001|11 years ago|reply
Fantom: Typesystem is unsound, far away from correctness, only hard-coded Generics, many basic things are not expressions, like if-then-else or try-catch.

Ceylon: if-then-else or try-catch are no expressions, embraces null, unstable software, breaks backward compatibility in minor releases.

Kotlin: Embraces null, inexpressive type system limits the things the compiler can check, unstable software, breaks backward compatibility in minor releases.

[+] vorg|11 years ago|reply
Clojure and Scala are really the only alternative JVM languages to gain any traction since Sun/Oracle started promoting the JVM for languages other than Java.

Most of the other languages I've noticed mentioned in the comments so far (i.e. C, C++, Go, Ruby, Python, JavaScript, Haskell) don't target the JVM, and those that do just do it on the side.

Perhaps Ceylon or Kotlin will gain some traction and become a third alternative for the JVM -- all the other contenders have been around too long and lost momentum. I'd pick Kotlin over Ceylon since it can use the popular IntelliJ as a delivery platform.