3 ms·
>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?
by nousernamesleft 13y ago
>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.
- enjo 13y ago>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
- virtualwhys 13y ago> 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 ;-)
- nousernamesleft 13y ago>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.