0

次の Scala コードでは、val に代入できないというコンパイル エラーが発生します。

簡単な例:

class State {
  val a = 1
  val b = 2

  def compute( res: =>Int, add : Int ): Unit = {
    res = add + 123456
  }

  compute(a,b)
  compute(b,a)
}

私の実際の使用に近い例:

class Editor {
  var str:String = ""
  var cursor:Int = 0

  case class UndoState(str:String, cursor:Int)

  var undoState = Seq[UndoState]()
  var redoState = Seq[UndoState]()

  def undo(): Unit = if (undoState.nonEmpty) {
    redoState = UndoState(str,cursor) +: redoState
    str = undoState.head.str
    cursor = undoState.head.cursor
    undoState = undoState.tail
  }

  def redo(): Unit = if (redoState.nonEmpty) {
    undoState = UndoState(str,cursor) +: undoState
    str = redoState.head.str
    cursor = redoState.head.cursor
    redoState = redoState.tail
  }
}

元に戻す/やり直しは非常に似ているため、共通コードを関数に抽出したいと思います。これは、ソース/ターゲットのペアをredoState/として渡しundoState、その逆を行いたいと考えていました。

関数が何かを格納する場所を特定する方法はありますか? (C++ では、この状況ではメンバーへのポインターを渡します)。

4

3 に答える 3

1

戻り値を使用します。

def compute( add : Int ): Int = {
  add + 123456
}

val a = compute(b)
val b = compute(a)

C++ で行うような参照渡しは、Scala では実行できず、通常はやりたいことでもありません。ただし、変更可能なフィールドへの参照を含むコンテナーを渡すことができます。

class Box(var value: Int)

def compute( box: Box, add : Box): Unit = {
  box.value = add.value + 123456
}

val a = new Box(1)
val b = new Box(2)
compute(a, b)
compute(b, a)

または (わずかなバリエーション) make computemember of Box:

class Box(var value: Int) {
  def compute(add: Box): Unit = {
    value = add.value + 123456
  }
}

val a = new Box(1)
val b = new Box(2)
a.compute(b)
b.compute(a)
于 2015-01-22T13:23:53.950 に答える
1

新しい状態を設定する関数を作成して渡すことができます (取り消しまたはやり直し)。

...
var undoState = Seq[UndoState]()
var redoState = Seq[UndoState]()

def anywaydo(set: (Seq[UndoState]) => Unit) {
  set(...)
  ...
}

def undo {
  anywaydo((state) => undoState = state)
}
于 2015-01-22T13:57:33.393 に答える
1

(不変) seq の代わりに状態 (可変) スタックを作成し、それらを共通関数に渡して操作することができます。

  def undoredo(states: (Stack[UndoState], Stack[UndoState])): Unit = states match {
      case (Stack(), _) => ()
      case (from, to) => 
          to.push(UndoState(str,cursor))
          val state = from.pop
          str = state.str
          cursor = state.cursor              
  }

  def undo() = undoredo(undoState -> redoState)
  def redo() = undoredo(redoState -> undoState)

または、scala の派手な「DSL ライクな」機能が好きなら、次のような楽しい方法でこれを行うことができます。

implicit class StateStack(from: Stack[UndoState]) {
    def ->(to: Stack[UndoState]): Unit = if(from.nonEmpty) {  
        to.push(UndoState(str,cursor)) 
        val state = from.pop
        str = state.str
        cursor = state.cursor            
    }
  }

すると、undoState -> redoState「元に戻す」とか「やり直し」とかredoState -> undoState……

于 2015-01-22T15:07:40.543 に答える