Hacker News new | past | comments | ask | show | jobs | submit login

How the fuck do you release a language without enums?



To be honest I haven’t seen a single programming language that has decent enums.

With that I mean fundamental and fool proof functions for to/from a string, to/from an int, exhaustive switch cases, pattern matching, enumerating.

Seems like something that wouldn’t be too hard but everybody always fails on something.


> I haven’t seen a single programming language that has decent enums.

There's not much you can do with an enumeration. It's just something that counts one-by-one.

A useful tool when you have a large set of constants that you want to number, without having to manually sit there 0, 1, 2, 3... But that's the extent of what it can offer.

> With that I mean fundamental and fool proof functions for to/from a string, to/from an int, exhaustive switch cases, pattern matching, enumerating.

While a programming language may expose this kind of functionality, none of these are properties of enums. They are completely separate features. Which you recognize, given that you are able to refer to them by name. Calling these enums is like calling if statements functions because if statements may be layered with functions.


Can someone help me understand why enums are needed? They only seem like sugar for reducing a few lines while writing. What cannot be achieved without them or what is really a pain point they solve? Maybe it is hard to have a constant with type information?


The original enum are just enumerated integer constants.

What people want "the ability to express enums with an associated value", I think we should invent a new term.


The term you're looking for is ADT - Algebraic Data Types

https://en.wikipedia.org/wiki/Algebraic_data_type


We did: Sum types.


You can enumerate constants. There is syntax to implicitly assign the integer values, just use iota as a value.


You'll have to ask the Rust community. Rust lacks enums. Go, however, most definitely has enums (and exceptions too!).

    type E int
    const (
        A E = iota
        B
        C
    )
It's funny how people who have clearly never even looked at Go continually think they are experts in it. What causes this strange phenomena?


Go has a way to implement enums - I'll give you that. Rust does have enums though: https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html

They can have values like sum types, or not.


> Rust does have enums though

It does not. You'll notice that if you read through your link. A tag-only union is not the same thing, even if you can find some passing similarities.

If you mean it has enums like the Democratic People's Republic of Korea has a democracy, then sure, it does have enums in that sense. I'm not sure that gives us anything meaningful, though.

If we're being honest, sum types are the better solution. Enums are hack for type systems that are too limited for anything else. They are not a feature you would add if you already have a sufficient type system. It's not clear why Rust even wants to associate itself with the hack that are enums, but your link shows that its author has a fundamental misunderstanding of what enums even are, so it may be down to that.

To be fair, Swift made the same mistake, but later acknowledged it. It is interesting that Rust has chosen to double down instead.


> A tag-only union is not the same thing, even if you can find some passing similarities

Why not? Seems to function the same way.


Enums produce values. Tag-only unions 'produce' types (without values).

Realistically, there isn't a whole lot of practical difference. They were both created to try and solve much the same problem. As before, I posit that there is no need for a language to have both. You can do math on enum values, but that is of dubious benefit. In theory, tag-only unions provide type safety, whereas enums are just values so there is no inherit safety... But, as you probably immediately recognized a few comments back, with some static analysis you can take the greater view,

    type E int
    const (
        A E = iota
        B
        C
    )
and invent something that is just as useful as proper type safety. All the information you need is there. So, in reality, that need not even be significant.

But, technically there is a difference. Values and types are not the same thing.


> Enums produce values. Tag-only unions 'produce' types (without values).

Source? Is this something that is widely accepted, or just how you think enums should be defined.

My understanding is you are saying (using c++ as an example since it has both types) an `enum` is a "true" enum, while an `enum class` somehow isn't?


> Source?

To which language?

> `enum` is a "true" enum, while an `enum class` somehow isn't?

No. Enums are used in both cases. The difference there is in the types the enums are applied to. In one case, a basic integer-based type. In the other, a class.

This differs from Rust. Rust does not use enums. It relies on the type itself to carry all the information. C++ enum classes could have done the same, so it is not clear why they chose to use enums, but perhaps for the sake of familiarity or backwards compatibility with the regular enum directive?


> To which language?

I mean more in the sense of "where did you get this definition from."

> The difference there is in the types the enums are applied to. In one case, a basic integer-based type. In the other, a class.

I'm still not seeing a difference, mainly because when I went to see how c++'s `enum class` and rust's `enum`, they both seemed to work the same.

    #[repr(u8)]
    enum Words {
        Foo = 0,
        Bar,
        Baz,
    }

    const _: () = {
        assert!(Words::Foo as u8 == 0);
        assert!(Words::Bar as u8 == 1);
        assert!(Words::Baz as u8 == 2);
    };
vs

    enum class Words : uint8_t {
     Foo = 0,
     Bar,
     Baz
    };

    static_assert(static_cast<uint8_t>(Words::Foo) == 0);
    static_assert(static_cast<uint8_t>(Words::Bar) == 1);
    static_assert(static_cast<uint8_t>(Words::Baz) == 2);


> I mean more in the sense of "where did you get this definition from."

In other words, you want to have a conversation with someone else by proxy? If that's the case, why not just go talk the other people you'd really prefer to talk to?

> I'm still not seeing a difference

There is no difference. I recant what I said. This (strangely, undocumented in the above link) functionality does, in fact, provide use of enums.

Curious addition to the language. Especially when you consider how unsafe enums are. When would you ever use it? It is at least somewhat understandable in C++ as it may be helpful to "drop down" to work with the standard enum construct in some migratory situations, but when do you use it in Rust?


> Why not just go talk the other people you'd really prefer to talk to?

sorry, I didn't mean to be so argumentative or negative. (The "You'll have to ask the Rust community. Rust lacks enums." did get me a little annoyed :p)

> This (strangely, undocumented in the above link) functionality does, in fact, provide the use of enums.

That link was from "the rust book" which is primarily is for learning rust. For more technical info the referenced is used https://doc.rust-lang.org/reference/items/enumerations.html

> When would you ever use it?

I assume (like you said for c++) a good reason would be for c/c++ interoperate, but it also probably makes things like serialization easier. Sometimes you just need a number (e.g. indexing an array) and it's simpler to be able to cast then have a function that goes from enum -> int.

> Especially when you consider how unsafe enums are.

Do note though, going from int -> enum is an unsafe op which would require `std::mem::transmute`.


> sorry, I didn't mean to be so argumentative or negative.

Thanks, but I had no reason to think that the output of software has human qualities.

> That link was from "the rust book" which is primarily is for learning rust.

Learn Rust by keeping features of the language a secret? Intriguing.

> a good reason would be for c/c++ interoperate

I'm not sure that's a good reason. C++ doing it is questionable to begin with, but at least you can understand how a bad idea might have made it in many years ago when we didn't know any better.

> it also probably makes things like serialization easier.

It would, except you would never want to serialize the product of an enum as it means your program becomes forever dependent on the structure of the code. I mean, sure, you can remove the enum later if you are to change the code, so you're not truly stuck, but that kind of defeats the purpose. You may as well do it right the first time.

Enums are inherently unsafe. That you have to be explicit about converting the union to an integer at least gives some indication that you are doing something unsafe. It is not so unusual that Rust allows some kind of "escape hatch" to get at the actual memory. What is interesting, though, is that it also allows manipulation of what values are assigned by the enumerator as a first-class feature, which suggests that it promotes this unsafe behaviour. This is what is surprising and what doesn't seem to serve a purpose.


because you can just declare a custom type and have constants that use the custom type.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: