logoalt Hacker News

SkiFire13yesterday at 10:50 PM5 repliesview on HN

> Consider an enum that represents a tree. Since, it is a recursive type, Rust will force you to use something like Box<> for referencing a type within itself. > > enum TreeNode<T> { > Leaf(T), > Branch(Vec<Box<TreeNode<T>>>), > } > > (You could also us Box<Vec<TreeNode<T>>> instead)

This is wrong, you don't need a `Box` here. The Rust compiler forces you to have a layer of indirection, but `Vec` already does that.


Replies

tialaramextoday at 1:04 AM

In one sense the places where the Rust is wrong don't trouble me because I already know Rust well, but in the end they do trouble me because it seems reasonable to assume the Swift is equally wrong but I don't know where and how.

For example "In fact, Swift treats enums as more than just types and lets you put methods directly on it" seems to assume that "just types" don't have methods, which I guess is what you might assume coming from say, C++ but Rust isn't C++ and so of course all of its types, including not only user-defined enums, structures and indeed unions can have methods - but also the built-in primitive types all have methods too.

    'F'.to_digit(16).unwrap() // is the 32-bit unsigned integer constant 15
Or maybe an even closer to the metal example: Rust's pointer provenance APIs get to provide a method on raw pointers which takes a closure to do stuff like hide boolean flag bits at the bottom of an aligned pointer. The fact that you're ultimately going to lower to an XOR on a CPU address register doesn't mean you shouldn't get method syntax, it's the 21st century.
show 1 reply
JackYoustrayesterday at 11:02 PM

Adding on, its also a bit much to say that Swift has a good level of sugar and reference an enum of all things. Swift's union type story is so poor that, instead of properly modeling state, people to this day still use masses of optional types in their views rather than an enum because actually using swift enums and protocols is so painful.

show 3 replies
saghmtoday at 2:25 AM

You're not wrong, but I think there's a subtle way people still might get confused about `Vec` versus `Box` with the way you've phrased it. I'd argue the important characteristic of `Vec` here isn't that it's indirection but specifically that it's sized at compile time. Compared to a `Box`, it does not provide meaningful indirection around types that are themselves not sized at compile time (e.g. dyn trait objects), and storing them inside a `Vec` itself will require a `Box` or something similar.

YmiYugyyesterday at 11:22 PM

I don't think that is true. Testing with rust 1.92

enum Tree<T> { Lead(T), Branch(Vec<Tree<T>>), }

works just fine, no superfluous Box needed.

show 1 reply
LukaDyesterday at 11:38 PM

You don't need Box here because Vec<T> is already a fixed size handle to heap data.

show 1 reply