# Referring to the type of value of an enum in the enum's class methods

**URL:** <https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529>\
**Category:** Help & Support\
**Created:** [March 29, 2022, 1:31pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529 "2022-03-29T13:31:15Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 1:31pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/1 "2022-03-29T13:31:15Z")

</div>

Let’s say I have the enums Foo and Bar

```auto
enum Foo : Int32
  # a lot of options
end

enum Bar : Int64
  # a lot of options
end

```

And for Int32 and Int64 I have defined:

```auto
struct Int32
  def self.foo (x)
    1
  end
end

struct Int64
  def self.foo (x)
    5
  end
end

```

Now I would like to be able to do something like:

```auto
foo= Foo.foo x

```

With the intention: Foo’s values are of type Int32, so I would want that somehow `Int32.foo(x)` gets called and if I would use` Bar.foo(x)` then `Int64.foo(x)` shall be called, and so on.

I guess I would have to define a method `self.foo` for `struct Enum` but I wouldn’t know how to refer to the enum’s value type in such a method

```auto
struct Enum
  def self.foo (x)
    __something_to_refer_to_the_type_of_the_value_of_the_enum__.foo x
    # basically this: new(0).value.class.foo x
    # but I assume there is a better way than the new(0) workaround 
  end
end

```

With what would I have to replace ` __something_to_refer_to_the_type_of_the_value_of_the_enum__ `?

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [March 29, 2022, 1:56pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/2 "2022-03-29T13:56:07Z")

</div>

This doesn’t answer your question, but adding methods to core types is not recommended. I mean, you can do it. But I don’t see any strong reason to do things like that.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 29, 2022, 2:16pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/3 "2022-03-29T14:16:28Z")

</div>

I’m a bit confused on the purpose this whole thing is serving? Like is that idea that calling `Int32.foo 10` returns a `Foo` instance with a value of `10`?

---

<div class="post-metadata">

**Author:** ![lbguilherme](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/lbguilherme/32/1484_2.png) [@lbguilherme](https://forum.crystal-lang.org/u/lbguilherme)\
**Post date:** [March 29, 2022, 2:29pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/4 "2022-03-29T14:29:52Z")

</div>

It looks like you want the `#value` method to get the integer value out of the enum instance.

```crystal
enum AAA : Int32
  Aaa
  Bbb
  Ccc
  
  def foo
    value.foo
  end
end

struct Int32
  def foo
    "foo#{self}"
  end
end

p AAA::Aaa.foo # => "foo0"
p AAA::Bbb.foo # => "foo1"
p AAA::Ccc.foo # => "foo2"

```

But as @asterite said, avoid adding new methods to built-in types, especially primitive types. That will cause issues down the line.

---

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 3:02pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/5 "2022-03-29T15:02:01Z")

</div>

I just simplified it a bit in my first example code, as it seemed to make the code just unnecessary complicated for what 'm trying to ask.

What I try to do achieve is the same as this (working) code would do:

```auto
struct Enum
  def self.foo (x)
    from_value values[0].value.class.foo x
    # x is not an integer at all, but
    # Int32.foo(x), Int64.foo(x), etc will return values of Int32, Int64, etc
  end
end

```

The workaround `values[0].value.class` works, but I would imagine there must be some way, which would be more straightforward, to address the enum type’s value’s type.

---

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 3:15pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/6 "2022-03-29T15:15:56Z")

</div>

Thanks. But sadly it’s not what I try to achieve (which would happen already before there is even an instance of AAA, basically I need it to figure out the value AAA shall get initiated with).

I originally used some pseudo enums (custom classes, which did behave somewhat like enums). But I’m trying to replace it with real enums (as Crystal’s enums seem to be quite awesome). And while new methods for built-in types might be to avoid, I guess they will be preferable over my pseudo enums which I used in the first place.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 29, 2022, 3:26pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/7 "2022-03-29T15:26:02Z")

</div>

No, I get what you’re _wanting_ to do, but it’s still not clear to me _why_. Like do your enum’s value actually represent something? If not then I’m doubtful that’s what you actually want to use. Just feels weird to go from a number, call an enum class method, that calls a monkey patched class method on specific number types, just to get another number? Could you share a bit more on what you’re using this for? May be a simpler way to go about it.

But to answer your question, pretty sure you could just do `typeof(x).foo x`. E.g.

```auto
struct Enum
  def self.foo(x)
    pp typeof(x).foo x
  end
end
 
Enum.foo 10
Enum.foo 10_i64

```

---

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 5:14pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/8 "2022-03-29T17:14:55Z")

</div>

The x in my example is most of the time a socket (and sometimes a buffer and in rare occasions a pseudo socket which just holds an infinite amount of ‘0’ bytes). The integers I retrieve from x are (most of the time) 7bit encoded, but some are just “normal” (little endian with the length of the type), and to deal with them I have the deserialisation done via `TargetType.foo(x)` (or actually `from` instead of `foo`, and I’m fully happy with the resulting code, like in `Int64.from host.socket`).

Some fo the transferred integers represent enums, and I end up wanting to do `@someEnum= SomeEnum.from socket`; of course I could do `@someEnum= SomeEnum.from_value Int64.from socket` but this would mean I would repeat the type Int64 even though it’s already known that `enum SomeEnum : Int64`. And as the enum is (and needs to be) typed already I want to avoid to type it anywhere else again.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 29, 2022, 5:43pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/9 "2022-03-29T17:43:33Z")

</div>

Okay cool, this helps a lot I think. Because you know that each enum should handle a specific integer type. I think you could do something like:

```auto
Enum SomeEnum
  def self.from(socket) : self
    self.from_value Int64.from socket
  end
end

```

Then you can just do `SomeEnum.from socket` and call it a day? Although this of course would not handle a more generic API of defining something on `Enum` itself that handles returning one or the other enum types based on the type it’s defined as.

There was a PR to add `Enum.base_type`: [Document how to change base type of an enum by Blacksmoke16 · Pull Request #9803 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/pull/9803). But wasn’t really worth adding. Although you could leverage some compiler typeof magic to do like:

```auto
struct Enum
  def self.from(socket)
    self.from_value typeof(self.values.first.value).from socket
  end
end

```

This would return the type of the enum via some magic that doesn’t actually result in an array access or anything.

---

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 6:19pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/10 "2022-03-29T18:19:14Z")

</div>

Your suggestion for typeof magic, looks almost exactly like my current workaround.  
The only real difference is that my workaround uses

`values.first.value.class` instead of  
`typeof(values.first.value)`

Is there in this specific context one preferable over the other?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 29, 2022, 6:23pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/11 "2022-03-29T18:23:28Z")

</div>

> [@anon69898395](#):
>
> Is there in this specific context one preferable over the other?

Yes, [Carcin](https://play.crystal-lang.org/#/r/cypc) illustrates it well. When you use `values.first.value.class` that’s actually calling those methods and creating an array and such. Whereas `typeof(values.first.value)` does not actually do any of that. I.e. which is why `first` is only printed once in the playground link.

---

<div class="post-metadata">

**Author:** ![anon69898395](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon69898395](https://forum.crystal-lang.org/u/anon69898395)\
**Post date:** [March 29, 2022, 6:26pm UTC](https://forum.crystal-lang.org/t/referring-to-the-type-of-value-of-an-enum-in-the-enums-class-methods/4529/12 "2022-03-29T18:26:52Z")

</div>

> whereas `typeof(values.first.value)` does not actually do any of that

😮 this I didn’t know at all. I’m glad I asked (and you replied). Thanks!
