0

在代码出现的第 12 天,我使用 monocle(scala 中的一个镜头库)重构了我的代码。

是否可以改进此代码:

  type Register = String
  type Mem = Map[String, Int]

  @Lenses
  case class State(mem: Mem, pointer: Int)

  def processInstruction(instructions: Seq[Instruction]): State => State = { s =>
    (instructions(s.pointer) match {
      case Inc(r) =>
        State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ + 1))
      case Dec(r) =>
        State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ - 1))
      case CpyInt(v, to) =>
        State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(v))
      case CpyReg(from, to) =>
        State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(s.mem(from)))
      case Jnz(r, v) => if (r != "1" && s.mem(r) == 0)
        State.pointer.modify( _ + 1)
      else
        State.pointer.modify( _ + v )
    }).apply(s)
  }

而这里又是一个尝试,分离每个字段的修改

  def processInstruction2(instructions: Seq[Instruction]): State => State = { s =>
    val ptr = instructions(s.pointer) match {
      case Jnz(r, v) if !(r != "1" && s.mem(r) == 0) => State.pointer.modify(_ + v)
      case _ => State.pointer.modify(_ + 1)
    }

    val mem = instructions(s.pointer) match {
    case Inc(r) => (State.mem composeLens at(r)).modify(_.map(_ + 1))
    case Dec(r) => (State.mem composeLens at(r)).modify(_.map(_ - 1))
    case CpyInt(v, to) => (State.mem composeLens at(to)).set(Some(v))
    case CpyReg(from, to) => (State.mem composeLens at(to)).set(Some(s.mem(from)))
    case _ => identity[State]
  }
    (ptr andThen mem)(s)
  }

还有一个问题:有没有办法Map.withDefaultValue与单片眼镜一起使用?

完整代码在这里:https ://gist.github.com/YannMoisan/b8ba25afc041d88706545527d9ec1988

4

1 回答 1

-1

您可能想要使用第二种方法,因为它分离了两个字段的处理。但是,这些函数不应按顺序 ( andThen) 解释,而应将它们组合为PartialFunctions 和orElse

def processInstruction3(instructions: Seq[Instruction]): State => State = {
  val ptr: PartialFunction[Instruction, State => State] = {
    case Jnz(r, v) =>
      State.pointer.modify(_ + v)
  }

  val incPointer: State => State = State.pointer.modify( _ + 1)
  def reg(r: String): Lens[State, Option[Int]] = State.mem composeLens at(r)
  val mem: PartialFunction[Instruction, State => State] = {
    case Inc(r) => reg(r).modify(_.orElse(Option(0)).map(_ + 1))
    case Dec(r) => reg(r).modify(_.orElse(Option(0)).map(_ - 1))
    case CpyInt(v, to) => reg(to).set(Some(v))
    case CpyReg(from, to) => s => reg(to).set(reg(from).get(s))(s)
  }
  val interpreter = ptr orElse (mem andThen (_ andThen incPointer))
  s => instructions.foldLeft(s)((s, i) => interpreter(i)(s))
}

更新(在 Yann Moisan 评论之后)

如果用户程序出现无限循环,执行可能不会终止。因此,我们需要一些递归函数来代替foldLeft指针提取下一条指令:

@tailrec
def loop(s: State): State = {
  if(s.pointer>=instructions.length)
    s
  else {
    val instruction = instructions(s.pointer)
    val nextState = interpreter(instruction)(s)
    loop(nextState)
  }
}
loop _

(最后一行processInstruction3应该换成上面的代码)

于 2017-01-04T08:37:00.070 回答