游戏动作的明确回报

use*_*343 1 scala playframework

我有以下行动

def login: Result = Action(parse.json) { request =>
  if (/* Let's we say here is some validation */) {
    return BadRequest("bad")
  }

  Ok("all ok")
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误.Intellij建议使用Action[JsValue]类型.当我说返回将是那种类型时,我再次出现错误BadRequest,因为类型不匹配.

我试着搜索这个问题,我找到了一些建议设置Action[AnyContent]为返回类型的答案.但我仍然得到错误.

另外我需要从if... 返回...我不想else在那之后写if,因为在一些更复杂的函数中,我很可能会有很少的if语句应该打破动作,如果我使用if/else方法,代码将是噩梦.

Ale*_*lcu 6

当然可以.在Scala中,嵌套匿名函数中的"return"语句是通过抛出和捕获NonLocalReturnException来实现的.它在Scala语言规范第6.20节中这样说.

这样做是因为为了理解,人们能够编写如下代码:

def loop() = {
  for (i <- 0 until 20) {
    if (someCondition) return
  }
}
Run Code Online (Sandbox Code Playgroud)

该循环实际上相当于:

(0 until 20).foreach { i => if (someCondition) return }
Run Code Online (Sandbox Code Playgroud)

你能看到匿名功能吗?你能看到有问题的"回归"并不是指单独从匿名函数返回吗?在我看来,这是一个设计错误.另一方面,在像Scala这样的语言中,无论如何都不需要"返回".

所以你有一个匿名函数:

Action(parse.json) { request => ... this one here ... }
Run Code Online (Sandbox Code Playgroud)

在该函数内部,您正在使用"返回",它会触发异常.

因此,Scala的一般经验法则 - 永远不要使用返回.无论如何,这是一种面向表达的语言.你不需要它.

Action(parse.json) { request =>
  if (/* Let's we say here is some validation */) 
    BadRequest("bad")
  else
    Ok("all ok")
}
Run Code Online (Sandbox Code Playgroud)

在那里,更加惯用.顺便说一句 - 你也没有"休息"或"继续".习惯没有他们的工作.另外,关于你的意见:

另外我需要从if返回...如果我之后不想写别的,因为在一些更复杂的函数中,我很可能会有很少的if语句应该破坏动作,如果我使用if/else方法,代码将是噩梦.

这是错误的,我真的很讨厌使用依赖于返回,中断或继续的代码,因为复杂的逻辑变得混乱,我希望有一个清晰的视图:

  1. 不变量,如果我们谈论一个循环
  2. 退出条件
  3. 分支/路径

使用返回,中断或继续破坏所有3点的清晰度.它们并不比GOTO跳跃好多少.如果你有复杂的功能,如果阅读它会开始成为一个问题,将它们分成多个功能.

此外,比多个"if/else"分支更好的是"匹配"语句.一旦你习惯了它们,你会爱上它们,特别是考虑到编译器甚至可以在你错过分支的某些情况下保护你.

  • @ user232343 3年前,当我开始使用Scala时,我有同感.现在我认为它是它的一个特点.Scala主要是一种功能性/表达式语言,试图吸收它并保留判断,直到你获得一些经验.我保证你会喜欢它:-) (2认同)

win*_*ner 6

您无法return在此上下文中使用,因为Scala编译器会误解您的意思return.您打算return从要传递的函数返回Action.apply,即此块:

{ request =>
  if (/* Let's we say here is some validation */) {
    return BadRequest("bad")
  }

  Ok("all ok")
}
Run Code Online (Sandbox Code Playgroud)

但是,在Scala return中不能用于return函数,只能用于方法.任何都return被解释为从最近的封闭方法返回.在这种情况下,编译器认为您正在返回login.

你输的错了login.login应该是一个Action[JsValue].使用正确的类型,编译器会抱怨返回,因为您返回的是SimpleResult而不是预期的Action[JsValue].对于不正确的类型Result,编译器接受return但后来不满意,因为返回值Action.apply始终是一种类型Action.

这样return工作的原因是支持循环,如:

def allPositive(l: List[Int]): Boolean = {
  l.foreach { x => if (x < 0) return false }
  true
}
Run Code Online (Sandbox Code Playgroud)

但使用return是单一的.在return上述环与异常抛出来实现,因此是无效的.并且return可以使代码非常混乱:

def login: Result = Action(parse.json) { request =>
  /*
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL with return  OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE WALL OF CODE
  */

  Ok("all ok")
}
Run Code Online (Sandbox Code Playgroud)

显然这login总是会回归Ok.哦等等......有一个return埋在那里.