0

scala のレンズ ライブラリである monocle を使用して、コードの出現から12 日目にコードをリファクタリングしました。

このコードを改善することは可能ですか:

  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)
  }

もう 1 つの質問:Map.withDefaultValueモノクルを使用する方法はありますか?

完全なコードはこちら: https://gist.github.com/YannMoisan/b8ba25afc041d88706545527d9ec1988

4

1 に答える 1

-1

2 つのフィールドの処理が分離されるため、2 番目の方法を使用することをお勧めします。ただし、関数は ( andThen) の順序で解釈するのではなく、 と として結合する必要がありPartialFunctionます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 に答える