Live data from Hacker News

The type system is a programmer's best friend

dusted.codes

381–390 of 467 posts

Re: The type system is a programmer's best friend

#381

Earlier quoted context omitted.

The above, while carefully tailored to tickle HN biases, has no connection with reality. Types are exactly equally as "traceable" in C++ as in Rust.

This is offensive. To suggest my opinion has no connection to reality? Read what I wrote carefully. I'm not talking about type errors. I'm talking about errors in GENERAL. Your comment is carefully tailored to incite flame war. You represent HN bias at it's finest, reading something and giving a casual dismissal without really interpreting it.

We get that you hate C++.

But the topic here is type systems, and Rust's is more like C++'s than any other, and vice versa. C++ compilers used to have error messages that were hard to interpret, but competition between compilers has improved them.

Meanwhile, C++ itself has changed enabling better error messages because it is clearer what your code is trying to do.

Re: The type system is a programmer's best friend

#382
post #379

Earlier quoted context omitted.

Replace it with helmets if you want a more controversial option.

How do helmets change the argument? Like seat belts, you can choose to wear or not wear a helmet independent of all other factors. The motorcycle or bicycle is exactly the same regardless of whether you're wearing a helmet. Also, everyone understands the benefits of a helmet. The benefits don't make everyone wear a helmet, but everyone is clear about why there are helmets.

It does, wearing helmets means you need to carry them around and store them, and it can ruin your hairstyle. People who can balance the tradeoffs make mostly reasonable decisions ("I write large programs with the support of a type system and eschew it for small scripts", "I will probably be OK without a helmet just biking slowly between two buildings at work") but some people will never accept the upsides as being worth it.

Re: The type system is a programmer's best friend

#383
post #379

Earlier quoted context omitted.

How do helmets change the argument? Like seat belts, you can choose to wear or not wear a helmet independent of all other factors. The motorcycle or bicycle is exactly the same regardless of whether you're wearing a helmet. Also, everyone understands the benefits of a helmet. The benefits don't make everyone wear a helmet, but everyone is clear about why there are helmets.

It does, wearing helmets means you need to carry them around and store them, and it can ruin your hairstyle. People who can balance the tradeoffs make mostly reasonable decisions ("I write large programs with the support of a type system and eschew it for small scripts", "I will probably be OK without a helmet just biking slowly between two buildings at work") but some people will never accept the upsides as being wo…

> some people will never accept the upsides as being worth it.

How is this any different from the selt belt case? "(1) believe they'll beat the statistics, and thus no statistical argument will convince them or (2) value their "freedom" a lot more than they value their own lives"

Would you really expect an article "The helmet is a biker's best friend" to convince them?

Everyone knows that a helmet helps prevent head injuries. That doesn't need to be explained. Whether the tradeoff of messing up your hair or whatever is worth it is up to the individual to decide, but there's nothing complex about the decision that needs an academic discussion.

Re: The type system is a programmer's best friend

#384

Earlier quoted context omitted.

If it does matter to the conversation then it's evidence supporting my point. I'm saying type checking isn't a key differentiator between something like JS/ruby/python vs. C++. You're implying the GC is the key differentiator. If you're saying that you CAN'T compare the python to C++ because of the GC then I disagree. GC only stops memory leaks. That is not the most frequent error that happens with C++. Clearly if yo…

GC is not just for memory leaks, but memory safety in general. It also enables several paradigms that are extremely difficult to get right without memory safety. In order to have a proper comparison, you should control for variables that are irrelevant to the experiment. In this case, you want to look at the effect of typing, so you should control for GC. Which is why you should compare python to other GC'd static la…

>GC is not just for memory leaks, but memory safety in general.

No this is not true. Memory safety and memory leaks are different concepts. You can trigger a memory leak without violating memory safety. In fact a memory leak is not really an error recognized by an interpreter or a compiler or a GC. It is a logic error. A memory leak is only a leak because you interpret it as a leak. Otherwise the code is literally doing what you told it to do. It's similar to a logic error. I mean think about it, the interpreter can't know whether you purposefully allocated 1gb of memory or whether you accidentally allocated it.

Memory safety on the other hand is protection against violation of certain runtime protocols. The interpreter or runtime knows something went wrong and immediately crashes the program. It is a provable violation of rules and it is actually not open to interpretation like the memory leak was.

See python: https://docs.python.org/3/library/gc.html. You can literally disable the GC (during runtime) and the only other additional crash error that becomes more frequent is OOM. The GC literally just does reference counting and generational garbage collection... that's it.

I can tell you what makes python MORE memory safe then C++. It's just an additional runtime checks that are not zero cost.

  x = [1,2]
  print(x[2])
The above triggers an immediate exception that names the type of error (out of bounds) and the exact line that triggered it. This error will occur regardless of whether or not you disabled the GC. It happens because every index access to a list also checks against a stored length. If you're above that length it raises an exception. It's not zero cost but it's more safe.

For C++:

   int x[] = {1,2};
   std::cout
This triggers nothing. It will run even though index 2 is beyond the bounds of the array. There is no runtime check because to do so would make the array data structure not zero cost. This is what happens during buffer overflows. It's one of the things that makes C++ a huge security problem.

Let's look at the type issue.

    def head(input_list: List[int]) -> Optional[int]:
        return input_list[0] if len(input_list) > 0 else None

    x: int = head(2)
--------------------

    #include 
    #include 
    std::Optional head(const std::vector& input_list){
         return (input_list.length() > 0) ? input_list[0] : std::nullopt; 
    }
    
    int main(){
       auto x = head(2)
       return 0;
    }

Both pieces of code are identical. Python is type annotated for readability (not type checked). But both literally produce the same error messages (wrong input type on the call to head). Both will tell you there's a type error. It's just python happens at runtime and C++ happens at compile time. C++ has a slight edge in the fact that the error is caught as a static check. But this is only a SLIGHT advantage. Hopefully this example will allow you to see what I'm talking about as both examples literally have practically the exact same outcome of a type error. A minority of bugs are exclusively caught with type checking because runtime still catches a huge portion of the same bugs... and in general this is why overall C++ is still MUCH worse in terms of usability then python despite type checking.

Re: The type system is a programmer's best friend

#385

Earlier quoted context omitted.

Your argument makes no sense. I say the type checker is not the key differentiator then you say for python the key differentiator is the garbage collector. So that makes your statement contradictory. You think type checkers are important but you think python works because of garbage collection. Either way I'm not talking about the implementation of the language. I'm talking about the user interface. Why is one user i…

No contradiction, really, it's just that we are talking about two different programming goals: I emphasize the goal of producing well-behaved software (especially when it comes to large software systems), while you emphasize the goal of producing software in an easier (more productive) manner. For my goal, a strong type system is a key differentiator. For your goal, a garbage collector is a key differentiator. The di…

>but I suspect your assumption that "100,000 lines of code of python tend to be safer and more manageable then 100,000 lines of C++" might be wrong.

I can give you my anecdotal experience on this aka "authoritative" in your words. I am a really really really good python engineer with over a decade of experience. For C++ I have 4 years of experience, I would say I'm just ok with it.

Python is indeed safer then C++. Basically when you check for type errors at runtime, you actually easily hit all reasonable use cases pretty quickly. This is why unit testing works in reality even though your only testing a fraction of the domain.

Sure this isn't a static proof but in Practical terms static type checking is only minimally better then run-time type checking. You can only see this once you have extensive experience with both languages and you see how trivial type errors are. Practicality of technologies isn't a property you can mathematically derive, it's something you get a feel for once you've programmed enough in the relevant technologies. It helps you answer the question of "How often and how easy do type errors occur uncaught by tests?" Not that much more often and not hard at all to debug.

The thing that is actually making C++ less usable are the errors outside of type checking. The memory leaks, the segfaults, etc. The GC basically makes memory leaks nearly impossible and python doesn't have segfaults period. What python does is fail fast and hard once you write something outside of memory bounds. Basically it has extra run time checks that aren't zero cost that make it much much more safe.

All of this being said, I am talking about type-less python above... when I write python, I am in actuality a type Nazi. I extensively use all available python type hints including building powerful compositional sum types to a far more creative extent then you can with C++. I am extremely familiar with types and python types. I have a very detailed viewpoint from both sides of the spectrum from both languages. That's why I feel I'm qualified to say this.

>No contradiction, really, it's just that we are talking about two different programming goals: I emphasize the goal of producing well-behaved software (especially when it comes to large software systems), while you emphasize the goal of producing software in an easier (more productive) manner.

I'm actually partly saying both. Python is both easier and more well-behaved and more safe. The "well-behaved" aspect has a causal relationship to "easier". It makes sense if you think about it. Python behaves as expected more so then C++.

Literally I repeat: Python (even without types) is categorically safer then C++. I have a total of 14 years of experience in both. I would say that's enough to form a realistic picture.

Re: The type system is a programmer's best friend

#386

Types got a bad wrap because of C++. There was a strange dichotomy between languages like python/javascript and C++. If type systems were so good why was it easier to program with javascript and python then with C++? People got confused and promoted dynamically typed languages as better. What many people didn't realize was that C++ was hard DESPITE the type system, not because of it. This was soon rectified with type…

> Whether the error occurs at runtime or compile time is besides the point. Compile time adds a bit of additional safety, but really if an error exists, it will usually trigger at some point anyways. Well, if the error is at compile time, there's no chance that code makes it to production and affects customers. If the error is at runtime, you need to have tested that edge case and if you haven't, there could be custo…

I agree with you, but I'm saying things from a practicality standpoint.

Let me put it this way. If you have type checking I'm saying that from my anecdotal experience you probably catch 10% more errors then you would normally catch before deployment. The reason is you're bound to run runtime tests anyway and these tests cause you to correct all your little type bugs anyway.

And this isn't even errors you would'nt've caught. It's just about catching the errors earlier.

That's it. Catching 10% of errors after deployment rather then before... that is not a huge deal breaker. Type checking benefits are marginal in this sense. Yes agreed it's better, but it's not the deal breaker.

I'm trying to point out the deal breaker feature. The delta difference that causes python to be BETTER then C++ in terms of usability and safety. Type checking is a negligible factor in that delta is basically my thesis. This is subtle. A lot of people are going on tangents but that is my point.

Re: The type system is a programmer's best friend

#387

Earlier quoted context omitted.

This is offensive. To suggest my opinion has no connection to reality? Read what I wrote carefully. I'm not talking about type errors. I'm talking about errors in GENERAL. Your comment is carefully tailored to incite flame war. You represent HN bias at it's finest, reading something and giving a casual dismissal without really interpreting it.

We get that you hate C++. But the topic here is type systems, and Rust's is more like C++'s than any other, and vice versa. C++ compilers used to have error messages that were hard to interpret, but competition between compilers has improved them. Meanwhile, C++ itself has changed enabling better error messages because it is clearer what your code is trying to do.

> We get that you hate C++.

You just can't stop can you? There's really zero need to say this other then trying to be an ass. I don't hate C++. I chose to write C++ as my day to day job after quite some time doing python because it's a challenge. There is no hate. But I have no loyalty to the language either. That is my way. No loyalty and therefore no bias. C++ is definitively less safe then python. This is fact and that is why I program in it.

I am also talking about type systems. Not just C++. However I AM using C++ as an example. It is flawed despite a stronger type system then python. The paradoxical dichotomy between the two languages is the quintessential example of my point. The type system is not essential to safety. It's an illusion. Types are simply sugar on top of it all because in essence you're just relying on error messages to resolve all the errors. Whether those errors happen at compile time or runtime aren't a big deal.

That is the point. I'm not waging a war against C++. I'm EXPLAINING to people like you who don't bother to read carefully or think carefully.

>But the topic here is type systems, and Rust's is more like C++'s than any other, and vice versa.

Categorically wrong. Rust's type system is derived from the Hindley Milner. See: https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_sy.... Haskell is the the language famous for using this type system. In short Rust's type system comes from functional programming and C++'s type system is derived from OOP origins.

>but competition between compilers has improved them.

I use C++ everyday for my work. It may have improved but it's still overall horrible.

Re: The type system is a programmer's best friend

#388
post #378

Earlier quoted context omitted.

>I don't know what this means? You seem to be suggesting that code in a statically typed language cannot be debugged? You don't know what it means probably because you don't have experience with C++. These types of errors are littered throughout C++. What you think I'm suggesting here was invented by your own imagination. I am suggesting no such thing. You talk about strawmen? Literally what you said can be viewed as…

> You don't know what it means probably because you don't have experience with C++. I started developing in C++ in 1992, so I have a few years with it. I've never run into the problems you seem to be experiencing. > Type errors that happen at runtime or compile time contain the same error message. Yes. But for the runtime error to occur, you need to trigger it by passing the wrong object. Unless you have a test case…

>Yes. But for the runtime error to occur, you need to trigger it by passing the wrong object. Unless you have a test case for every possible wrong object in every possible call sequence (approximately nobody has such thorough test coverage)

And I'm saying from a practical standpoint manual tests and unit tests PRACTICALLY cover most of what you need.

Think about it. Examine addOne(x: int) -> int. The domain of the addition function is huge. Almost infinite. Thus from a probabilistic standpoint why would you write unit tests with one or two numbers? it makes no sense as the your only testing a probability of 2 out of infinite of the domain. But that probability is flawed because it is in direct conflict with our behavior and intuition. Unit tests are an industry standard because it works.

The explanation for why it works is statistical. Let's say I have a function f:

   assert(f(6) == 5).
The domain and the range are practically infinite. Thus for f(6) to randomly produce 5 is a very low probability because of the huge number of possibilities. This must mean f is not random. With a couple of unit tests verifying confirming that f outputs non-random low probability results demonstrates that the statistical sample you took has high confidence. So statistically unit tests are basically practically almost as good as static checking. They are quite close.

This is what I'm saying. Yes static checks catch more. But not that much more. Unit tests and manual tests cover the "practical" (keyword) majority of what you need to ensure correctness without going for an all out proof.

>If you had been catching these during compile time, like a static type system allows, that can never happen. >I started developing in C++ in 1992, so I have a few years with it.

The other part of what I'm saying is that most errors that are non-trivial happen outside of a type system. Seg faults, memory leaks, race conditions etc... These errors happen outside of a type system. C++ is notorious for hiding these types of errors. You should know about this if you did C++.

Python solves the problem of segfaults completely and reduces the prevalence of memory leaks with the GC.

So to give a rough anecdotal number, I'm saying a type system practically only catches roughly 10% of errors that otherwise would not have been caught by a dynamically typed system. That is why the type checker isn't the deal breaker in my opinion.

Re: The type system is a programmer's best friend

#389
post #369

Earlier quoted context omitted.

Vim: I can do that too, I swear! Just configure some plugins, can’t tell you what they might be though. But I’m turing complete, and I’m the best! VScode: Of course I can do autocomplete bud. Here, search my package repo, I’ll tell you which plug-ins are the most popular and handle the entire download and install process for you. There’s no comparison.

They’re different experiences for users with different priorities. Your priority is evidently ease of configuration, VScode is definitely easier out of the box - there is no comparison. My priority is hackabilty for streamlined editing and code navigation. Here neovim run circles around vscode. Neither is “right”, just different preferences. Note that I’m not here to tell you my editor is better, I personally enjoy u…

"My priority is hackabilty for streamlined editing and code navigation. Here neovim run circles around vscode."

I hear this line a lot from hard-core vim users, but it's always talked about in the general. I'd like to hear a specific use case and exact scenario where a common workflow is faster in neovim over a more full featured IDE like JetBrains or Visual Studio.

Re: The type system is a programmer's best friend

#390
post #378

Earlier quoted context omitted.

> You don't know what it means probably because you don't have experience with C++. I started developing in C++ in 1992, so I have a few years with it. I've never run into the problems you seem to be experiencing. > Type errors that happen at runtime or compile time contain the same error message. Yes. But for the runtime error to occur, you need to trigger it by passing the wrong object. Unless you have a test case…

>Yes. But for the runtime error to occur, you need to trigger it by passing the wrong object. Unless you have a test case for every possible wrong object in every possible call sequence (approximately nobody has such thorough test coverage) And I'm saying from a practical standpoint manual tests and unit tests PRACTICALLY cover most of what you need. Think about it. Examine addOne(x: int) -> int. The domain of the ad…

I don't understand why you're talking about statistical sampling. Aside from random functions, functions are deterministic, unit testing isn't about random sampling. That's not the problem here.

Problem is you have a python function that takes, say, 5 arguments. The first one is supposed to be an object representing json data so that's how it is used in the implementation. You may have some unit tests passing a few of those json objects. Great.

Next month some code elsewhere changes and that function ends up getting called with a string containing json instead, so now it blows up in production, you have an outage until someone fixed it. Not great. You might think maybe you were so careful that you actually earlier had unit tests passing a string instead, so maybe it could've been caught before causing an outage. But unlikely.

Following month some code elsewhere ends up pulling a different json library which produces subtly incompatible json objects and one of those gets passed in, again blowing up in production. You definitely didn't have unit tests for this one because two months ago when the code was written you had never heard of this incompatible json library. Another outage, CEO is getting angry.

And this is one of the 5 arguments, same applies for all of them so there is exponential complexity in attempting to cover every scenario with unit tests. So you can't.

Had this been written in a statically typed language, none of this can ever happen. It's the wrong object, it won't compile, no outage, happy CEO.

This isn't a theoretical example, it's happening in our service very regularly. It was a huge mistake to use python for production code but it's too expensive to change now, at least for now.

Post reply on HN