This is sort of true in theory, but not in practice. Scala is actually a pretty pragmatic and - for what you actually need in practice - conceptually simple language. In many ways it's simpler than Java.
It does have a powerful type system, and people do bizarre and unnatural things with it, but unless you're trying to do those things the complexity doesn't come into play.
(That's an interesting contrast with C++, where in theory all its features were designed to be orthogonal so that you don't need to know about exceptions or templates unless you're using them, but in practice in any nontrivial codebase you'll spend days staring at screenfuls of incomprehensible STL errors.)
It's actually smaller and simpler than Java or C++ as far as I know. It's designed to have fewer edge cases and employ a smaller number of powerful features instead of many less-expressive ones.
It's interesting that you use the word "scare." It's a computer language. What's there to be afraid of?
With great power and complexity comes great responsibility. Not many people can write decent C++ programs given the complexity of the language. It's pretty easy to abuse the power and write horrible code.
Currently Scala is less affected, since there are not many users at this pont. I'd say this group consists of more sophisticated users, too.
> It's interesting that you use the word "scare." It's a computer language. What's there to be afraid of?
I guess you haven't read very much C++ code. :P
With respect to the intent of its design versus the outcome, I can think of a few things that have been difficult for me in my playing with Scala. Implicit parameters, type parameters in general, especially the <: and >: operators, and some things like :/ and Ordering.by have confounded me quite a bit. The limited nature of its point-free style is also kind of difficult to get in -- IMO, they should have left that out entirely because two ways to do something is often worse than one. The distinction between = and = { at the end of method declarations, when you do and don't have to put parens on a no-arg method, and various other little quirks of the syntax are also a little annoying.
Don't get me wrong. I'd far rather program in Scala than C++ on a day to day basis. But, it seems quite large to me. It's a subjective measure, but that's my assessment as a professional C++ programmer and a beginner Scala programmer.
If you believe, as I do, that a given programmer can produce roughly the same number of lines of code per day independent of the language used, you can see how this reduction of lines of code can translate into a substantial increase in productivity and a faster time-to-market.
Do people actually believe this? It seems to me the time spent typing actual lines of code is dwarfed by an order of magnitude by the time spent thinking between writing each line or method, cut and pasting for refactoring, etc. To borrow Fred Brooks' terminology, I think the most common languages at this point - certainly Java, Ruby, and Python - are at a high enough level that we spend an order of magnitude more time on fundamental rather than incidental complexity.
I Agree. If one would take "concepts a day" or structures/modules/interfaces/whatever-intelligible-concept a day I could follow he author. But lines per day? Put this way developers seem coding monkeys using smaller paper in their typewriter to produce more pages.
Not true at all. I encounter incidental complexity all the time when writing code in Java, Ruby, and Python. Especially when I need to interface with other libraries and other frameworks.
Ruby, Python, Java deal with the expression problem very poorly. The desire to write code generically is real so you have the mess of generics and people run to dynamic langs. In dynamic langs the desire to monkey-patch is real because you often need to extend objects whose source you do not control. In dynamic langs you often want an extension point, that does not a mean a list of methods to call, rather a list of method signatures to implement so I plug my own functionality in w/o reading through your source.
All this adds up to countless hours wasted.
These are real problems in real software today that current mainstream languages address very poorly.
Scala (implicits, structural typing) and Clojure (protocols, extend-type) both have great solutions to these problems. Anyone know of other langs that deal with these issues properly?
Haskell. Aside from usual functional facilities for code reuse such as polymorphism and Higher Order Functions, monads (specifically monadic composition) and Type Classes are quite useful for writing generic code.
Am I correct in assuming that any language with support for overloading functions for new types, instead of extending existing types with new members/methods, would have a solution to such issues? This would then also cover:
* anything CLOS-inspired: Common Lisp, Dylan, Factor, Clojure
* but also presumably anything with C++- or Clay-like (http://tachyon.in/clay/) generic programming, namely w.r.t generically using freely-overloadable functions. I believe Haskell achieves something similar to this using type classes.
> In dynamic langs the desire to monkey-patch is real because you often need to extend objects whose source you do not control.
And in static languages, you never need to extend objects whose source you do not control.
I must be doing it wrong - I've only been tempted to monkey patch once, and that was because the folks who controlled the code explicitly said to monkey patch in certain circumstances.
My experience is that in e.g. multi-tier web apps fundamental complexity (often little more than CRUD at its core) is still usually completely swamped by incidental complexity.
I've always disliked that metric (constant lines / day) because I've never believed it took into account the real full lifecycle of code.
For example, as much as people (mostly) dislike creating code in Java, when I inherit code to maintain I love it when it is Java. It is just so straightforward with such limited ability to confuse or abstract things (as much as the many frameworks try) that I know I can always easily get to the bottom of any problem. Not to mention things like awesome debugging facilities and runtime analysis tools. With other languages I'm just lost once they reach any level of complexity because they all start doing "magic".
I hope that Scala perhaps retains a little of this through it's statically typed nature - but there's enough potential for "magic" there that I suspect it's partly lost. This is why I'm quite intrigued by Mirah (http://www.mirah.org/) ... but that is a long way from being mainstream enough to be useful in a wide range of situations.
Well, it's interesting because my reply touches on that. I don't believe writing code is the hardest part of programming. Designing and thinking about code is the hard part. This was my reply:
I find the LOC discussion of Sala fascinating. In my time working on my Open Source Scala project, I've found that it does take me longer to type out each line of Scala compared to if I had done java. This is probably because Java has so much needless verbosity that doesn't require much thought.
So each line with scala is actually doing something significant, I need to give it more attention. However, the fact that my program is >3k LOC means I am never trying to remember what classes do what, or why a method works the way it does, or any of the other problems you have when working on an extremely large code base.
I'm not sure I'd be able to grok a 10k LOC java project near as well as I do my 3k LOC Scala project, and I'm that much faster because of it.
the TL;DR is Scala that the advantage of less LOC is not that I can produce more faster, it's that I can comprehend more and fit more code into my head.
This is very true in my experience. Java programs can have a dizzying profusion of classes that seem completely gratuitous until you start thinking, "How would I do this in Java myself?" Then the classes start to make sense. You have to think in terms of implementation because the structure of the code is more complex than the solution expressed by the code.
One way to understand why is to see that when a language can't directly express the ideas a programmer devises to solve a problem, the gap must be made up by design patterns. To put it another way, code = concepts + design patterns. When you're trying to figure out the intent of code, what it actually does, you rearrange the equation to read, concepts = code - design patterns. You have to recognize the design patterns in the code and subtract them out to realize what the code actually does. The more design patterns your code uses, the less the code reflects the concepts, and the more work you have to do to isolate the concepts.
Well, the typing is not the reason we're looking at lines. With exceptions for outliers like APL, a line of code is generally a decent approximation to a unit of thoughtstuff.
Within any program, you have nitty gritty bits that deal with things like vector multiplication, and you have high and mighty bits that define the sequence of actions in the main loop. But writing code in those two places proceeds at a similar pace -- regardless of whether your function calls are doing a lot or a little. So it is with programming languages. Whether you can say a lot with a line of perl, or a little with a line of C, how much you have to think about that line, how much effort goes into organizing and composing a program from those lines . . . well, it turns out to be a pretty similar pace from language to language.
I personally think Scala's greatest complexity is in its type system. While algebraic data types are straightforward in themselves, Scala blends them with an object-oriented mindset more rigorous than Java's. In particular, Scala requires a solid understanding of covariance and contravariance — concepts unnecessary in Java or C++.
Right. The OO subtyping combined with the type system makes it complicated. I don't mind that, but another consequence is the limitedness of the type inference, which is kind of annoying.
Scala provides tools that allow highly competent developers to write very concise code, and if you give them those tools they will use them. Developers who are less competent may then have trouble understanding that code.
A wise co-worker of mine once said that it is just miserable when you have to maintain code written by someone smarter than you. So I strive to be concise and clear, but very rarely can I justify using arcane features and concepts to achieve that goal.
34 comments
[ 8.0 ms ] story [ 114 ms ] threadIt does have a powerful type system, and people do bizarre and unnatural things with it, but unless you're trying to do those things the complexity doesn't come into play.
(That's an interesting contrast with C++, where in theory all its features were designed to be orthogonal so that you don't need to know about exceptions or templates unless you're using them, but in practice in any nontrivial codebase you'll spend days staring at screenfuls of incomprehensible STL errors.)
It's interesting that you use the word "scare." It's a computer language. What's there to be afraid of?
Currently Scala is less affected, since there are not many users at this pont. I'd say this group consists of more sophisticated users, too.
I guess you haven't read very much C++ code. :P
With respect to the intent of its design versus the outcome, I can think of a few things that have been difficult for me in my playing with Scala. Implicit parameters, type parameters in general, especially the <: and >: operators, and some things like :/ and Ordering.by have confounded me quite a bit. The limited nature of its point-free style is also kind of difficult to get in -- IMO, they should have left that out entirely because two ways to do something is often worse than one. The distinction between = and = { at the end of method declarations, when you do and don't have to put parens on a no-arg method, and various other little quirks of the syntax are also a little annoying.
Don't get me wrong. I'd far rather program in Scala than C++ on a day to day basis. But, it seems quite large to me. It's a subjective measure, but that's my assessment as a professional C++ programmer and a beginner Scala programmer.
I find scala to be on par w/ Java in terms of complexity (more complex in some areas, more consistent in others).
Do people actually believe this? It seems to me the time spent typing actual lines of code is dwarfed by an order of magnitude by the time spent thinking between writing each line or method, cut and pasting for refactoring, etc. To borrow Fred Brooks' terminology, I think the most common languages at this point - certainly Java, Ruby, and Python - are at a high enough level that we spend an order of magnitude more time on fundamental rather than incidental complexity.
Ruby, Python, Java deal with the expression problem very poorly. The desire to write code generically is real so you have the mess of generics and people run to dynamic langs. In dynamic langs the desire to monkey-patch is real because you often need to extend objects whose source you do not control. In dynamic langs you often want an extension point, that does not a mean a list of methods to call, rather a list of method signatures to implement so I plug my own functionality in w/o reading through your source.
All this adds up to countless hours wasted.
These are real problems in real software today that current mainstream languages address very poorly.
http://www.reddit.com/r/scala/comments/ectzr/why_no_type_inf...
* anything CLOS-inspired: Common Lisp, Dylan, Factor, Clojure
* but also presumably anything with C++- or Clay-like (http://tachyon.in/clay/) generic programming, namely w.r.t generically using freely-overloadable functions. I believe Haskell achieves something similar to this using type classes.
And in static languages, you never need to extend objects whose source you do not control.
I must be doing it wrong - I've only been tempted to monkey patch once, and that was because the folks who controlled the code explicitly said to monkey patch in certain circumstances.
For example, as much as people (mostly) dislike creating code in Java, when I inherit code to maintain I love it when it is Java. It is just so straightforward with such limited ability to confuse or abstract things (as much as the many frameworks try) that I know I can always easily get to the bottom of any problem. Not to mention things like awesome debugging facilities and runtime analysis tools. With other languages I'm just lost once they reach any level of complexity because they all start doing "magic".
I hope that Scala perhaps retains a little of this through it's statically typed nature - but there's enough potential for "magic" there that I suspect it's partly lost. This is why I'm quite intrigued by Mirah (http://www.mirah.org/) ... but that is a long way from being mainstream enough to be useful in a wide range of situations.
If anything can make looking at java using a good great debugger still a nightmare, it's AOP and other such magic...
Well, it's interesting because my reply touches on that. I don't believe writing code is the hardest part of programming. Designing and thinking about code is the hard part. This was my reply:
I find the LOC discussion of Sala fascinating. In my time working on my Open Source Scala project, I've found that it does take me longer to type out each line of Scala compared to if I had done java. This is probably because Java has so much needless verbosity that doesn't require much thought.
So each line with scala is actually doing something significant, I need to give it more attention. However, the fact that my program is >3k LOC means I am never trying to remember what classes do what, or why a method works the way it does, or any of the other problems you have when working on an extremely large code base.
I'm not sure I'd be able to grok a 10k LOC java project near as well as I do my 3k LOC Scala project, and I'm that much faster because of it.
the TL;DR is Scala that the advantage of less LOC is not that I can produce more faster, it's that I can comprehend more and fit more code into my head.
One way to understand why is to see that when a language can't directly express the ideas a programmer devises to solve a problem, the gap must be made up by design patterns. To put it another way, code = concepts + design patterns. When you're trying to figure out the intent of code, what it actually does, you rearrange the equation to read, concepts = code - design patterns. You have to recognize the design patterns in the code and subtract them out to realize what the code actually does. The more design patterns your code uses, the less the code reflects the concepts, and the more work you have to do to isolate the concepts.
Within any program, you have nitty gritty bits that deal with things like vector multiplication, and you have high and mighty bits that define the sequence of actions in the main loop. But writing code in those two places proceeds at a similar pace -- regardless of whether your function calls are doing a lot or a little. So it is with programming languages. Whether you can say a lot with a line of perl, or a little with a line of C, how much you have to think about that line, how much effort goes into organizing and composing a program from those lines . . . well, it turns out to be a pretty similar pace from language to language.
Oh, wait.
I personally think Scala's greatest complexity is in its type system. While algebraic data types are straightforward in themselves, Scala blends them with an object-oriented mindset more rigorous than Java's. In particular, Scala requires a solid understanding of covariance and contravariance — concepts unnecessary in Java or C++.
A wise co-worker of mine once said that it is just miserable when you have to maintain code written by someone smarter than you. So I strive to be concise and clear, but very rarely can I justify using arcane features and concepts to achieve that goal.