top | item 38219311

(no title)

pleoxy | 2 years ago

It does slow some of us down. It's not really about terseness. I can write code that works on all primitives that might be sent down pretty easily. That code, sometimes is longer than limiting the inputs by types would be. I can also write code such that it only runs if the structure of the data is as required for that code to run, allowing for nulls or missing nested objects.

These two patterns allow you to write most code, type free, that gracefully handles anything you throw at it while always doing the right thing.

Making changes to such a system is easy and friction free.

Not many type advocates speak of the downsides of type systems, always pitching the net win and ignoring the actual cons.

When you refactor, make a change, or try to add new functionality, and end up fighting the type checker. That's friction to change you are experiencing and that experience is optional.

I get that having discipline in code patterns and the required robustness is a difficult ask at some organizations and some devs. In that circumstance it's better to have a minder in a type system that enforces base the conventions for everyone.

discuss

order

lolinder|2 years ago

> When you refactor, make a change, or try to add new functionality, and end up fighting the type checker. That's friction to change you are experiencing and that experience is optional.

I don't really see that as "fighting the type checker", I see it as the type checker doing its job and warning me of the places where my refactor broke things. The alternative isn't usually that my refactored code magically works, it's that I have to manually grep through the codebase looking for all the places where I might have broken something, and get runtime errors if I don't catch them all.

In that sense the experience of struggling to make a refactor work isn't optional—the choice you get is whether you want the compiler to assist you with it or not.

I realize there are exceptions for certain types of refactors to certain types of functions, but the vast majority of patterns I've ever seen in any codebase—static or dynamic—are patterns that are difficult to refactor without a type checker and trivial to do with one.

To be clear, there are other reasons to prefer dynamic typing, and I'm not trying to say you're wrong to prefer it, but you're not going to get very far trying to persuade a static types fan that refactoring of all things is better in the dynamic world.

Munksgaard|2 years ago

> When you refactor, make a change, or try to add new functionality, and end up fighting the type checker. That's friction to change you are experiencing and that experience is optional.

I'm not sure exactly what you're saying. If your language is strongly typed, you'll get type errors no matter what. The only difference is whether the type errors happen at compile time or run time. Let's take a hypothetical example:

Let's say I have a programming language called Foo. There are two ways to run programs written in Foo, using the interpreters A and B. A and B are identical, except for that fact that on startup, A will check that the given program is well-typed (static type checking), while B defers such checks to runtime (dynamic type checking).

Given a well-typed program X, I can run X with A or B without ever encountering a type error. Now, I make some changes, like you suggest, and I attempt to run it again. If the resulting code is not well-typed, I will immediately know when trying to run it with A, but with B I have to be lucky enough to hit the specific case that isn't well-typed.

If I understand you correctly, you're saying that you can easily make changes in a dynamic language without _ever_ causing run-time type errors. If that's the case, you would have _exactly_ the same experience whether you ran your code using A or B.

cglan|2 years ago

Making code that works on all primitives and accounting for nulls/empty each time is way more difficult than using a type system.

That’s the same argument people always use. “If you account for every case and also have 30 billion unit tests you can avoid all the problems”. The reality is, people don’t. They cut corners, they forget, or they simply make mistakes.

Not only that, debugging a system without types is a terrible experience, and IDEs don’t offer nearly the same level of refactoring support for untyped languages bc it gets very hard or impossible to infer what’s going on.

If it’s a personal project or a small script, untyped languages are fine. Any other scenario you should be using types