Live data from Hacker News

The type system is a programmer's best friend

dusted.codes

201–210 of 467 posts

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

#201

Earlier quoted context omitted.

I don’t disagree that it makes things much more pleasant, but I started doing this around 2013, which, while old, was still a year beginning with 20, and consensus was trending the opposite way and people were bullish about stuff like Ruby. The pendulum has really swung in the other direction.

No, there really is no new insight OP or anyone else has. At the end of the day, the only thing that matters is writing something that works and works well. Hackers go through too many moodswings to be worth paying attention to when they start telling you how you should code.

> Hackers go through too many moodswings

True! But computer scientists (who are sometimes also hackers, sometimes not) apply research methods to existing codebases and the practice of coding, and have repeatedly presented findings that indicate that, mood swings/fads/hype cycles aside, some techniques really do deliver better software quicker. The VPRI STEPS work is an interesting example of this.

That's not to say that every CS methodology paper should be taken as gospel; we have problems just like other disciplines, sometimes more. But it's a far cry from post-hoc rationalization and hacker mood swings.

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

#202
post #93

Earlier quoted context omitted.

No no no, entirely not. OOP need not be statically typed at all; see Smalltalk.

Or Python, or JavaScript. The reverse is true, you can have static type-checking without OOP, like C, Rust, Haskell.

I feel compelled to note that C only has the lightest possible amount of type checking, if even that. For example, the following program compiles:

  #include 
  void foo(double* c) {
    printf("%g", *c);
  }
  void bar() {
    printf("bar");
  }
  int main() {
    int x = 9;
    int* y = &x;
    foo(x); //warning
    foo(y); //warning
    bar(1.0); //not even a warning
  }

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

#203

This is, IMvHO, such old news that it feels... weird to still read about it in a year with the prefix of 20. Every programmer who has ever single-handedly written a 100,000+ LOC software system will tell you the same thing: shift as much responsibility on the compiler as you can and have the compiler check the code you write to any extent technologically possible. Getting rid of bugs by experiencing, diagnosing and f…

But there's a paradox. Why does 100,000 lines of code of python tend to be safer and more manageable then 100,000 lines of C++ despite the fact that python has no type checker and C++ has a relatively advanced type checker? Why do startups choose a python web stack over a C++ web stack? I don't think it's "self-evident." I think there's something more nuanced going on here. Hear me out. I think type systems are GREAT…

> So basically compile time type checking just makes some of the errors get caught earlier which is a slight benefit but not a KEY differentiator.

Unfortunately, I have to completely disagree here, at least based on my experience. Shifting software error detection from runtime to compile time is absolutely paramount and, in the long run, worth any additional effort required to take advantage of a strong type system.

Firstly, writing unit tests that examine all the possible combinations and edge cases of software component input and state is... an art that requires enormous effort. (If you don't believe me, talk to the SQLite guys and gals, whose codebase is 5% product code and 95% unit test code.)

Secondly, writing automated UI tests that examine all the possible combinations and edge cases of UI event processing and UI state is... next to impossible. (If you don't believe me, talk to all the iOS XCUI guys and gals who had to invent entire dedicated Functional Reactive paradigms such as Combine and SwiftUI. ;) J/K)

Thirdly, I don't even want to get into the topic of writing tests for detecting advanced software problems such as memory corruption or multi-threaded race conditions. Almost nobody really seems to know how to write those truly effectively.

> So what was it that makes python easier to use then C++?

The Garbage Collector, which is side-stepping all the possible memory management problems possible with careless C++. However, a GC programming language probably cannot be the tool of choice for all the possible problem domains (e.g., resource-constrained environments such as embedded and serverless; high-performance environments such as operating systems, database internals, financial trading systems, etc.)

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

#205

This is, IMvHO, such old news that it feels... weird to still read about it in a year with the prefix of 20. Every programmer who has ever single-handedly written a 100,000+ LOC software system will tell you the same thing: shift as much responsibility on the compiler as you can and have the compiler check the code you write to any extent technologically possible. Getting rid of bugs by experiencing, diagnosing and f…

But there's a paradox. Why does 100,000 lines of code of python tend to be safer and more manageable then 100,000 lines of C++ despite the fact that python has no type checker and C++ has a relatively advanced type checker? Why do startups choose a python web stack over a C++ web stack? I don't think it's "self-evident." I think there's something more nuanced going on here. Hear me out. I think type systems are GREAT…

I think it is simpler than that: C++ is an incredibly complex and verbose language. Most of web development is working with strings, and C++ kinda sucks there. There is also a compilation/build step, so overall productivity is lower. Python is "easier" all the way around (we'll ignore the dependency management/packaging debates.)

It depends on how you define "safer." Run-time errors with Python happen frequently in large programs due to poor type checking all the time. Often internal code is not well documented (or documented incorrectly) so you may get back a surprise under certain conditions. Unless you've have very strict tooling, like mypy, very high test coverage, etc. there is less determinism with Python.

Also, this may come as a surprise, but many people do not run or test their code. I've seen Python code committed that was copy-pasta'd from elsewhere and has missing imports, for example. Generally this is in some unhappy path that handles an error condition, which was obviously never tested or run.

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

#206

I have to plug Ada's rich type system for explicitly encouraging this kind of design. With things like type predicates [1], you can do run-time enforcement or even prove at compile-time (to optimize away the runtime checks) that type constraints are met. As an example of this, in a piece of code I'm working on there's a Base64_String type, where only RFC 4648 characters are permitted to be part of the string, the '='…

How does this get enforced for string content changed at runtime? Or does this apply for only to strings initialised in code.

You can enforce newtype on strings, or also use a dynamic predicate which checks at runtime.

https://ada-lang.io/docs/arm/AA-3/AA-3.2/#324--subtype-predi...

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

#207
post #179

Earlier quoted context omitted.

Based on the casing JsonValue is an object, not a primitive, so there's no reason that interface wouldn't work. It would just by a different subtype depending on what type the value is, and lists/dicts would also implement the Map interface.

As much as I can just happily ignore JSON because I don't do webdev, I think there is a strong case to make that lists should be implemented using a native list, array, or vector class. But I won't argue because it's not necessary. The possibility for argument already proves my point. My point is to show that "the type system" provides endless rabbit holes, and often is just a waste of time. There are a lot of situat…

> The possibility for argument already proves my point.

Was just correcting something wrong:

> But as a heads up, Map couldn't be representation of all valid JSON documents.

So,

> As much as I can just happily ignore JSON because I don't do webdev

I think this is why you're going wrong here. JSON is pretty much a solved problem, and Map is pretty close to how it's used in Java and other languages that don't have native types that match its structure (like javascript and python do).

> (Trivial example, as an embedding in an HTTP response object)

This isn't json, it's what you get when you stringify/dumps/convert the json into a different datatype. When you need to be specific it's often called a "json string".

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

#208

I’ve always grokked primitive types as mapping to different concepts used when storing values in memory. A string is some bytes in a line with a terminator at the end. An integer is a group of signed or unsigned bytes. An enum value points at another value with a pointer. Etc. What I think this describes is some validation classes, which don’t need to be built into a language’s runtime. Primitive types have a real re…

This doesn't make too much sense. For example, (on 64-bit Linux) long, unsigned long, long long, unsigned long long, double, void*, char*, int(*)(int), []int are all stored in exactly the same way: they are a 64-bit value somewhere in memory. You could argue that double is different since it's just packing a mantissa and exponent, and that signed is actually a sign bit + a 63-byte number, but that still leaves long*, int(*)(int) and long being the same thing: a 64-byte number. Not to mention that struct X { long X } has the same representation as well most likely.

Instead, it's more normal to think of types (primitive or not) as descriptions of what can be done with a particular kind of value - from this point of view, it's obvious why long* is a different type than long (you can dereference it) or int(*)(int) (you can't call it). With this new definition, we can also see why we may want to distinguish EmailAddress from String - you can send an email to an EmailAddress, but you can't send an email to a String; conversely, you can sort the characters of a String, but you can't sort the characters of an EmailAddress.

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

#209

Earlier quoted context omitted.

I’d take this further. I was listening to the John Carmack episode of Lex Fridman from the summer, and he makes a comment about being frustrated that in the Valley there’s an almost religious opposition to IDEs, debuggers, and static analysis. Some of those tools have only become more powerful over time and I’m perplexed as to the mindset that would make a person averse to automating the drudgiest parts of their job…

When I graduated college in the '00s I thought Vim was the most amazing thing I'd ever learned. Then a colleague at my first job showed me what happend when you typed . after a variable name in Visual Studio. Code completion, inline documentation...my mind was blown, and I never looked back. When I meet a young chap extolling the benefits of Vim or Emacs or really anything that doesn't have stepped debugging and code…

When I was a kid learning to code, programming books recommended stridently against even using syntax highlighting. It's funny how helpful things get rejected by people who "did it the hard way."

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

#210

Articles like this bug me. You've given me a list of why types are awesome. Great. Now, tell me what the tradeoff is. Nothing is free in engineering. To get something, you have to give up something else. Even grug[0] understands this. [0]: https://grugbrain.dev/#grug-on-type-systems

> Nothing is free in engineering. To get something, you have to give up something

I think this is a dangerous position to take to extremes/as an axiom.

Not talking about type systems at all here. The assumption that, given two tools/techniques for accomplishing the same goal, there are always equivalent tradeoffs simply isn't true.

Some tools are better than others.

That statement usually provokes misinterpretation. It should not be taken to mean:

- That some tools are always better than others, in every context. There are situations in 2022 where COBOL is the best choice for new code, and other situations where rewrite-it-in-Rust is the best choice. Problems occur when "tradeoffs of tool A (even if we don't know what they are yet) make it equivalent to tool B" is a core tenet of decision making.

- That some tools always have been and/or always will be better than others. Context, expectations, tool capabilities, and available programmer talent pools all change massively over time.

- That one tool is better than all the others. Plenty of times there are multiple ways to deliver optimal-given-constraints outcomes, and it comes down to a matter of taste or "just pick something, anything, and let us get to work".

Chasing hype and cargo culting leads to poor outcomes; "we should build our two-core app on Kubernetes/write our 2TPS app in Rust" are often justified with "because it's the future" or "because the cool kids are doing it". That's a major bummer.

But the opposite extreme is just as bad: assuming that all choices are fundamentally a wash because "to get something, you have to give up something else" is just as methodologically irresponsible as following the hype cycle. Programming isn't alchemy. This kind of bad decisionmaking can lead to dependence on obsolete (unsupported/insecure) tools, difficulty hiring, and, at worst, a culture of "don't talk about Python to me; if you can't freehand it in C you just need to get gud" gatekeeping cruelty.

Everything has tradeoffs. That doesn't mean they're equivalent.

Post reply on HN