我最近正在接收Scala。我以前习惯了C和Java。我想知道是否有更优雅的方式反复询问输入,直到给出正确的输入。
val choiceType = {
var in = ""
var pass = false
do {
in = readLine()
pass = in match {
case "1" => println("Not implemented"); true
case "2" => println("Not implemented"); true
case "3" => println("Not implemented"); true
case "4" => println("Not implemented"); true
case "5" => println("Thanks for using."); true
case _ => println("Error input. Please enter again. (Possible value: 1 - 5)"); false
}
} while (!pass)
in.toInt
}
if (choiceType == 5) System.exit(0)
我想知道在Scala中是否有更好的方法吗?
答案 0 :(得分:7)
你可以使用Iterate.continually
一遍又一遍地做同样的事情,直到你施加一些停止条件(使用dropWhile
),或者你可以使用Iterator.iterate
给你以前的如果您想在错误消息中使用它,请使用以下行:
val choiceType = Iterator.iterate(readLine())(line => {
println("Error input: "+line+". Please enter again (from 1-5).)")
readLine()
}).collect(line => line match {
case "1" => println("Not implemented"); line
case "2" => println("Not implemented"); line
case "3" => println("Not implemented"); line
case "4" => println("Not implemented"); line
case "5" => println("Thanks for using."); line
}).next.toInt
这种方法的工作方式是从readLine开始,然后如果它需要另一行,它会根据前一行宣布一条错误消息(显然是错误的)并读取另一行。然后使用collect
块来选择正确的输入;错误的输入只是没有被收集而落空。在这种情况下,因为你想把它变成一个整数,我只是通过这条线。现在,我们只想要一个好的条目,所以我们得到next
并将其转换为int。
你也可以使用递归函数来做类似的事情:
def getChoice: String = {
val line = readLine()
line match {
case "1" => println("Not implemented"); line
case "2" => println("Not implemented"); line
case "3" => println("Not implemented"); line
case "4" => println("Not implemented"); line
case "5" => println("Thanks for using."); line
case _ => println("Error, blah blah."); getChoice
}
}
val choiceType = getChoice.toInt
这里的诀窍是,在输入错误的情况下,您只需再次调用该函数。由于这是函数中发生的最后一件事,Scala将避免真正的函数调用并再次跳转到开头(尾递归),因此您不会溢出堆栈。
答案 1 :(得分:2)
递归FTW,恕我直言。无论如何,我会建议对Rex Kerr的递归解决方案进行一些修改。
def getChoice: String = {
val line = readLine()
line match {
case "1" | "2" | "3" | "4" => println("Not implemented"); line
case "5" => println("Thanks for using."); line
case _ => println("Error, blah blah."); getChoice
}
}
答案 2 :(得分:2)
import io.Source.stdin
val choices = stdin.getLines.collect {
case "1" => println("Not implemented")
case "2" => println("Not implemented")
case "3" => println("Not implemented")
case "4" => println("Not implemented")
case "5" => println("Thanks for using.")
System.exit(0)
}
choices.next
答案 3 :(得分:1)
我会使用递归函数。像这样:
def getChoice: Int = readLine match {
case x if x < "6" && x > "0" && x.length == 1 => x.toInt
case _ => println("Error, Possible values: (1 - 5)")
getChoice
}
答案 4 :(得分:1)
Scala允许您将{ case }
块视为PartialFunction特征的实例。 PartialFunction为您提供了一种测试函数是否为特定输入定义的方法。所以你可以像这样重写:
val operation: PartialFunction[String, Unit] = {
case "1" => println("Not implemented")
case "2" => println("Not implemented")
case "3" => println("Not implemented")
case "4" => println("Not implemented")
case "5" => println("Thanks for using."); System.exit(0)
}
var input: String = ""
do {
input = readLine()
} while(!operation.isDefinedAt(input))
operation(input)
如果你想避免使用可变input
变量,你也可以使用Iterator.continually()(将表达式转换为无限的Iterator,重复计算表达式)。
val operation = ... // as above
val input = Iterator.continually(readLine()).dropWhile(!operation.isDefinedAt(_)).next
operation(input)
您可以避免使用Iterator的operation
方法为collect
命名。
Iterator.continually(readLine()).collect {
case "1" => println("one")
}.next