Remix.run Logo
▲ Fluorescence 2 hours ago

Not sure that type is good advice:

    pub struct NonEmpty<T> {
        pub head: T,
        pub tail: Vec<T>,
    }
You'd have to manually implement the traits to support the ergonomics of slices and iteration and costly reallocation if you need to pass ownership as a Vec:

I'd expect:

    pub struct NonEmpty<T> {
        v: Vec<T>,
    }
The constructor would enforce the invariant and then you'd impl Deref and DerefMut for [T] to gain normal len/is_empty/indexing/iteration, passing as &[T] to other funcs and mutating values (which can't break the invariant).

To mutate length while preserving the invariant it's dealers choice e.g.

- add .into_vec() for unwrap/mutate/rewrap

- add invariant preserving mutators of your choice

▲ 21 minutes ago | parent | next [-]
[deleted]
▲Rusky 27 minutes ago | parent | prev | next [-]

There's a whole follow up post about this: https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-...

▲eptcyka an hour ago | parent | prev [-]

Which deref must I use to get most of the existing interface sans `retain()`?

▲Fluorescence 21 minutes ago | parent [-]

Deref/DerefMut enables implicit type coercion rather than exposing an interface. You can choose the target type and immutable/mutable but not parts of the target type.

You can use all the slice reference methods (that do not require ownership) with:

    impl<T> Deref for NonEmpty<T> {
        type Target = [T];

        fn deref(&self) -> &Self::Target {
            &self.v
        }
    }

    impl<T> DerefMut for NonEmpty<T> {
        fn deref_mut(&mut self) -> &mut [T] {
            &mut self.v
        }
    }
https://doc.rust-lang.org/std/primitive.slice.html

If you DerefMut to a Vec then you won't be able to preserve the invariant.

If you want control over methods to expose then you need wrapper methods for those you want. If you want to expose some of the traits the inner type implements then there are likely derive macros available e.g. with derive_more you could expose just indexing as:

    #[derive(Index, IndexMut)]
    struct MyVec(Vec<i32>);