scala foreach中的模式匹配,然后做最后一步
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11302979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pattern match in foreach and then do a final step
提问by Farmor
Is it possible to do anything after a pattern match in a foreachstatement?
I want to do a post match step e.g. to set a variable. I also want to force a Unit return as my foreachis String => Unit, and by default Scala wants to return the last statement.
在foreach语句中的模式匹配之后可以做任何事情吗?
我想做一个匹配后步骤,例如设置一个变量。我还想强制一个 Unit 返回,因为我foreach是 String => Unit,默认情况下 Scala 想要返回最后一个语句。
Here is some code:
这是一些代码:
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)
)
UPDATED:New code and context. Also new questions added :) They are embedded in the comments.
更新:新代码和上下文。还添加了新问题 :) 它们嵌入在评论中。
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)
}
回答by Brian Hsu
I don't know what your ctmis, but you could always do this:
我不知道你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")
}
Note you should use {}instead of ()when you want use a block of code as the argument of foreach().
请注意{},()当您想使用代码块作为 foreach() 的参数时,您应该使用代替。
回答by lambdas
I will not answer your question, but I should note that reassigning variables in Scala is a bad practice. I suggest you to rewrite your code to avoid vars.
我不会回答你的问题,但我应该注意到在 Scala 中重新分配变量是一种不好的做法。我建议您重写代码以避免vars。
First, transform your strings to something else:
首先,将您的字符串转换为其他内容:
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/>"
}
Next, push it
接下来推一下
strings map { out.push(_) }
It looks like your implementation of pushhas side effects. Bad for you, because such methods makes your program unpredictable. You can easily avoid side effects by making pushreturn a tuple:
看起来您的实现push有副作用。对您不利,因为此类方法使您的程序不可预测。您可以通过push返回一个元组来轻松避免副作用:
def push(s: String) = {
...
(ctm, last)
}
And using it like:
并使用它:
val (ctm, last) = out.push(str)
Update:
更新:
Of course side effects are needed to make programs useful. I only meant that methods depending on outer variables are less predictable than pureone, it is hard to reason about it. It is easier to test methods without side effects.
当然,要使程序有用,需要副作用。我的意思是,依赖于外部变量的方法不如纯方法可预测,这很难推理。更容易测试没有副作用的方法。
Yes, you should prefer vals over vars, it makes your program more "functional" and stateless. Stateless algorithms are thread safe and very predictable.
是的,您应该更喜欢vals 而不是vars,它使您的程序更“实用”和无状态。无状态算法是线程安全的并且非常可预测。
It seems like your program is stateful by nature. At least, try to stay as "functional" and stateless as you can :)
看起来您的程序本质上是有状态的。至少,尽量保持“功能性”和无状态:)
My suggested solution of your problem is:
我建议的解决您的问题的方法是:
// 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()
}
It is hard to test this without context of your code, so you should fit it to your needs yourself. I hope I've answered your question.
在没有代码上下文的情况下很难对此进行测试,因此您应该自己根据自己的需要进行测试。我希望我已经回答了你的问题。

