0

How can I convert this piece of code to functional approach? In akka I've seen Aktor::become() method that allows to overwrite the behaviour. How can I achieve something similar?

class Updater {
  var move: String = ""
  val step = 50

  def handler(key: KeyEvent) = {
    if (key.getCode.equals(KeyCode.Up.delegate)) move = "up"
    if (key.getCode.equals(KeyCode.Down.delegate)) move = "down"
    if (key.getCode.equals(KeyCode.Left.delegate)) move = "left"
    if (key.getCode.equals(KeyCode.Right.delegate)) move = "right"
  }

  def update(state: State): State = {
    val result = move match  {
      case "up" => State(state.x, state.y - step)
      case "down" => State(state.x, state.y + step)
      case "left" => State(state.x - step, state.y)
      case "right" => State(state.x + step, state.y)
      case _ => state
    }

    move = ""
    result
  }
}
1
  • 2
    This seems like it belongs on Code Review, btw. Instead of storing move in a field, you might be able to pass it as a parameter so you wouldn't have to reset it each time. Perhaps you can directly call the update method from the handler method if you changed the signature of the latter to include a State object? Also, you can use == instead of .equals, I'm pretty sure. Commented May 17, 2020 at 21:03

1 Answer 1

2

You can transform the behaviour and put a lambda that directly will do the behaviour expected. Something like this:

case class Updater(step = 50) {
  val goUp: State => State = x => State(state.x, state.y - step)
  val goDown: State => State = x => State(state.x, state.y + step)
  val goLeft: State => State = x => State(state.x - step, state.y)
  val goRight: State => State = x => State(state.x + step, state.y)
  val doNothing: State => State = x => x

  var behaviour: State => State = doNothing

  def handler(key: KeyEvent) = 
    behaviour = key.getCode.equals match{
    case KeyCode.Up.delegate => goUp
    case KeyCode.Down.delegate => goDown
    case KeyCode.Left.delegate => goLeft
    case KeyCode.Right.delegate => goRight
    case _ => doNothing
  }

  def update(state: State): State = behaviour(state)
}
Sign up to request clarification or add additional context in comments.

5 Comments

that looks great but I have to bind that handler to scene (scalafx) like that: scene.onKeyPressed = updater.handler So I would have to reassign this every time. So this is not immutable anyway :) I mean on the scalafx side
if I update instance then I still got variable there :)
So you are going to add an instance of Updater with a key assigned, and then it only will call the update method?
I may pass scene to the Updater and then set new handler to it every time behaviour changes. It is out of my control anyway and it is mutable by design. Is this valid solution?
We've been writting simultaneously. I will describe you my goal. I have an immutable state. Updater generates new state based on old state and the key pressed. Keyboard input is controlled by scalafx (Scene object) and I only may assign own handler to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.