6

foreachステートメント内のパターン マッチの後に何かできることはありますか?
変数を設定するなど、一致後のステップを実行したいと考えています。また、my は String => Unit であるため、Unit を強制的にforeach返したいと考えています。デフォルトでは、Scala は最後のステートメントを返したいと考えています。

ここにいくつかのコードがあります:

    Iteratee.foreach[String](_ match {
      case "date" => out.push("Current date: " + new Date().toString + "<br/>")
      case "since" => out.push("Last command executed: " + (ctm - last) + "ms before now<br/>")
      case unknow => out.push("Command: " + unknown + " not recognized <br/>")
    } // here I would like to set "last = ctm" (will be a Long) 
    ) 

更新: 新しいコードとコンテキスト。また、新しい質問が追加されました:)それらはコメントに埋め込まれています。

def socket = WebSocket.using[String] { request =>

 // Comment from an answer bellow but what are the side effects?
 // By convention, methods with side effects takes an empty argument list
 def ctm(): Long = System.currentTimeMillis

 var last: Long = ctm

 // Command handlers
 // Comment from an answer bellow but what are the side effects?
 // By convention, methods with side effects takes an empty argument list
 def date() = "Current date: " + new Date().toString + "<br/>"
 def since(last: Long) = "Last command executed: " + (ctm - last) + "ms before now<br/>"
 def unknown(cmd: String) = "Command: " + cmd + " not recognized <br/>"

 val out = Enumerator.imperative[String] {}

 // How to transform into the mapping strategy given in lpaul7's nice answer.
 lazy val in = Iteratee.foreach[String](_ match {
   case "date" => out.push(date)
   case "since" => out.push(since(last))
   case unknown => out.push(unknown)
 } // Here I want to update the variable last to "last = ctm"
 ).mapDone { _ =>
   println("Disconnected")
 }

 (in, out)
}
4

2 に答える 2

18

私はあなたが何であるかわかりませんがctm、あなたはいつでもこれを行うことができます:

val xs = List("date", "since", "other1", "other2")

xs.foreach { str =>

    str match {
        case "date"  => println("Match Date")
        case "since" => println("Match Since")
        case unknow  => println("Others")
    } 

    println("Put your post step here")
}

foreach()の引数としてコードのブロックを使用する場合は、{}代わりに使用する必要があることに注意してください。()

于 2012-07-03T01:30:48.983 に答える
3

あなたの質問には答えませんが、Scala で変数を再割り当てすることは悪い習慣であることに注意してください。sを回避するためにコードを書き直すことをお勧めしますvar

まず、文字列を別のものに変換します。

val strings = it map {
  case "date" => "Current date: " + new Date().toString + "<br/>"
  case "since" => "Last command executed: " + (ctm - last) + "ms before now<br/>"
  case unknow => "Command: " + unknown + " not recognized <br/>"
}

次は押してみよう

strings map { out.push(_) }

の実装にpushは副作用があるようです。そのような方法はあなたのプログラムを予測不可能にするので、あなたにとって悪いことです。pushreturn をタプルにすることで、副作用を簡単に回避できます。

def push(s: String) = {
  ...
  (ctm, last)
}

そしてそれを次のように使用します:

val (ctm, last) = out.push(str)

アップデート:

もちろん、プログラムを有用なものにするためには副作用が必要です。外部変数に依存するメソッドは、純粋なメソッドよりも予測しにくいということだけを意味していました。それについて推論するのは難しいです。副作用のないメソッドをテストする方が簡単です。

はい、vals よりも s を優先する必要がありvarます。これにより、プログラムがより「機能的」でステートレスになります。ステートレス アルゴリズムはスレッド セーフであり、非常に予測可能です。

あなたのプログラムは本質的にステートフルのようです。少なくとも、できる限り「機能的」でステートレスな状態を保つようにしてください:)

あなたの問題の私が提案する解決策は次のとおりです。

// By convention, methods with side effects takes an empty argument list
def ctm(): Long = // Get current time

// Command handlers
def date() = "Current date: " + new Date().toString + "<br/>"
def since(last: Long) = "Last command executed: " + (ctm() - last) + "ms before now<br/>"
def unknown(cmd: String) = "Command: " + unknown + " not recognized <br/>"    

  // In your cmd processing loop

  // First, map inputs to responses
  val cmds = inps map {
    case "date"  => date()
    case "since" => since(last)
    case unk     => unknown(unk)
  }

  // Then push responses and update state
  cmds map { response =>
    out.push(response)
    // It is a good place to update your state
    last = ctm()
  }

コードのコンテキストなしでこれをテストするのは難しいため、自分のニーズに合わせて調整する必要があります。私はあなたの質問に答えたことを願っています。

于 2012-07-03T02:00:32.867 に答える