Hacker News new | ask | show | jobs
by ryderm 4063 days ago
Interesting point of view to hear. RE: enums - There is an idiomatic way to do enums in go I believe:

  type MyEnum int

  const (
        A MyEnum = iota
        B
        C
        D
  )
4 comments

Rust's enums aren't like Java enums, they are algebraic datatypes and each variant can hold different data. Check out the example with DrawTriangle and whatnot for what I mean :)
You are not correct regarding Java's enums. Define properties for your enum type, widen the constructor appropriately, and provide the accessor methods:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html...

That's not the same thing. Rust enums are types, each with the possibility of having different fields that store data. Java enums are instances of a type, each with static data.

(rust enums can have associated data too, but its not their main usage in idiomatic code)

Why does Rust incorrectly use the name "enum" for "tagged union" or "sum type"?
Because in the simplest case when no variant has any associated data they are indistinguishable from C-style enums. The `enum` keyword was originally `tag` in ancient versions of Rust, and at least twice in the past three years there have been massive bikesheds to reconsider the keyword. You are free to dig through Rust's history if you'd like to understand why `enum` won out every time.
They don't have to be though, a degenerate enum `enum Foo { Bar, Baz }` is equivalent to a C enum.
Rust's Enum, it looks like, aren't the same as C-esque enums, and look a lot closer to Go-interfaces (or like the article says C's unions).

That said I wonder why they named it enum.

> That said I wonder why they named it enum.

Because it's a type-safe enumeration? ADTs are pretty much a superset of C-style enums, an ADT with all-dataless constructors is equivalent to a C enum:

    enum Foo { Bar, Baz, Qux, Quux }
And members can converted to integrals:

    > println!("{}", Foo::Qux as u8);
    2
With explicit integrals very much like C:

    > enum Foo { Bar = 5, Baz, Qux, Quux }
    > println!("{}", Foo::Qux as u8);
    7    
Calling it "enum" makes it familiar to C developers[0], "union" would have been confusing for the same (as you can't just write one representation and read the other) and "type" is a tad too generic (and used for type aliases à la typedef).

[0] even more so C++ developers as they have `enum class` which is also type-safe and not implicitly converted to integrals

Well you are right, the name does make sense, but I would have thought "union" would have made more sense than "enum" for those of us from the C-family.

OTOH I haven't written a line of Rust of yet, so enum might be more familiar in use.

> Well you are right, the name does make sense, but I would have thought "union" would have made more sense than "enum" for those of us from the C-family.

The issue with `union` is it might hint at things which are not available (e.g. the union of an int and a float where you can access to the raw data as either).

A Rust enum is really an encoding of the `struct { enum, union }` pattern, but it degenerates to an enum if there's no union part (no data payload), not to a union. So calling it an enum makes more sense.

What Rust calls an "enum" is a discriminated variant record from Pascal. They're used in a completely different way, though. Their primary use is encapsulating function results which can be either a useful value, or some indication of error. The "Result" and "Some" generic enums are used for this. Then the "match" operation is used to fan out control depending on what enum case came back from a function. It's both elegant and kind of clunky.
Tagged unions in particular, C's version of variant types. An enum can be considered a degenerate case of such a type, so the naming isn't totally arbitrary.
mmm, this seems to be a confusion of names. Using const and iota in Go helps you to create enumerations (http://en.wikipedia.org/wiki/Enumeration) whereas enum in Rust is actually creating a tagged union (http://en.wikipedia.org/wiki/Tagged_union). Most of the time in Go, you would define a new interface for the situation the author is describing.
I think what he actually wanted was:

    type Shape struct {
            Rectangle *Rectangle
            Circle *Circle
            Triangle *Triangle 
    }
Then you send shapes on your channel rather than interface {}. If you want to enforce having only one element populated, make the struct members private and write:

    func NewRectangleShape(r *Rectangle) *Shape {
        return &Shape{rectangle: r}
    }
No, please don't. Go structs are not C unions. Please see my other comment in this thread about using Go interfaces.
I disagree. Sometimes an interface is not appropriate; just because you have two things that are alike doesn't mean that they implement an interface.

"A circle, triangle, or rectangle" is not the same data structure as "Something that can be drawn". Certainly if you have a function that draws something given a Draw() method, having the function take a "Drawable" is appropriate. But it's not the only use case; sometimes you really mean "A circle, triangle, or rectangle" and in that case, a struct is absolutely what you want.