Comment

Comment by couchand

I'm immediately turned off by the entirely gratuitous use of unsafe here. I clicked through to the linked Reddit discussion and I'm not convinced the author has really thought it through. Writing, "pedagogically, that's irrelevant to the post, so I didn't highlight it" misunderstands the pedagogy here.

However, there's some really neat stuff later, so it's wise to grit your teeth and get past it.

In case anyone else had the same reaction, here's an entirely-safe version of the first snippet that you can pretend replaced the original:

    // Each state is a unique type
    struct Receiving;
    struct Sending;

    // The state machine is parameterized by the state
    struct Channel<State> {
      chan: ...,
      _state: PhantomData<State>
    }

    // Methods for the state are uniquely associated with only the state
    impl Channel<Receiving> {
      // recv consumes ownership, ensuring old state is invalidated
      fn recv(mut self) -> (Channel<Sending>, String) {
        let Channel { chan, .. } = self;
        let msg = chan.recv();
        // The state type changes after executing a transition
        let next = Channel { chan, _state: PhantomData };
        (next, msg)
      }
    }

    impl Channel<Sending> {
      fn send(mut self, msg: String) -> Channel<Receiving> {
        let Channel { chan, .. } = self;
        chan.send(msg);
        Channel { chan, _state: PhantomData }
      }
    }

    #[test]
    fn channel_test() {
      let c: Channel<Sending> = Channel::new();
      let c: Channel<Receiving> = c.send("hi");
      let (c, msg) = c.recv();
      // and so on
    }
parent couchand 6 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton