News for hackers. Stuff that matters.
Re:Why we love Scala at Coursera by enjo on Tuesday February 18, 2014 @12:58PM (#7259706)
"Refactoring a statically typed language is easier than refactoring an interpreted one; modifying existing PHP, and even Python, is a difficult chore that engineers shy away from because modifications are likely to create more bugs than they fix."

Over the years I've worked pretty deeply with both static (C++/Java/Scala) and dynamic languages (Python/Ruby). I simply don't agree.

The biggest thing that contributes to refactorability has nothing to do with type safety. Instead unit test coverage, by a mile, is the thing that makes code easy to refactor. In my experience issues of type safety are rare. The same types of bugs are going to crop up in Scala, Python, Java, or even Fortran unless you have tests to help you discover those issues.

I've long felt that type safety is largely a solution to a problem that doesn't really exist. Not in a hugely meaningful way at least. Logic errors are generally independent of type issues, and as such it is code quality and unit test coverage, more than any specific language feature, that lead to highly flexible (and therefore refactorable) code.

Re:Why we love Scala at Coursera by NickPollard on Tuesday February 18, 2014 @01:02PM (#7259735)
> The biggest thing that contributes to refactorability has nothing to do with type safety. Instead unit test coverage, by a mile, is the thing that makes code easy to refactor

Type Safety is Unit Test Coverage.

Typing is a statically checked test of correctness of your program.

Languages like C give static typing a bad name. Types are not things like 'float', 'int', 'double'. Types are 'degrees', or 'radians'. Types are 'buy', or 'sell', 'price' or 'yield'. Types guarantee that your code executes as you expect, and prevent you from writing incorrect code in the first place.

Is it 100% effective? No. But there's a reason that high level statically typed languages (Scala, Haskell, OCaml) usually work correctly after they compile.

Re:Why we love Scala at Coursera by klibertp on Tuesday February 18, 2014 @02:10PM (#7260299)
> Types guarantee that your code executes as you expect, and prevent you from writing incorrect code in the first place.

If you write a Rational class and implement it's + method as

    def +(other: Rational):Rational = new Rational(0)
then no amount of static typing will save you. At least without dependent types.

Static typing gives you a knowledge about what kind of object you're dealing with without the need to run the code. It's almost completely useless if the "kinds" supported in type system are as broad as 'int', but it does help quite a lot if the type system let's you differentiate between cm and inches.

It still won't help you at all if you have a logic error - and this is where unit tests are valuable.

Personally I find a mixture of Typed Racket and Racket with contracts and unit tests to be the right thing when it comes to producing as error-free programs as possible. I was also pleasantly surprised with Smalltalk, which has no static typing, but because it runs all the time and every piece of code becomes "live" the moment it's written you can use introspection in place of static typing with very similar benefits.

Anyway, static typing is a valuable tool and one way of making software less wrong but it's important to know there are other tools and to use them all when it makes sense.

Re:Why we love Scala at Coursera by mercurial on Tuesday February 18, 2014 @04:02PM (#7261021)
> then no amount of static typing will save you. At least without dependent types.

Sure. Static typing also doesn't help with misunderstanding requirements, or a faulty test in a recursive function. But strong typing, especially in languages where there is no such thing as a NullPointerException, does eliminate entire class of problems. On the other hand, with dynamic languages, you are often a typo away from a runtime error.

Re:Why we love Scala at Coursera by brandonbloom on Tuesday February 18, 2014 @01:05PM (#7259764)
> usually work correctly after they compile

I still don't buy in to this trope.

Q: What is true of every single bug in production?

A: It passed both your type checker and your tests.

Re:Why we love Scala at Coursera by NickPollard on Tuesday February 18, 2014 @01:13PM (#7259830)
That's a tautology. By that reasoning, don't bother writing any tests, because all your bugs in production will get past them anyway!

My bugs got past my type-checker, but only 100 of them. You have 1000 because the 900 my type checker caught, your dynamic language didn't. Then you go and write unit tests for them, and spend a day writing code that my compiler generated automatically for me.

Re:Why we love Scala at Coursera by brandonbloom on Tuesday February 18, 2014 @01:48PM (#7260114)
> By that reasoning ...

My reasoning in no way implies that. I simply said that I'm sick of this argument that "if it compiles, it works!" Nobody who knows what they are talking about actually believes that, especially not people who design and build statically typed languages!

Re:Why we love Scala at Coursera by grey-area on Tuesday February 18, 2014 @01:27PM (#7259943)
If you can provide statistics on bugs being an order of magnitude higher in dynamic languages to back up your figures here, it would be a far more convincing argument. I'm sure type safety catches a few bugs and prevent some from being made, but does it catch as many as you think?
Re:Why we love Scala at Coursera by chimeracoder on Tuesday February 18, 2014 @01:31PM (#7259975)
Look at it the other way. In fact, you can do a blind test. Try writing in a strongly, (well[0]) statically-typed language for a while, and count the number of times your code fails to compile due to a type error.

Each of those would likely have been a runtime error in a language like Python.

Just earlier today, I had to write a short Python script (I normally write Go), and I was bitten by this. I'm used to the compiler telling me up-front when I try to concatenate a string and an integer, or when I misspell a variable name.

Yes, there are other ways around this (and proofreading your code before you write it is a good practice, in addition to tests). But static typing can make development much faster[1].

Even if you claim that you would have caught all of those bugs in unit/integration/system tests (which I simply don't believe - no real-world project has test coverage that's that good), it's much better to catch bugs at compile-time, because (unless you're writing C++) your tests take much longer to run than your code does to compile.

[0] I qualify this to rule out C, which has weak typing as well as memory management issues to complicate things, and Java, which just has a terrible type system period.

[1] In some sense this is all a moot point, because any difference in development speed and/or code correctness between statically-typed and dynamically-typed languages is dwarfed by one's familiarity with the languages in question. The only real way to test this directly would be to use a statically-typed language that allows disabling of all compile-time type checks as a compiler flag or pragma, but few languages do this in a way that'd be straightforward to do a meaningful blind test.

Re:Why we love Scala at Coursera by brandonbloom on Tuesday February 18, 2014 @01:47PM (#7260105)
Look at it the other way. In fact, you can do a blind test. Try writing in a strongly, (well[0]) dynamically-typed language for a while, and count the number of times your code fails at the REPL due to a type error.

Each of those would likely have been a compile time error in a language like Haskell.

Just earlier today, I was writing some C++ (I normally write Clojure) and I was bitten by this. I'm used to evaluating code in the REPL as I work, telling me up front when I try to concatenate a string and an integer, or when I misspell a variable name.

Yes, there are other ways around this (and proofreading your code before you write it is a good practice, in addition to tests). But dynamic typing can make development much faster[1].

Even if you claim that you would have caught all of those bugs in a type system (which I simply don't believe - no real-world project has types that are that precise), it's much better to catch bugs at run-time, because (unless you're writing Go) your compiler takes much longer to run than your REPL does to eval.

[0]: I qualify this to rule out Python, which has weak typing as well as mutability issues to complicate things, and JavaScript, which just has a terrible REPL period.

[1]: In some sense this is all a moot point, because any difference in development speed between statically-typed and dynamically-typed languages is dwarfed by one's familiarity with the languages in question. The only real way to test this would be to use a dynamically-typed language that has an optional type system as an external tool, luckily quite a few languages do this in a way that'd be straightforward to do a blind test (Typed Racket, Typed Clojure, Erlang w/ Dialyzer).

Re:Why we love Scala at Coursera by mercurial on Tuesday February 18, 2014 @04:13PM (#7261107)
> Each of those would likely have been a compile time error in a language like Haskell.

Why do you consider this a hindrance? Haskell has a lot of issues, but that's really not one of them. You can write a Haskell program and be relatively confident that it's going to work right in a way you simply won't be with, eg, Java. And you don't have to wait until compiling. With ghc-mod and vim/emacs configured, you'll be notified upon saving if you blew up something in the current file. You don't need to run your code in a REPL to find out about it, although GHCi is pretty good. You spend a lot less time figuring out what goes wrong at runtime, although I'll grand you that the tooling is poor enough that you have a bad time doing when it happens.

> I qualify this to rule out Python, which has weak typing

Excuse me? You rule out Python due to weak typing and mutability but disqualify Javascript due to its REPL? This must be sarcasm. I have no comment about Javascript's REPL (which one? node's?), but Python is most certainly not weakly typed, not in the way "weak typing" is commonly understood. As for mutability, they are comparable (except that Python has at least the good grace to throw an exception at runtime if you attempt to access an attribute which does not exist).

Re:Why we love Scala at Coursera by vilhelm_s on Tuesday February 18, 2014 @02:05PM (#7260261)
You can have a REPL in a statically typed language too---Haskell has one.
Re:Why we love Scala at Coursera by brandonbloom on Tuesday February 18, 2014 @02:11PM (#7260312)
GHC's REPL wraps all expressions in a giant do-block with an IO monad. It's practically useless without the meta-language of the colon commands. That said, truly modern versions of GHC have deferred type checking for REPL use, which is impressive, useful and, ultimately, a simple emulation of a dynamic language.

Never mind that not even Python or Ruby, and especially not JavaScript, provide sensible useful REPLs with sane code reloading semantics.

People who shit on crappy type systems turn around and then shit on crappy REPLs in broken dynamic languages. I'd take a statically typed language over a language with a bad REPL any day.

Re:Why we love Scala at Coursera by singingcheese on Tuesday February 18, 2014 @02:18PM (#7260369)
> You can have a REPL in a statically typed language too---Haskell has one.

And so does Scala...

Re:Why we love Scala at Coursera by cryptolect on Wednesday February 19, 2014 @12:47AM (#7262032)
I tried Go after a few years of Ruby, and compile-time errors is what annoyed me the most. Bzzt that variable is defined but not in use, fail. Bzzt that function is defined but not used, fail. Bzzt that library is included but not used, fail. Felt like I was getting a rap across the knuckles with each failure as I was trying to learn Go.

The try/fail/modify/repeat cycle of REPL-driven-development is what appeals to me. I "get" the value of strongly typed languages, but I'd prefer to opt-in to strictness, rather than have it forced upon me.

Re:Why we love Scala at Coursera by virtualwhys on Wednesday February 19, 2014 @03:02AM (#7262405)
Interesting, felt the same way, and then something changed, rather than feeling punished by the type checker, the type checker became my ally, teaching me about my mistakes at compile time.

Other than for quick scripts I have no interest in dynamic languages now, fully converted to the Typed side ;-)

Ruby and Scala are quite similar in some ways: terse syntax, functional, MOP capable (implicits), mixins (traits), etc., but yes, you have to prove to the type checker that your intentions are correct/sound.

Re:Why we love Scala at Coursera by thesz on Wednesday February 19, 2014 @07:56AM (#7263348)
Haskell will give you REPL-driven development and strong typechecking (an optional one in the last haskell compiler).

BTW, Go is not that strongly typed. It seems Google engineers don't like strongly typed languages.

Re:Why we love Scala at Coursera by nousernamesleft on Tuesday February 18, 2014 @03:14PM (#7260725)
>In some sense this is all a moot point, because any difference in development speed between statically-typed and dynamically-typed languages is dwarfed by one's familiarity with the languages in question

I dunno, I have 11 years of python experience, and almost a year of haskell experience. I am more productive in python when doing small (<100 lines) scripting type tasks. But I am noticeably more productive in haskell when writing bigger things. Haskell has a relatively crappy web ecosystem, yet I'm still more productive with snap+postgresql-simple+digestive-functors then I have ever been with any python framework (from zope way back in the day to django and flask). Tasks that are more skewed to haskell's strengths like highly concurrent network servers make the difference even more pronounced.

Re:Why we love Scala at Coursera by basman on Tuesday February 18, 2014 @02:23PM (#7260414)
So yes, they would be runtime errors in Python. But that's not such a catastrophe, actually. The way I write Python is by being in an IPython shell, writing short functions, unit-testing them as I go. So the development-time cost of those runtime errors is not very high, and in my experience offset by the flexibility and interactiveness. Writing in a functional style without much mutable state is really the thing that I find saves development/debugging time.
Re:Why we love Scala at Coursera by sampo on Wednesday February 19, 2014 @12:20PM (#7264695)
> The way I write Python is by being in an IPython shell, writing short functions, unit-testing them as I go.

One can write Scala the same way in a Scala shell.

Re:Why we love Scala at Coursera by kasey_junk on Tuesday February 18, 2014 @01:05PM (#7259768)
Not to start a needless back and forth, but I've worked in both static and dynamic languages on projects large and small as well. I do believe that unit tests are the biggest improvement by a long stretch for re-factorability, but a good type system simply eliminates whole swaths of error cases, and modern systems don't require a lot of overhead either.

Another advantage for some strongly typed languages are the complex, yet safe refactorings they enable automatically by a good IDE. This is not universal though, and is a serious downside to picking Scala over Java.

Re:Why we love Scala at Coursera by crystaln on Tuesday February 18, 2014 @01:12PM (#7259816)
Type safety dramatically reduces the number of unit tests required. Since unit tests often depend on the structure of code, that reduces the amount of rewritten and modified test code and the stability of the tests over refactors, which in turn must make refactoring easier.
Re:Why we love Scala at Coursera by lbarrow on Tuesday February 18, 2014 @01:21PM (#7259890)
If you write unit tests that make assertions that would be caught by a type checker, you're writing bad tests.
Re:Why we love Scala at Coursera by crystaln on Tuesday February 18, 2014 @01:45PM (#7260086)
If you don't understand why a dynamic language needs more tests than a typed one, you probably haven't worked with typed languages. The difference is dramatic and clear.

Just one example, code coverage must be 100% for a dynamic language in order to avoid runtime catastrophic failures due to simple typos - like letter transposition. Sure, 100% test coverage is a nice goal, but it's rarely met. In a typed language, you can be 100% sure this won't happen with zero tests.

Re:Why we love Scala at Coursera by jcrites on Tuesday February 18, 2014 @02:06PM (#7260265)
That's a great point!

It's also what makes refactoring so much easier. If I need to rename a method obj.f() to obj.g(), then I can do so safely knowing that no lingering references to f() remain in my code base (else they would fail to type as f() is no longer a valid method).

As you say, 100% code coverage is unrealistic. Having maintained large applications in both static and dynamically typed languages, I feel that statically typed programs are far easier to manage for this reason - that if my code compiles then it means there exist no errors of a certain trivial class, such as typos and references to classes or methods that have been removed.

There are still other errors to worry about, but mitigating those errors can be done effectively without needing to approach 100% code coverage.

Re:Why we love Scala at Coursera by cia_plant on Tuesday February 18, 2014 @01:28PM (#7259955)
All unit test assertions can be caught by a type checker.
Re:Why we love Scala at Coursera by crystaln on Tuesday February 18, 2014 @01:46PM (#7260098)
Assuming you are sarcastically dismissing typed language defenses, as if people promoting typed languages have the position that tests are not necessary.
Re:Why we love Scala at Coursera by cia_plant on Tuesday February 18, 2014 @02:01PM (#7260220)
No, I'm simply stating the fact that there are type systems capable of encoding assertions.
Re:Why we love Scala at Coursera by basman on Tuesday February 18, 2014 @01:42PM (#7260064)
Your type checker catches array indexing bugs? Impressive.
Re:Why we love Scala at Coursera by virtualwhys on Tuesday February 18, 2014 @02:17PM (#7260362)
No, but Scala encourages FP, so when you:

    val fooList = List(1,2,3)
    fooList.map(...)
you'll _never_ hit the types of bugs you're referring to.

If you fooList(3), then of course you're hosed, but that's not the type checker's fault ;-)

Re:Why we love Scala at Coursera by kasey_junk on Tuesday February 18, 2014 @02:21PM (#7260393)
I don't agree even with the sentiment of the original post, but there is an argument that while you can't get rid of array indexing bugs with a type checker (contracts might help here) you can design your collection types such that things like indexing above or below an array are compile time caught, as is indexing into the "wrong" array location.

Whether it is worth the trouble to do this in the type system probably depends on how good your language's type system is and how expensive array indexing bugs are to catch/fix.

Re:Why we love Scala at Coursera by AnimalMuppet on Tuesday February 18, 2014 @03:27PM (#7260809)
Actually, in the original (circa 1968) Pascal, it did.

In Pascal, the size of an array was part of the type of the array. IIRC, You simply could not write an array index out of bounds bug. This made it a somewhat reasonable choice for a medical device, where an array index out of bounds could be catastrophic. However...

You also could not create a variable-sized array. There was no way even to talk about the type of such an object. (Yes, I ran into that professionally once.) I think this is why Turbo Pascal (and maybe others?) softened that.

Re:Why we love Scala at Coursera by nousernamesleft on Tuesday February 18, 2014 @03:23PM (#7260787)
Re:Why we love Scala at Coursera by kailuowang on Tuesday February 18, 2014 @01:27PM (#7259944)
I worked deeply with both static and dynamic languages as well. I do feel that it's easier to refactor in scala than ruby, especially in large projects.

In ruby, you have to have close to 100% test coverage because if you don't you can't have any confidence when you refactor. For example, in ruby project, even a simple delegation call needs to be tested, otherwise you may break it without knowing it when you rename the method delegated to.

You don't need to write such test in a Scala project because there is no business logic in a simple delegation and the compiler will check the rename for you, actually the IDE will do the rename refactor perfectly for you.

In general, some of the unit tests devs wrote in Ruby projects are not to test against business logic but to test type matching. For type related refactoring, they actually have to refactor both the code and unit tests. The dilemma here is that if you are changing your unit tests, how confident you are that they are still covering your refactor?

Re:Why we love Scala at Coursera by frowaway001 on Tuesday February 18, 2014 @01:57PM (#7260195)
> Logic errors are generally independent of type issues

Eh ... what?! Is that some kind of joke?

https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspon...

Re:Why we love Scala at Coursera by spo81rty on Tuesday February 18, 2014 @01:03PM (#7259749)
I've only used static languages and therefore never had to make unit tests. Unit tests should exists for certain business rules, not every line of code.
Re:Why we love Scala at Coursera by nnq on Tuesday February 18, 2014 @01:58PM (#7260201)
...sorry to have to ask, but this was sarcasm, right?
Re:Why we love Scala at Coursera by m_gol on Tuesday February 18, 2014 @02:56PM (#7260635)
Lol, never? Types won't check your whole business logic, it's irresponsible to nog write them (unless you're doing something really small).
Re:Why we love Scala at Coursera by nathanvanfleet on Tuesday February 18, 2014 @09:37PM (#7261488)
> I've long felt that type safety is largely a solution to a problem that doesn't really exist.

Sure, assuming you never have to evaluate, convert, merge or do anything with that data. Then you might have some issues when you have expectations on the behaviours of those actions.

Re:Why we love Scala at Coursera by michaelochurch on Tuesday February 18, 2014 @01:17PM (#7259859)
My preferred language these days is Clojure, which is dynamic, but I don't agree that most errors have nothing to do with type safety.

Most errors are fairly random. There isn't a pattern to them. Misspellings, misconceptions. Whether your type system catches them depends on the strength of your type system in addition to how you represent things. (Hashmaps vs. records, whether the get call on a Hashmap returns a nil value or an error when the key's not found.)

A strong type system makes it likelier that errors are caught earlier. This may or may not be justified, depending on the application. For some problems, the reduced error-to-failure distance is considerable and it's a huge win.

Re:Why we love Scala at Coursera by ChikkaChiChi on Tuesday February 18, 2014 @01:10PM (#7259803)
Am I missing a big problem with dynamic typing? Wouldn't clearly defined naming conventions solve part of the problem?
Re:Why we love Scala at Coursera by okaram on Tuesday February 18, 2014 @01:20PM (#7259884)
They't need to be not just clearly defined but enforced; wouldn't it be cool if we could write a tool that automatically enforces them ? hmmm ... :)
Re:Why we love Scala at Coursera by cgrubb on Tuesday February 18, 2014 @01:19PM (#7259870)
To put some meat on the discussion, what would be an example of a logic error which would be introduced by a refactoring?
Re:Why we love Scala at Coursera by nousernamesleft on Tuesday February 18, 2014 @03:04PM (#7260685)
>Over the years I've worked pretty deeply with both static (C++/Java/Scala) and dynamic languages (Python/Ruby). I simply don't agree.

How did you use scala? Did you write java code in scala as most people with a C++/C#/java background do? Because that would completely explain the rest of your post. In particular, this statement:

>In my experience issues of type safety are rare

I've been doing pretty exploratory, "refactor the hell out of it every other day" kind of coding lately. I would literally rather not program than have had to do it in a language other than haskell. If I were to record this process, I am sure I would come up with several hundred type errors being caught over the course of a week.

>The same types of bugs are going to crop up in Scala, Python, Java, or even Fortran unless you have tests to help you discover those issues.

The obvious example of that being a bad assumption is that static type systems can completely eliminate unexpected NULL errors. It can eliminate "oops I used the count as the X co-ord by mistake" style errors. It can eliminate a huge class of errors that java programmers don't recognize are in fact type errors.

>Logic errors are generally independent of type issues

Which is why it is so nice to let the computer deal with type errors and be able to concentrate on logic errors instead of constantly having to worry about type errors manually.

Re:Why we love Scala at Coursera by enjo on Wednesday February 19, 2014 @01:59AM (#7262260)
>How did you use scala? Did you write java code in scala as most people with a C++/C#/java background do? Because that would completely explain the rest of your post.

Nope.

My issue here is that types, once defined, rarely change in any significant fashion. Refactoring is (generally) an exercise in mutation of logic, not so much the underlying types. When types do change the code that operates on them drastically changes as well. We're no longer refactoring at that point, we're re-writing and then the issues more or less disappear.

>The obvious example of that being a bad assumption is that static type systems can completely eliminate unexpected NULL errors.

What? In Scala it is perfectly possible to pass an uninitialized reference to a piece of code. The type checker most definitely isn't going to catch that. It can merely verify that the reference itself is of the right type. This is actually a common runtime error in those languages.

>It can eliminate "oops I used the count as the X co-ord by mistake" style errors.

Just as long as the count and the X co-ord are of different types. Which I'd guess isn't always the case.

> It can eliminate a huge class of errors that java programmers don't recognize are in fact type errors.

I will concede that static type systems do catch some errors that aren't caught by dynamic languages. My belief is that the class of errors they catch are among the most trivial, and most easily caught in testing (unit-testing or otherwise). Thus I simply don't see big gains in either runtime correctness or refactorability. Maybe slight ones, but nothing worth the loss of expression provided by more dynamic languages. This is true of even softer type systems such as Hindler-Milner (although type inference continues to improve, there might be some middle ground here to explore in the future).

There is no doubt some philosophy at play here. The discussion here is much broader than refactoring alone. I for one find that giving up some formal proof about the correctness of the program is worth the freedom dynamic languages provide.

I'll leave my favorite quote on the subject:

"Static type checking limits programs to only expressing things that the static type system can prove are OK, as opposed to expressing things that the human programmer believes are OK. That's the source of both the expressiveness loss with statically checked languages, and the class of runtime type errors which are unique to dynamically checked languages." - Anton van Straaten

Re:Why we love Scala at Coursera by virtualwhys on Wednesday February 19, 2014 @03:20AM (#7262460)
> What? In Scala it is perfectly possible to pass an uninitialized reference to a piece of code.

NULLs are a non-issue; that's what Option and FP constructs (map, flatMap, etc.) are for.

> I will concede that static type systems do catch some errors that aren't caught by dynamic languages.

Dynamic languages catch NO errors at all, period. You yourself must maintain your own adhoc type checker (unit tests, with 100% coverage) in order to prevent the class of errors that statically typed languages catch from manifesting at runtime.

That's a great quote, actually backs Scala given that you give up pretty much nothing in terms of expressiveness (compared to Ruby, Python, Groovy, etc.) while retaining all of the safety ;-)

Re:Why we love Scala at Coursera by nousernamesleft on Wednesday February 19, 2014 @09:46AM (#7263819)
>My issue here is that types, once defined, rarely change in any significant fashion. Refactoring is (generally) an exercise in mutation of logic, not so much the underlying types. When types do change the code that operates on them drastically changes as well. We're no longer refactoring at that point, we're re-writing and then the issues more or less disappear.

That is the exact opposite of my current experience. I'm changing types constantly. As I flesh out more code, I realize I needed to pass an (Account, Client) not just a Client. Now the compiler tells me every single line in every single file where I need to fix the code to handle that.

>What? In Scala it is perfectly possible to pass an uninitialized reference to a piece of code

Because scala has to make bad concessions to java compatibility. Scala itself is fine, but java opens the door to problems. I did not say scala accomplished this, I said static type systems can. Use ocaml or haskell.

>Just as long as the count and the X co-ord are of different types. Which I'd guess isn't always the case.

But you control the types, that is the point. So if you choose not to use the type system, then obviously it protects you from very little. That is not a problem with the type system, it is a problem with you. You could write a program using only strings if you really hated yourself, and you would thus get absolutely no benefit from the type system. But nobody would be silly enough to blame the type system.

>My belief is that the class of errors they catch are among the most trivial, and most easily caught in testing (unit-testing or otherwise). Thus I simply don't see big gains in either runtime correctness or refactorability. Maybe slight ones, but nothing worth the loss of expression provided by more dynamic languages.

I do not believe your earlier claim to not have been writing java in scala now. If you think there is a "loss of expression", you do not have experience with a modern statically typed language.

>"Static type checking limits programs to only expressing things that the static type system can prove are OK

And if you have no idea how much you can express with the type system, then you draw bad conclusions from that.