‹ BackHN Continuity

Thread

Rusty thoughts on "Parse, don't validate"

95 points · 47 comments · ingve

  1. Fluorescence · · focus · HN ↗
    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

    1. eptcyka · · focus · HN ↗
      Which deref must I use to get most of the existing interface sans `retain()`?
      1. Fluorescence · · focus · HN ↗
        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
                }
            }
        
        <a href="https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.slice.html" rel="nofollow">https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.slice.html

        If you DerefMut to a Vec then you won&#x27;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&lt;i32&gt;);
        1. eptcyka · · focus · HN ↗
          The reason I am asking is because I strongly believe to achieve the semantics of the type, just derefing to a Vec will not be sufficient.
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.