scala:提高这段代码的可读性和风格
发布时间:2020-12-16 18:03:45 所属栏目:安全 来源:网络整理
导读:以下是一个非常常见的播放框架2控制器: def save(ideaId : Long) = CORSAction { request = Idea.findById(ideaId).map { idea = request.body.asJson.map { json = json.asOpt[Comment].map { comment = comment.copy(idea = idea).save.fold( errors = Js
以下是一个非常常见的播放框架2控制器:
def save(ideaId : Long) = CORSAction { request => Idea.findById(ideaId).map { idea => request.body.asJson.map { json => json.asOpt[Comment].map { comment => comment.copy(idea = idea).save.fold( errors => JsonBadRequest(errors),comment => Ok(toJson(comment).toString) ) }.getOrElse (JsonBadRequest("Invalid Comment entity")) }.getOrElse (JsonBadRequest("Expecting JSON data")) }.getOrElse (JsonBadRequest("Could not find idea with id '%s'".format(ideaId))) } 我发现所有嵌套的.maps都有点烦人,我也发现每个错误处理都在底部有点乏味 您将如何改进它以使其更具可读性,同时保持功能惯用的scala代码? 我想也许是这样的(它是seudo代码,仍然无法编译) def save(ideaId : Long) = CORSAction { request => val idea = Idea.findById(ideaId).getOrElse( return JsonBadRequest("Could not find idea with id '%s'".format(ideaId))) val json = request.body.asJson.getOrElse( return JsonBadRequest("Expecting JSON data")) val comment = json.asOpt[Comment].getOrElse( return JsonBadRequest("Invalid Comment entity")) comment.copy(idea = idea).save.fold( errors => JsonBadRequest(errors),comment => Ok(toJson(comment).toString) ) } ps:我知道避免退货声明会好得多…… 解决方法
首先要简化.假设我有三个方法接受一个String并返回一个Option [String]:
def foo(s: String): Option[String] = if (s.size >= 4) Some(s + "1") else None def bar(s: String): Option[String] = if (s(0) != 'A') Some(s + "2") else None def baz(s: String): Option[String] = if (s toSet ' ') Some(s + "3") else None 我想要一个方法,通过这些方法管理字符串,并返回相应的错误消息,如果我一路上得到一个无.我可以这样写: def all(s: String): Either[String,String] = foo(s).map { x => bar(x).map { y => baz(y).map { z => Right(z) } getOrElse Left("Doesn't contain a space!") } getOrElse Left("Starts with an A!") } getOrElse Left("Too short!") 但是,这不是很好.我们可以使用for-comprehension和Option上的toRight方法来编写更清晰的版本: def all(s: String): Either[String,String] = for { x <- (foo(s) toRight "Too short!" ).right y <- (bar(x) toRight "Starts with an A!" ).right z <- (baz(y) toRight "Doesn't contain a space!").right } yield z 在Option上调用toRight(msg)如果它为空则给我们一个Left(msg),否则给我们一个Right(无论如何).然后,我们必须使用.right进行正确的投影,因为Scala的Either不是正确的. 您的情况中的等价物将是这样的: def save(ideaId: Long) = CORSAction { request => val saveResult = for { idea <- (Idea.findById(ideaId) toRight "Could not find id" ).right json <- (request.body.asJson toRight "Invalid Comment entity").right comment <- (json.asOpt[Comment] toRight "Expecting JSON data" ).right result <- comment.copy(idea = idea).save().right } yield result saveResult.fold( error => JsonBadRequest(error),comment => Ok(toJson(comment).toString) ) } 不像你想要的语法简洁,但错误消息出现在一个更合乎逻辑的地方,我们已经摆脱了丑陋的嵌套. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |