Hacker News new | ask | show | jobs
by uryga 2427 days ago
my best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this:

  enum List<T> {
    Nil,
    Cons(T, List<T>)
  }
instead, you have to box/reference-ify the recursive occurrence:

  enum List<T> {
    Nil,
    Cons(T, Box<List<T>>)
  }
so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technically-not-exactly-a-coproduct (i think). a bit of a stretch but it sort of makes sense next to a by-reference-only ML langs where you can (co)product anything as you please

(btw, it's the same for recursive products)

---

1 - https://users.rust-lang.org/t/recursive-enum-types/2938/2

3 comments

You don't have to box, but you do need some sort of type to make things sized. This is usually a pointer of some kind, but any kind of pointer works. Take references, for example:

  enum List<'a, T> {
    Nil,
    Cons(T, &'a List<'a, T>)
  }
  
  fn main() {
      let list = List::Cons("hello", &List::Nil);
  }
Box is usually chosen because it's a good default choice.
you're right of course! i should've used a more generic term like "indirection" or "reference", didn't mean to put emphasis on Box
It’s all good, most people say just Box, because it is the majority case.
I think that's because Rust types are Sized, but I could be wrong. The first example has size = Infinity, while the second has a constant size.
Thanks for commenting, that's probably it. I was aware of the requirement for explicit box-ing but it didn't immediately come to mind.