Can you list those same features that it provides? My understanding of Scala's philosophy is it provides as many features as it can. A Maybe type, immutable state, separation of IO, etc. isn't very useful if my coworker can choose not to use it.
In theory that's true, and I hope Scala eventually makes non-null, immutability and perhaps even I/O visible at the type level. In practice as long as it's clear when you are bypassing these systems, and you have a culture of not doing so (and the language libraries are part of the same culture), you get most of the benefits.
Even in Haskell you can cast out of your type system, or unsafePerformIO, no?
Scala is like Perl in that there is a non-zero possibility of writing non-native code. In Scala, you're supposed to favor immutability and functional constructs, but there's nothing preventing you from treating Scala exactly like Java. Same with Perl and C.
Also, if you need a language to dictate your coworker's behavior, that says something more about your coworker than the language. Why doesn't he just choose to write good code? (barring arguments regarding the activation energy of good versus bad code)
I assume by "non-native", you mean "non-idiomatic"?
Since I recently went through coworkers writing "bad" (by which I mean non-idiomatic) Scala, and repairing the situation, I can say that it was surprisingly easy to lay down "functional constructs" and the result was amazing. The code became reliable, well-structured, and easy to leverage. Switching to Scala for our projects -- including introducing procedurally minded programmers to it -- was a huge win for us.
Yeah, we discovered that for my team's projects as well. Having a scala "guru" define and teach idiomatic scala has actually increased our productivity a lot. Any non-idiomatic scala is now purely for interacting with our existing Java libraries
FWIW, the constructs with the initial biggest win for us (in converting procedural thinking) were pattern matching and option types. For pattern matching, the guidelines were
- Don't do any processing after the pattern match within a function; break into smaller functions
- Reach for pattern matching before if/else
- Avoid the use of var
- Avoid dropping through to wildcard pattern. (This tip was from Yaron Minsky of OCaml fame)
In conjunction with preferring the use of combinators over loops, and using Option (and being forced to think about None), we got surprisingly functional Scala code in a short time.
Sometimes it is good to drop into non-idiomatic, imperative code for the sake of performance. This is one of the things I like Scala for - it lets you choose your poison.
Scala doesn't really provide much of what is mentioned in the article.
It still has nullable types, side-effects aren't tracked in the type-system (so any function can potentially do anything) and the presence of sub-typing has several unpleasant consequences, for example: lack of full type-inference, generally more complex type signatures than in Haskell and having to deal with covariance vs contravariance.
If Scala provided all the things that were mentioned in the article exactly as is, Scala would become essentially yet another Haskell and couldn't do many things that Haskell can't (e.g. seamless usage of Java libraries, real OOP support or performant imperative code). And this would probably restrict it to the academic-niche.
Anyway, while I generally agree, I'd wish that people would stop bringing up type-inference in these discussions. It always makes me question whether those persons have understood the topic at all.