游戏动作的明确回报

时间:2014-06-26 16:32:10

标签: scala playframework

我有以下行动

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

  Ok("all ok")
}

这给了我一个错误。 Intellij建议Action[JsValue]类型。当我说返回属于那种类型时,我在BadRequest行再次出错,因为类型不匹配。

我尝试搜索此问题,并找到了一些建议将Action[AnyContent]设置为返回类型的答案。但我仍然得到错误。

此外,我需要从if返回...我不想在else之后写if,因为在一些更复杂的函数中,我很可能会很少if {1}}应该破坏行动的陈述,如果我使用if/else方法,代码将成为噩梦。

2 个答案:

答案 0 :(得分:6)

当然可以。在Scala中,嵌套匿名函数中的“return”语句是通过抛出和捕获NonLocalReturnException来实现的。它在Scala Language Specification第6.20节中这样说。

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

def loop() = {
  for (i <- 0 until 20) {
    if (someCondition) return
  }
}

该循环实际上相当于:

(0 until 20).foreach { i => if (someCondition) return }

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

所以你有一个匿名函数:

Action(parse.json) { request => ... this one here ... }

在该功能中你正在使用“返回”,它会触发异常。

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

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

那里有更多的惯用语。顺便说一句 - 你也没有“休息”或“继续”。习惯没有他们的工作。另外,关于你的意见:

  

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

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

  1. 不变量,如果我们谈论循环
  2. 退出条件
  3. 分支/路径
  4. 使用return,break或continue会破坏所有3点的清晰度。它们并不比GOTO跳跃好多少。如果你有复杂的功能,如果阅读它会开始成为一个问题,将它们分成多个功能。

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

答案 1 :(得分:5)

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

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

  Ok("all ok")
}

但是,在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
}

但使用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")
}

显然,此login始终返回Ok。哦等等......那里埋有return