‹ BackHN Continuity

Thread

Rusty thoughts on "Parse, don't validate"

95 points · 47 comments · ingve

  1. articulatepang · · focus · HN ↗
    I prefer a slightly more general rule: Make Illegal States Unrepresentable. The "Parse, don't validate" rule is a special case of MISU.

    What's the difference? MISU applies even when there's no parsing-like transformation happening. For example, if you have a variable that represents the current state of a network connection, and let's say it can be Disconnected, or Connected to some IP address (this is an oversimplification).

    Then one way to do it would be

      struct {
        connected: bool,
        peer_ip: int32
      }
    
    The trouble is that this allows us to represent an illegal/meaningless state: we're disconnected but there's still some junk old peer_ip hanging in there. Even worse, we might have written

      struct {
        connected: bool,
        peer_ip: Option<int32>
      }
    
    Now we could have connected = true but peer_ip = None.

    The solution is to use a sum type:

      type connection = 
         Disconnected
       | Connected of int32
    
    (sorry for using made-up syntax; I hope it's clear to anyone familiar with Rust.)

    "Make Illegal States Unrepresentable" applies throughout your program, at every interface between modules or functions in the program, including but not limited to parsing input.

    1. laszlokorte · · focus · HN ↗
      In rust this would simply be

         enum ConnectionStste {
              Connected(u32),
              Disconnected
          }
      1. slopinthebag · · focus · HN ↗
        or

           struct Connected { peer_ip: u32 }
           struct Disconnected;
           struct Connection<State> { state: State }
        1. sendfoods · · focus · HN ↗
          Wouldn’t peer: Option<int32> be enough to represent this?

          None = disconnected

          1. treyd · · focus · HN ↗
            Yes, it'd probably be compiled into very machine code. However defining an enum for it puts the intention into the source code more explicitly, so that's considered the more idiomatic way. You'd probably have a `fn peer_id(&self) -> Option<Inet4Addr>` accessor that you'd use in the case where you'd want the Option.
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.