4 ms·
> we want code that's expressive enough to do what we want, while being constrained enough to not do what we don't I don't think that's an ideal mental model.
by addaon 1y ago
> we want code that's expressive enough to do what we want, while being constrained enough to not do what we don't
I don't think that's an ideal mental model. Code in any (useful) language can do what you want, and can not do what you don't want. The question is how far that code is from code that breaks those properties -- using a distance measure that takes into account likelihood of a given defect being written by a coder, passing code review, being missed in testing, etc. (Which is a key point -- the distance metric changes with your quality processes! The ideal language for a person writing on their own with maybe some unit testing is not the same as for a team with rigorous quality processes.) Static typing is not about making correct code better, it's about making incorrect code more likely to be detected earlier in the process (by you, not your customers).
- weavejester 1y agoI was being glib, so let me expand on what I said a little. By 'constraint' I mean something the language disallows or at least discourages. Constraints in software development are generally intended to eliminate certain classes of errors. Static typing, immutability, variable scoping, automatic memory management and encapsulation are all examples of constraints, and represent control that the language takes away from the developer (or at least hides behind 'unsafe' APIs). By 'expressiveness' I mean a rough measurement of how concisely a language can implement functionality. I'm not talking code golf here; I mean more the size of the AST than the actual number of bytes in the source files. Adding constraints to a language does not necessarily reduce its overall expressiveness, but static typing is one of those constraints that typically does have a negative effect on language expressiveness. Some will argue that static typing is worth it regardless, or that this isn't an inherent problem with static typing, but one that stems from inadequate compilers.
- owlstuffing 1y agoThat is a pretty fair assessment, and I'll avoid the nominal v. structural subject, but in my experience the difference between static and dynamic typing comes down to metaprogramming. For instance, much of Python's success stems from its dynamic metaprogramming capabilities. By contrast Java's limitations wrt metaprogramming prevent it from competing in areas such as ML and data science / analytics. One of the most untapped and misunderstood areas in language design is static metaprogramming. Perhaps this is what you meant by "inadequate compilers", but there is no reason why Java can't provide compile-time metaprogramming. With a comprehensive implementation it can compete directly with dynamic metaprogramming, with the benefits of static analysis etc., which is a game changer.
- OptionOfT 1y agoReading your previous comments made me read 'glib' as 'g-lib', the GTK one.
- hakunin 1y agoEverything has a cost. If you had to pick between "write 99% correct code in 1 week" vs "write 100% correct code in 1 year", you probably would pick the former, and just solve the 1% as you go. It's an absurd hypothetical, but illustrates that it's not just about correctness. Cost matters. What often annoys me about proponents of static typing is that they sound like it doesn't have a cost. But it does. 1. It makes syntax more verbose, harder to see the "story" among the "metadata". 2. It makes code less composable, meaning that everything requires complex interfaces to support everything else. 3. It encourages reuse of fewer general types across the codebase, vs narrow scoped situational ones. 4. It optimizes for "everything must be protected from everything" mentality, when in reality you only have like 2-5 possible data entries into your system. 5. It makes tests more complex to write. 6. Compiled languages are less likely to give you a powerful/practical REPL in a live environment. For some, this loses more than it gains. Also, albeit I haven't seen this studied, human factor probably plays bigger role here than we realize. Too many road signs ironically make roads less safe due to distraction. When my code looks simple and small, my brain gets to focus better on "what can go wrong specifically here". When the language demands I spend my attention constructing types, and add more and more noise, it leaves me less energy and perspective on just taking a step back and thinking "what's actually happening here".
- jstimpfle 1y agoI agree 100÷ with this. I've had the same concerns for a long time but rarely see them expressed with such eloquence.
- zigzag312 1y agoCost matters, but in my experience there's more to this story. It's more like this: "write 99% correct code in 1 week and then try to fix it as you go, but your fixes often break existing things for which you didn't have proper tests for. It then takes you total of 2 years to finally reach 100% correct code." Which one do you choose? It's actually not as simple as 1 year vs 2 years. For a lot of stuff 100% correctness is not critical. 99% correct code can still be a useful product to many, and to you it helps you to quickly validate your idea with users. However, the difference between static and dynamic typing is not that drastic, if you compare dynamic typing to an expressive statically typed language with good type inference. Comparing, for example, Python to C++ is not really fair as there are too many other things that make C++ more verbose and harder to work with. But if we compare Python to for example F# or even modern C#, the difference is not that big. And dynamic typing has a costs too, just different. 1. "Story" can be harder to understand without "metadata" due to ambiguity that missing information often creates. It's a delicate balance between too much "metadata" and too little. 2. Too much composability can lead to bugs where you compose wrong things or in a wrong way. Generic constraints on interfaces and other metaprogramming features allow flexible and safer composability, but require a bit more tought to create them. 3. Reuse is similar. No constraints on reuse, doesn't protect you from reusing something in corner case where it doesn't work. 4. (depends on how you design your types) 5. Dynamic languages require you to write more tests. 6. F# and C# for example both have REPL. Quality statically typed language is much harder to create and require more features to be expressive, so there are less of them or they have some warts and they are harder to learn. It's a game of tradeoffs, where a lot of choices depend on a specific use case.