从游戏动作中显式返回 [英] Explicit return from play action

查看:15
本文介绍了从游戏动作中显式返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下操作

def login: Result = Action(parse.json) { request =>if (/* 让我们说这是一些验证 */) {返回 BadRequest("坏")}好的(一切都好")}

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

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

我还需要从 if 返回...我不想在 if 之后写 else,因为在一些复杂的函数很可能我会有很少的 if 语句来中断操作,如果我使用 if/else 方法,代码将是一场噩梦.

解决方案

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

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

def loop() = {for (i <- 0 到 20) {if (someCondition) 返回}}

那个循环实际上相当于:

(0 到 20).foreach { i =>if (someCondition) 返回 }

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

所以你有一个匿名函数:

Action(parse.json) { request =>......这里的这个...... }

在该函数中,您使用了return",它在幕后触发了异常.

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

Action(parse.json) { request =>if (/* 让我们说这里是一些验证 */)错误请求(坏")别的好的(一切都好")}

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

<块引用>

此外,我需要从 if 返回...我不想在 if 之后写 else,因为在一些更复杂的函数中,我很可能只有很少的 if 语句应该中断操作,如果我使用 if/否则,代码将是一场噩梦.

这是错误的,我真的很讨厌使用依赖返回、中断或继续来使逻辑短路的代码,因为复杂的逻辑变得混乱,我想清楚地看到:

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

使用 return、break 或 continue 会破坏所有 3 点的清晰度.它们并不比 GOTO 跳跃好多少.如果你有复杂的功能,如果阅读开始成为一个问题,就把它们分解成多个功能.

此外,比多个if/else"分支更好的是match"语句.一旦习惯了它们,您就会爱上它们,尤其是考虑到编译器甚至可以在您缺少分支的某些情况下保护您.

I have following action

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

  Ok("all ok")
}

This is giving me an Error. Intellij is suggesting Action[JsValue] type. When I say return will be of that type, I am getting again error on BadRequest line, because types doesn't match.

I tried searching about this problem, and I found some answers which are suggesting to set Action[AnyContent] as return type. But I am STILL getting error.

Also I need to return from if...I don't want to write else after that if, because in some more complex function most probably I will have few if statements which should break action, and if I use if/else approach, code will be nightmare.

解决方案

Of course it does. In Scala, a "return" statement inside a nested anonymous function is implemented by throwing and catching a NonLocalReturnException. It says so in the Scala Language Specification, section 6.20.

This is done because of for comprehensions, for people to be able to write code like this:

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

That loop is actually equivalent to:

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

Can you see the anonymous function? Can you see that the "return" in question doesn't refer to returning from that anonymous function alone? In my opinion this was a design mistake. On the other hand, in a language like Scala, "return" isn't needed anyway.

So you have an anonymous function in there:

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

And inside that function you're using "return" which under the hood triggers an exception.

So the general rule of thumb in Scala - NEVER, EVER USE RETURN. It's an expression-oriented language anyway. You don't need it.

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

There, much more idiomatic. BTW - you also don't have "break" or "continue". Get used to working without them. Also, about your opinion:

Also I NEED to return from if...I don't want to write else after that if, because in some more complex function most probably I will have few if statements which should break action, and if I use if/else approach, code will be nightmare.

That is wrong and I REALLY HATE working with code that relies on return, break or continue for short-circuiting the logic PRECISELY because complex logic gets messy and I want to have a clear view of:

  1. invariants, if we are talking about a loop
  2. exit conditions
  3. the branches / paths

Using return, break or continue destroys clarity on all 3 points. They aren't much better than GOTO jumps. And if you have complex functions, break them into multiple functions if reading it starts to become a problem.

Also, much better than multiple "if/else" branches are "match" statements. Once you get used to them, you'll love them, especially given that the compiler can even protect you in some cases in which you're missing a branch.

这篇关于从游戏动作中显式返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆