Live data from Hacker News

The type system is a programmer's best friend

dusted.codes

441–450 of 467 posts

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

#441

Earlier quoted context omitted.

> Rust has a perfectly nice type system by modern standards I disagree -- Rust's type system is pretty weak and very limiting compared to other modern languages like Typescript, Nim, Zig, or even C++. That's without even without getting into dependent type languages. There are so many basic patterns which Rust's type system can't handle, especially when it comes to compile time types. For example, one recent thing I…

> Personally I'm excited to see how C++ Concepts can evolve. So, C++ 20 Concepts is basically what Bjarne Stroustrup proposed for a future version of his C++ language in the early 2000s. Several people proposed and WG21 accepted, a far more capable feature set for Concepts, this is often referred to as C++ 0x Concepts, since it was accepted for C++ 0x, the standard that would eventually (after years of delays) become…

To be fair I've mostly used concepts in Nim, not C++ x0 concepts. However, your comparisons of C++ concepts to Rust traits seems to be lacking a lot of details or is plain inaccurate. It also misses the flexibility of C++ concepts.

> C++ 0x Concepts was similar to Rust's Trait system in many ways. Particularly notable features of C++ 0x Concepts you might recognise in Rust's traits:

Perhaps at the loosest level of comparison around only defining limitations on possible types. However, C++ x0 concepts enable much more powerful combinations of logic to specify if a template fulfills a concept. In Nim the concept can be any arbitrary boolean statement.

This blog has some good examples of C++ concepts: https://www.sandordargo.com/blog/2021/03/10/write-your-own-c...

It's trivial to specify that a C++ concept can be either a float or an integer:

    template 
    concept HasPower = (std::integral || std::floating_point) && requires (Base base, Exponent exponent) { 
        base.power(exponent);
    };
That's not possible AFAICT with Rust's traits.

> 1. Third parties can implement a C++ 0x Concept for some type which was not originally conceived with this Concept in mind, they just write the implementation and it works.

That's true for C++ concepts, but not entirely true for Rust traits. You can only implement a Rust trait if you own the type or own the trait. If you use two third party libraries, you cannot implement a trait from one for a type from the other. At best you can wrap the type in a new struct, and reimplement the parent's traits.

https://stackoverflow.com/questions/25413201/how-do-i-implem...

> 2. C++ 0x Concepts must be explicitly implemented they're not just a syntactic requirement that could be satisfied by happenstance in a type which is not in fact suitable.

That doesn't appear to match with C++ resources like: https://en.cppreference.com/w/cpp/language/constraints

Everything in Rust traits requires them to be encoded into existing traits. C++ concepts let you define rules for arbitrary combinations of types. So you can create functions that take two independent types and define a constraint on those types.

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

#442
post #116

Earlier quoted context omitted.

It's because you can write these types: recognize : String -> UnverifiedEmail validate : UnverifiedEmail -> VerifiedEmail send : (VerifiedEmail, Message) -> () You can then use visibility controls to universally guarantee that recognize and validate must be called before send. No test can ensure this is true. Under the presumption that send should only perform work on verified emails, the alternative is not being abl…

But then you can just have a "makeEmailVerified" that takes an UnverifiedEmail and converts it to a VerifiedEmail without verification. Then the "send" function still needs to check things.

Typically, the owner of the VerifiedEmail type restricts your ability to construct new values of that type by making the constructor private and then only "blessing" a small number of public constructors, each one performing that verification.

If any type could be converted to any other (compatible) type for any reason whatsoever then types would have no semantic value. But fortunately, we can control how types are constructed and used.

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

#443

Earlier quoted context omitted.

>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 do…

I don't think anyone is arguing that C++ is more difficult to use than Python, and much less safe. The question is how does python stack up to Java or C#? As you can see in this thread and many other discussions on this forum and elsewhere, people with experience working on larger systems will tell you that it doesn't.

If you had jobs in both stacks as I have you'll see that the differences are trivial. Python can get just as complex as either c# and java.

Those other people your copying your argument from likely only had jobs doing Java or C# and they did some python scripts on the side and came to their conclusions like that. I have extensive experience for production work in both and I can assure you my conclusions are much more nuanced.

Python and java stack up pretty similarly in my experience. There's no hard red flags that make either language a nightmare to use when compared to the other. People panic about runtime errors, but like I said those errors happen anyway.

Python does however have a slight edge in the fact that it promotes a more humane style of coding by not enforcing the oop style. Java programmers on the otherhand are herded into doing oop so you have all kinds of service objects with dependency injection and mutating state everywhere. So what happens is in Java you tend to get more complex code, while python code can be more straightforward as long as the programmer doesn't migrate their oop design patterns over to python.

That's the difference between the two in my personal experience. You're mostly likely thinking about types. My experience is that those types are not that important, but either way, modern python with external type checkers actually has a type system that is more powerful then Java or C#. So in modern times there is no argument. Python wins.

But prior to that new python type system my personal anecdotal experience is more relevant and accurate then other people's given my background in both Java and python And C++. Types aren't that important period. They are certainly better then no types but any practical contribution to safety is minimal.

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

#444

Earlier quoted context omitted.

I would not use C++ in your comparison. Try with C# or Java. Not even close. They will crush in developer productivity and maintenance over Python, Ruby, Perl, JavaScript.

First off python now has types (you can place type annotations on the interpreter and run an external type checker) and javascript people use typescript. In terms of type safety i would argue python and javascript are now EQUAL to C# and Java. Developer productivity in these scripting languages is also even higher. Simply because of how much faster they are to program in with the code then run/test loop. Java and C#…

You wrote: > Yes, for initial build. After, it is only incremental. I have worked on three 1M+ line Java projects in my career. All of them could do initial compile with top spec desktop PC in less than 5 mins. Incremental builds were just a few seconds. If your incremental build in Java or C# isn't a few seconds, then your build is broken. Example: Apache Maven multi-module builds are notoriously slow. Most projects don't really need modules, but someone years ago thought it was a good idea. Removing modules can improve compile time by 5x. I have seen it with my own eyes.

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

#445

Earlier quoted context omitted.

"financial trading systems" This is a myth. Many financial trading systems are written in C# and Java. Don't be distracted by the 1% of hedge funds with lousy funding that need nanosecond reactions to make money. If you have good funding, product diversity matters more than speed. Otherwise, your post is excellent. Lots of good points. SQLite is something that EADS/ESA/NASA/JAXA would write for a aeroplane / jet figh…

Thanks, glad you found the post useful. I'm sure C# and Java make excellent programming languages for many if not most financial applications, but I meant that in the context of high-volume Enterprise Application Integration (EAI). Basically financial message transformation, explosion, summarization, audit, etc. across multiple financial institutions. The volume of messages to be processed was quite considerable, so…

I am sure your use case was incredibly specific. For insane performance requirements plus enterprise software that is not greenfield, basically everything is C++.

No trolling. Have you ever seen the high-frequency Java stuff from Peter Lawrey's Higher Frequency Ltd.? It is insanely fast. Also, LMAX Disruptor (Java) data structure (ring buffer) is also legendary. I have seen it ported to C++. That said, you can beat all of this with C++, given enough time and resources!

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

#446

Earlier quoted context omitted.

First off python now has types (you can place type annotations on the interpreter and run an external type checker) and javascript people use typescript. In terms of type safety i would argue python and javascript are now EQUAL to C# and Java. Developer productivity in these scripting languages is also even higher. Simply because of how much faster they are to program in with the code then run/test loop. Java and C#…

You wrote: > Yes, for initial build. After, it is only incremental. I have worked on three 1M+ line Java projects in my career. All of them could do initial compile with top spec desktop PC in less than 5 mins. Incremental builds were just a few seconds. If your incremental build in Java or C# isn't a few seconds, then your build is broken. Example: Apache Maven multi-module builds are notoriously slow. Most projects…

>> Yes, for initial build. After, it is only incremental.

I work with C++ currently. Even the incremental build is too slow. Also eventually you have to clear the cache for various reasons including debugging, a new library, etc, etc/

1M line python is 0s compilation time. You hit the runtime section instantaneously.

Go was created with fast compilation times to get around this problem. I would say in terms of compilation, go basically is the closest in terms of the python experience.

Basically when things are fast enough "5x compilation time" isn't even thought about because things are too fast to matter anyway. Go hits this area as well as python (given no compilation)

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

#447

Earlier quoted context omitted.

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.…

Another thing you're not addressing here is basically Type checking solves none of the problems you describe. You claim it's extraordinarily hard to write tests for UI and for memory corruption. And that's your argument for type checkers? It's next to impossible to type check UI and memory corruption. So your argument has no point here.

SQlite is written in C. It has type checking. Yet people still write unit tests for it. Why? Because type checking is mostly practically inconsequential. All your points don't prove anything. It proves my point.

All the problems you talk about can be solved with more advanced proof based checkers. These systems can literally proof check your entire program to be fully in spec precompile time. It goes far beyond just types. Agda, Idris, Coq, and Microsofts lean have facilities to prove your programs to be fully correct 100% of the time. They exist. But they're not popular. And there's a reason for that.

You say it's paramount to move error detection to compile time. I say, this problem is ALREADY solved, but remains unused because these methods aren't PRACTICAL.

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

#448

Earlier quoted context omitted.

Ever so slightly longer compile times. It's pretty close to a free lunch. There are only tradeoffs when we are at the frontier of what's possible with a set of technologies, and so must trade off on something in order to move along that frontier[1]. Many languages aren't operating at that frontier, and adding static typing is free (in the marginal case, ignoring the substantial effort to implement the type system). I…

People using dynamic languages deeply, especially library and framework authors, regularly write abstract/generic code for which a suitable type declaration would be mind-bendingly difficult in a very sophisticated type system and impossible in a weak one. You can argue that this is ill-advised! But static typing with normally-powered type systems leads to more voluminous and more purpose-specific code. Very powerful…

I think this is a little disingenuous. It’s not that the type system makes highly abstract/generic code difficult, it’s more that the specific ways people are used to writing that type of code in dynamically typed languages doesn’t lend itself well to adding type annotations. But I think you’d be hard pressed to find many places where Haskell programmers, for example, haven’t found a different way to express whatever the Python code is achieving while also allowing for type annotations.

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

#449
post #287

Earlier quoted context omitted.

For a while in the codebase I was working on, we had a set of distinct types for different units. You know, a type for meters, another for centimetres, etc etc. We had types for radians, types for degrees. We had conversion functions between them, and type inference when you performed certain operations. The result was a disaster. Not an enormous disaster, but enough of a problem to rip the entire thing out and repla…

>The result was a disaster. wtf? metres and centimetres are not different types! they are just different ways of writing same type: Length. radians and degrees are just ways of writing a dimensionless Angle quantity. you made the absolutely elementary mistake of conflating a physical quantity with the unit used to measure it, of course it was a disaster. >nothing sensible to infer when you, say, multiply an angle and…

You might not have seen this pattern before, but annotating values with units as types is a legitimate approach. There’s a whole chapter about it in the book Software Design for Flexibility by Gerald Sussmann, the author of Structure and Interpretation of Computer Programs, which is linked on here pretty often. It has to be done in the right way, though, in a language that’s expressive enough to support it.

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

#450

Earlier quoted context omitted.

I don't understand. What should you get instead?

Go does not have operator overloading, and numeric operators must have identical types. So if you have `var x int = 5` and `var t time.Duration = 2500 * time.Millisecond`, you have to `time.Duration(x) * t` or `time.Duration(x * int(t))`. It's slightly better than languages with no operator overloading nor newtypes at all (well, actually a lot better given other things you can use newtypes for) but without operator o…

Two options:

1. Don't type units like that.

2. Allow the * operator to multiply a time-unitful value with an untimed scalar and disallow using it with two time-unitful values.

Presumably the requirement that * operands are the same is arbitrarily modifiable and go developers have control over what types operators take.

Post reply on HN