News for hackers. Stuff that matters.
Re:Using enums to represent state in Rust by pdpi on Friday September 22, 2023 @08:59AM (#37611421)
I kind of consider algebraic data types (the combination of this style of enum (sum types) and structs (product types)) paired with pattern matching as the core feature set that any modern language must support. It makes for really simple, easy to follow code that’s much less error prone than the alternatives.
Re:Using enums to represent state in Rust by the__alchemist on Friday September 22, 2023 @09:18AM (#37611649)
I joke to myself that I program with "struct and enum-oriented programming". I got it from Rust, but apply it to Python too. (Python enums aren't as ergonomic, and they can't wrap values, but they're a start)
Re:Using enums to represent state in Rust by qsort on Friday September 22, 2023 @09:50AM (#37612047)
Python's equivalent of Rust's Enums would be the __match_args__ machinery rather than enums themselves, ironically.

They aren't as ergonomic or type-safe, and rather surprisingly the match statement is not an expression in Python's grammar, but regardless of its problems the match statement is very powerful, even more so than static equivalents.

Re:Using enums to represent state in Rust by GalaxySnail on Friday September 22, 2023 @01:15PM (#37614713)
IMO Python's equivalent of Rust's Enums would be `typing.Union` [1]. It is more ergonomic and type-safe, and mypy supports type narrowing [2] and exhaustiveness checking on it [3].

[1] https://docs.python.org/3/library/stdtypes.html#types-union

[2] https://mypy.readthedocs.io/en/stable/type_narrowing.html

[3] https://docs.python.org/3/library/typing.html#typing.assert_...

Re:Using enums to represent state in Rust by boredumb on Friday September 22, 2023 @09:32AM (#37611832)
Absolutely. It took me a few projects in Rust to sort of stumble on this and it can make some fairly complex business logic sit into nice matches that are trivial to run through.
Re:Using enums to represent state in Rust by ewuhic on Friday September 22, 2023 @11:13AM (#37613117)
What would be the equivalent of these patterns in Go?
Re:Using enums to represent state in Rust by fsdjkflsjfsoij on Friday September 22, 2023 @01:52PM (#37615273)
You can't do the exact same thing in Go because Go doesn't have a way to define a sum type yet outside of generic constraints. The closest you can get is using an interface and a type switch but that won't give you exhaustive matching.
Re:Using enums to represent state in Rust by newZWhoDis on Friday September 22, 2023 @09:46AM (#37612006)
Probably my favorite aspect of Swift as well, enums + payloads/associated types make for extremely safe and easy to understand code.

Combine it with switches and you get compiler guarantees that every state is explicitly handled, and if you are in a particular state you always have the relevant child objects.

I remember being shocked dart lacked this functionality when I tried out flutter.

Re:Using enums to represent state in Rust by flohofwoe on Friday September 22, 2023 @10:02AM (#37612189)
I just wish Rust wouldn't have called those things 'enums' but 'tagged unions', would have saved us C peasants a lot of confusion when encountering them first ;)
Re:Using enums to represent state in Rust by joshmarlow on Friday September 22, 2023 @10:14AM (#37612343)
C was my first language, and I actually have the opposite opinion - I suspect that calling them 'enums' helps adoption. My reasoning is that phrases like 'tagged unions' and 'algebraic datatypes' strike some developers as sounding very academic/ivory tower and so somewhat intimidating. I think this is really unfortunate (and is definitely not universal among developers).

Being able to say 'Rust enums can carry arguments' - for some reason - sounds less intimidating and conveys the core feature.

Re:Using enums to represent state in Rust by flohofwoe on Friday September 22, 2023 @10:17AM (#37612375)
I agree that something like 'sum type' sounds a bit too esoteric, but IMHO 'tagged union' is very descriptive. It's the same thing as a C union plus a tag indicating the currently active content (and that's also what the memory layout looks like under the hood).

(but yeah, 'enum with arguments' also describes it very well)

Re:Using enums to represent state in Rust by LoganDark on Friday September 22, 2023 @11:49AM (#37613570)
They do point them out as tagged unions many times in the documentation. But the syntax `tagged_union Whatever {}` doesn't exactly have me jumping out of my seat.
Re:Using enums to represent state in Rust by pavlov on Friday September 22, 2023 @02:33PM (#37615847)
It’s not like “enum” and “mut” are complete English words either, so maybe an abbreviation like “tun” could have worked.

But honestly I think enum was a better choice.

Re:Using enums to represent state in Rust by LoganDark on Friday September 22, 2023 @04:25PM (#37617308)
I personally think enum was basically the only reasonable choice, as normal enums really are just a subset of tagged unions. They just happen to support tagged unions on top of them.
Re:Using enums to represent state in Rust by goku12 on Friday September 22, 2023 @10:23AM (#37612461)
All C and C++ peasants should refer this: https://cheats.rs/#memory-layout . It will probably accelerate your initiation ritual.
Re:Using enums to represent state in Rust by Arnavion on Friday September 22, 2023 @12:04PM (#37613771)
That would still be technically misleading, since enums don't necessarily have tags due to niche optimization. Eg `Option` is an enum but `Option<Box<Foo>>` does not have any tags; it uses the content being zero to represent None since `Box<Foo>` cannot be zero.

Also, Rust does have actual tagged unions for C interop that you have to define yourself as a `struct` with an int field and a `union` field, just like in C.

Re:Using enums to represent state in Rust by twic on Friday September 22, 2023 @01:43PM (#37615126)
Rust enums always have a discriminant: https://doc.rust-lang.org/std/mem/fn.discriminant.html

Their representation in memory may not use it, but it's still defined.

Re:Using enums to represent state in Rust by 0x457 on Friday September 22, 2023 @02:37PM (#37615902)
They do, but IIRC this mostly to compare enum variants when it can't implement `Eq` and/or `PartialEq`. For example, in tests.

There are also zero variants enums that don't have any discriminant, but still could be used.

I'm not sure what's the point of comparing it to C because enums in C only carry tags and no data, while unions only carry data and no tag. Enums in rust could do both.

Re:Using enums to represent state in Rust by touisteur on Friday September 22, 2023 @03:57PM (#37616957)
Discriminated Records is The Way.
Re:Using enums to represent state in Rust by goku12 on Friday September 22, 2023 @10:40AM (#37612675)
I sometimes wish Rust had combined structs and enums into a single concept - same an enum. Structs would have been unnecessary. The compiler can simply avoid the tag or the union when a pure struct or a pure (c-type) enum is required, respectively.
Re:Using enums to represent state in Rust by bombela on Friday September 22, 2023 @02:18PM (#37615652)
> The compiler can simply avoid the tag or the union when a pure struct or a pure (c-type) enum is required, respectively.

I had to try:

  pub enum Foo {
      Foo { a: i32 },
  }
  
  impl Foo {
      pub fn new() -> Self {
        Foo::Foo { a: 42 }
      }
  
      pub fn get_a(Foo::Foo{a}: &Self) -> &i32 {
          a
      }
  }
At opt level above zero (-C opt-level=1) the tag is elided:

  example::Foo::new:
          mov     eax, 42
          ret
  
  example::Foo::get_a:
          mov     rax, rdi
          ret

https://godbolt.org/z/qKzMqvhb7
Re:Using enums to represent state in Rust by goku12 on Friday September 22, 2023 @11:08PM (#37620282)
That really does make structs superfluous, doesn't it? The only additional thing needed is a syntax sugar, where the variant name can be avoided if there is only one variant.
Re:Using enums to represent state in Rust by bombela on Saturday September 23, 2023 @12:02AM (#37620493)
Syntactic sugar to avoid the variant where there is only one, not only where used, but also when declared: enum Foo { Foo{...} }, what to do with the second Foo. And what about FFI (foreign function interface) where you have to maintain ABI compatibility over time. Factor all of that in, and it turns out Rust already has syntax for all of that: struct Foo {}.