scalafunctional-programmingstate

Do something only once, without state


I have the following situation:

Upon initialitation (actually first receive) of a socket I want to check something in the handshake (TLS), this has to be only checked upon connection initialization and not on every further receive.

Currently I have an odd:

   // this is happening outer scope
   var somethingThatGetsComputedinInit = 0

   def receive {
      if (init) {
        somethingThatGetsComputedinInit = doinitstuff(StuffIOnlyGetInitially)
        init = false
      }
    }

Although it would work, this smells so imperative and ugly. What would be a purely functional solution to this?


Solution

  • In your specific example, since you are using actors, you actually can swap out its implementation to model a state machine using "context.become and context.unbecome". There is an abstraction layer, Akka FSM, on top of this which provides a nicer syntax for doing exactly this type of thing.

    Example partially lifted from the Akka FSM docs:

    sealed trait State
    case object Initializing extends State
    case object Initialized extends State
    
    class Socket extends Actor with FSM[State, Option[Client]] {
    
      startWith(Initializing, None)
    
      when(Initializing) {
        case Event(msg: Connect, _) => createClient(msg).fold(stay) {
          client => 
            //Do more stuff
            goto(Initialized) using Some(client)
        }
      }
    
      when(Initialized) {
        case Event(msg: Receive, data@Some(client)) => 
          //Do more stuff using client
          stay using data
      }
    
      initialize()
    
    }