Scala allows you to restrict yourself to a much greater extent than many other languages. You could say use assembly for everything - there's nothing that assembly can't do, so in a sense assembly is more powerful than any other language.
For me the reasons I use Scala rather than Java/Python/etc. are the same reasons I would use Java/Python/etc. rather than assembly. To write code with the same guarantees as the core of my system would be theoretically possible in a "simpler" language, but it would be incredibly verbose: it would take longer to write and be much harder to maintain (because you'd have to keep a lot more in your head to understand each piece of functionality). If I weakened the guarantees (i.e. didn't keep track of as many possible side effects) I'd have a higher defect rate, especially when refactoring.
That's the small heart of a few projects, but I see a lot of merit in using the same language for your whole codebase: http://www.teamten.com/lawrence/writings/java-for-everything... . And Scala is actually a pretty nice language for one-off throwaway scripts where you don't care about tracking any effects or similar as well.
> To write code with the same guarantees as the core of my system would be theoretically possible in a "simpler" language, but it would be incredibly verbose: it would take longer to write and be much harder to maintain (because you'd have to keep a lot more in your head to understand each piece of functionality).
I could use the same reasoning to justify writing my code in Common Lisp instead. The thing about Turing-complete languages is that the only real dimmension of power is their expressiveness - i.e. how much boilerplate do you have to write to implement something (and therefore how much of that cruft other people have to deal with when trying to understand your code).
I therefore find this principle as applied to programming languages to be illogical.
It makes sense in non-Turing-complete languages though (configurations, DSLs) - because there by "least power" one means power in the computational sense. Accidentally making a language too powerful when it's not needed can lead to security issues.
> The thing about Turing-complete languages is that the only real dimmension of power is their expressiveness - i.e. how much boilerplate do you have to write to implement something
Have fun implementing your compile-time Common Lisp typechecker.
I mean, you can do it. I have friends implementing a typechecker for Python, and it works. As for me, I'm very happy to have someone else implementing/debugging/maintaining a typechecker for me so i can do other things with my time, like watch cats climb into boxes on youtube.
In practical terms I need a typechecker to write code at anything like the rate I do, with anything like the defect rate I achieve. But that's possibly sophistry. I agree the principle is not quite right (or at least not quite absolute) as stated; using extra power has a high but finite cost, it is occasionally worth using more power than you strictly need if the benefit is high enough.
I think there's a second dimension of languages to consider, namely how hard it is to write incorrect code. To some extent these goals are conflicting, in that preventing incorrect things often means disallowing some shorter correct solutions.
> I could use the same reasoning to justify writing my code in Common Lisp instead.
Maybe you should then. I find it too hard to restrict my code in lisps: if I want a certain part of my code to be in a DSL-like constrained sublanguage, there's no standardized way to express that, only ad-hoc macros.
> It makes sense in non-Turing-complete languages though (configurations, DSLs) - because there by "least power" one means power in the computational sense.
I think non-Turing-complete general-purpose languages are possible. I'm very excited for Idris.
> I find it too hard to restrict my code in lisps: if I want a certain part of my code to be in a DSL-like constrained sublanguage, there's no standardized way to express that, only ad-hoc macros.
There is a standardized way - via "ad-hoc" macros. Except they're not really more "ad-hoc" than using classes and traits in Scala is "ad-hoc".
Maybe 'aninhumer has a point - restricting the language is kind of the opposite goal of making it expressive/powerful.
> I think non-Turing-complete general-purpose languages are possible. I'm very excited for Idris.
> There is a standardized way - via "ad-hoc" macros. Except they're not really more "ad-hoc" than using classes and traits in Scala is "ad-hoc".
They're not standardized enough to have good common tooling around restricted embedded DSLs. If you use the type system to enforce restrictions around certain areas of Scala code, every Scala tool understands it. IME a lot of lisp programmers end up writing their own tool integration, because there is no standard for that kind of restriction (macros can be arbitrary code; in practice programmers restrict themselves to sensible macros, but in a way that isn't exposed to tooling).
> Idris is not Turing-complete? :o.
In practice there are escape hatches, but it's a total language: your function must come with a proof that it terminates.
> So, you can't express the programs that never terminate, but can you express all the programs that would terminate?
This gets philosophical - would the program "Y {f => x => if(x is a proof of the inconsistency of PA via the Goedel encoding) 0 else f(x+1) } 0" terminate? If you assume consistency of PA then no.
> Point in case, you probably shouldn't ever want to use a language for the specific feature that could express a non-deterministic program.
Well the mu operator or equivalent (informally, the inverse operator) is an extremely useful feature. Many useful programs can't be written strictly primitive recursively (as a trivial example, you can't compute the Ackermann function). I have hope that we can find more restricted versions of mu that let us express all the programs we want to, but that's a decidedly nontrivial problem.
I guess the point of the person you're responding to is that following the article's advice, Kotlin would probably be a better choice than Scala in most cases.
For example, Kotlin doesn't support higher kinded types so if your problem doesn't require highed kinded types, Kotlin would be a better fit than Scala since it's the "Least powerful language that will solve your problem".
Which will probably lead to the controversial claim that "All programs need higher kinds" followed by the realization that the perceived power of a technology is extremely subjective.
For me the reasons I use Scala rather than Java/Python/etc. are the same reasons I would use Java/Python/etc. rather than assembly. To write code with the same guarantees as the core of my system would be theoretically possible in a "simpler" language, but it would be incredibly verbose: it would take longer to write and be much harder to maintain (because you'd have to keep a lot more in your head to understand each piece of functionality). If I weakened the guarantees (i.e. didn't keep track of as many possible side effects) I'd have a higher defect rate, especially when refactoring.
That's the small heart of a few projects, but I see a lot of merit in using the same language for your whole codebase: http://www.teamten.com/lawrence/writings/java-for-everything... . And Scala is actually a pretty nice language for one-off throwaway scripts where you don't care about tracking any effects or similar as well.