重复提示直至输入正确

发布于 2024-10-22 13:02:00 字数 712 浏览 2 评论 0原文

我最近正在学习 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 中是否有更好的方法来做到这一点?

I am picking up Scala recently. I have been used to C and Java before. I am wondering if there is a more elegant way of asking for input repeatedly until correct input is given.

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)

I am wondering if there is a better way of doing this in Scala?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

听不够的曲调 2024-10-29 13:02:00

您可以使用 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块来挑选出正确的输入;错误的输入只会被丢弃而不会被收集。在本例中,由于您想将其转换为整数,所以我只是传递该行。现在,我们只想要一个好的条目,因此我们获取下一个条目并将其转换为 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 将避免真正的函数调用,而只是再次跳转到开头(尾递归),因此不会溢出堆栈。

You could use either Iterate.continually to do the same thing over and over again until you impose some stopping condition (with dropWhile), or you could use Iterator.iterate to give you the previous line in case you want to use it in your error message:

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

The way this works is by starting with a readLine, and then if it needs another line it announces an error message based on the previous line (obviously that one was wrong) and reads another line. You then use a collect block to pick out your correct input; the wrong input just falls through without being collected. In this case, since you want to turn it into an integer, I'm just passing the line through. Now, we only want one good entry, so we get the next one and convert it to an int.

You could also use a recursive function to do a similar thing:

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

Here the trick is that in the case where you get wrong input, you just call the function again. Since that's the last thing that happens in the function, Scala will avoid a true function call and just jump to the beginning again (tail-recursion), so you won't overflow the stack.

心安伴我暖 2024-10-29 13:02:00

递归 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
  }
}

Recursion FTW, IMHO. Anyway, I'm gonna suggest a little modification upon Rex Kerr's recursive solution.

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
  }
}
故事和酒 2024-10-29 13:02:00
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
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
向日葵 2024-10-29 13:02:00

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() (将表达式转换为无限迭代器,该迭代器重复计算表达式)。

val operation = ... // as above
val input = Iterator.continually(readLine()).dropWhile(!operation.isDefinedAt(_)).next
operation(input)

通过使用 Iterator 的 collect 方法,您可以避免为 operation 指定名称。

Iterator.continually(readLine()).collect {
  case "1" => println("one")
}.next

Scala allows you to treat { case } blocks as instances of the PartialFunction trait. PartialFunction gives you a way to test whether the function is defined for a particular input. So you could rewrite like this:

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)

If you want to avoid having the mutable input variable, you can also use Iterator.continually() (turns an expression into an infinite Iterator which repeatedly evaluates the expression).

val operation = ... // as above
val input = Iterator.continually(readLine()).dropWhile(!operation.isDefinedAt(_)).next
operation(input)

And you can avoid having to give operation a name by using Iterator's collect method.

Iterator.continually(readLine()).collect {
  case "1" => println("one")
}.next
ゝ偶尔ゞ 2024-10-29 13:02:00

我会使用递归函数。像这样的东西:

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
}

I would use a recursive function. Something like this:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文