Live data from Hacker News

Switching from C++ to Rust

laplab.me

71–80 of 289 posts

Re: Switching from C++ to Rust

#71

The call out to sum types is something I feel. I've been using Rust daily for almost 10 years now, and sum types are absolutely still one of the things I love most about it. It's easily one of the things I miss the most in other languages that don't have them. I'm usually a proponent of "using languages as they're intended," but I missed exhaustiveness checking so much that I ported a version of it to Go[1] as a sort…

I'm going to make the even stronger claim that a general-purpose statically typed language that doesn't support sum types and exhaustive pattern matching to at least the extent that Rust does is unfit for general use, just like a language that doesn't have product types is unfit for general use. Dynamically-typed languages often have adhoc sum types.

Well that's obviously not true given all the successful apps written in languages that don't support sum types.

Re: Switching from C++ to Rust

#73

Earlier quoted context omitted.

By using a struct with lazily initialized members, for example.

Why does the members be lazily init:ed?

If the data types have constructors and/or destructors that have side effects then it has to be lazy. Otherwise IMO it's not really behaving like a sum type.

Re: Switching from C++ to Rust

#74

Earlier quoted context omitted.

A union in C++ is the same thing as a struct, except all of its fields live at the same offset. So you can define any method you want on it, including special stuff like constructors and destructors. No base classes are allowed, though.

A method on a union is much less useful when you can't match on the tag though. I suppose you could store tag inside the union. Is that common? I've always imagined C/C++ tagged unions would store tag outside the union.

i haven't done c++ in a million years, but huh, you can! can't have any types w/ non-trival copy constructors in a union, though, apparently, which is quite the restriction.

https://gist.github.com/erinok/c823af95db408653c7e42ab189307...

Re: Switching from C++ to Rust

#75
post #43

The call out to sum types is something I feel. I've been using Rust daily for almost 10 years now, and sum types are absolutely still one of the things I love most about it. It's easily one of the things I miss the most in other languages that don't have them. I'm usually a proponent of "using languages as they're intended," but I missed exhaustiveness checking so much that I ported a version of it to Go[1] as a sort…

Yeah. In the C++ codebase I work on, we use folly::Expected (essentially similar to Rust's Result ) heavily. Is it as ergonomic as Result is in Rust? Absolutely not. But it's still a nice design pattern for some of the same reasons people use Result in Rust. (And C++ std::optional is somewhat similar to Rust's Option type.) https://github.com/facebook/folly/blob/main/folly/Expected.h...

Swift has a similar Result type, it’s very handy.

Re: Switching from C++ to Rust

#76
post #25

The call out to sum types is something I feel. I've been using Rust daily for almost 10 years now, and sum types are absolutely still one of the things I love most about it. It's easily one of the things I miss the most in other languages that don't have them. I'm usually a proponent of "using languages as they're intended," but I missed exhaustiveness checking so much that I ported a version of it to Go[1] as a sort…

To me its not just exhaustiveness but that sum types (enums) are just like product types (structs), they have have member methods, implement traits, etc. Coming from C++, when I realized Rust let me do that, it blew me away.

Actually all three of Rust's user defined types (the sum type enum, the product type struct, and union†) are fully fledged types which can implement traits and have functions of their own (including functions taking a self parameter, thus methods)

C++ unions can actually have methods, although this isn't used very much. However C++ enums can't have methods, even C++ 11 scoped enums ("enum classes") can't have methods, I have no idea why that restriction seemed like a good idea.

† Unions are special because they're crazy dangerous, which is why they're not usually covered in material for learning Rust - you can't fetch from them safely. You can store things in unions safely because the process of storing a value in a union tells the compiler which is the valid representation - the one you're storing to, but fetching is unsafe because you might fetch an inactive representation and that's UB. However Rust does have a particularly obvious union right in the standard library - MaybeUninit - and sure enough MaybeUninit implements Copy and has a bunch of methods.

Re: Switching from C++ to Rust

#77
post #63

Earlier quoted context omitted.

By using a struct with lazily initialized members, for example.

if that is your example, provide some code.

Pretend we have the following sum type:

    enum SumType {
        Foo(foo),
        Bar(bar),
        Baz(baz),
    }

    void DoSomething(SumType sum_type) {
        match sum_type {
            Foo(foo): foo.do_x();
            Bar(bar): bar.do_y();
            Baz(baz): baz.do_z();
        }
    }
This could be lowered to:

    struct LoweredSumType {
        optional foo;
        optional bar;
        optional baz;
    }

    void DoSomething(LoweredSumType sum_type) {
        if (sum_type.foo.has_value()) {
            sum_type.foo->do_x();
        } else if (sum_type.bar.has_value()) {
            sum_type.bar->do_y();
        } else {
            sum_type.baz->do_z();
        }
    }
This isn't real code; it's a pretend language that's kind of a mix of Rust and C++. But it illustrates that the sum type can be lowered into a non-union representation.

Re: Switching from C++ to Rust

#78
post #59

Earlier quoted context omitted.

Does your code ever contain class hierarchies with a fixed set of classes? Or variables where certain values have special case meaning? Those are the cases where Sum Types make things immeasurably nicer than the alternatives.

> Does your code ever contain class hierarchies with a fixed set of classes? no - one of the advantages of OO programing is that class hierarchies (should you feel the need to use them, which mostly i do not) can be expanded. or indeed contracted. > Or variables where certain values have special case meaning? very, very rarely (i would say never, in my own code) but of course we have the null pointer as a counter-exa…

Do you have any large open source code bases that you could share?

Re: Switching from C++ to Rust

#79
post #41
post #37

Earlier quoted context omitted.

Ah I was writing a reply to someone else as you commented this :) We've got experimental projects with some ports of our firmware to it already, but there are lots of showstoppers that we've run into (some of which are ESP-IDF's fault more-so than esp-rs directly). In the medium-to-long-term, I'm really hopeful we can move to it. Not quite there yet for our production use cases though unfortunately.

If the lack of some services allows it (maybe not given the chip, but it was enough for me) I recommend using esp-hal+esp-wifi rather than esp-idf-hal, it is a pure rust 'rewrite' and it's been a great experience compared to esp-idf(c++). Default is bare-metal but embassy resolves most of the need of an rtos.

I'll check it out! While it's unlikely that we're going to rewrite this firmware anytime soon, being able to leverage Rust for future projects would be nice. The big thing for us is, we use basically every peripheral and driver that ESP-IDF has, along with some extra third-party ones for some other peripheral chips we run via our daughterboard setup -- and currently today, a lot of that isn't supported yet.

Definitely keeping an eye on it though. The future of Rust on the ESP32 chips is promising!

Post reply on HN