在foreach
声明中模式匹配后是否可以执行任何操作?
我想做一个匹配后的步骤,例如设置变量。我也想强制单位返回,因为foreach
是String =>单位,默认情况下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)
}
答案 0 :(得分:13)
我不知道您的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()的参数,则应使用{}
而不是()
。
答案 1 :(得分:3)
我不会回答你的问题,但我应该注意到在Scala中重新分配变量是一种不好的做法。我建议您重写代码以避免var
s。
首先,将您的字符串转换为其他字符串:
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
的实施会产生副作用。对你不好,因为这样的方法会使你的程序变得不可预测。通过使push
返回元组,您可以轻松避免副作用:
def push(s: String) = {
...
(ctm, last)
}
使用它像:
val (ctm, last) = out.push(str)
<强>更新强>
当然,需要副作用才能使程序变得有用。我只是说依赖于外部变量的方法比pure更不可预测,因此很难对其进行推理。测试方法没有副作用更容易。
是的,你应该更喜欢val
s而不是var
s,它会使你的程序更“功能”和无状态。无状态算法是线程安全且非常可预测的。
看起来你的程序本质上是有状态的。至少,尽量保持“功能”和无国籍状态:)
我建议的问题解决方案是:
// 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()
}
如果没有代码的上下文,很难对此进行测试,因此您应该自己满足自己的需求。我希望我已经回答了你的问题。