加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala风格 – 如何避免大量的嵌套地图

发布时间:2020-12-16 09:19:16 所属栏目:安全 来源:网络整理
导读:在验证多个连续性条件时,我经常会遇到很多嵌套的.map和.getOrElse 例如: def save() = CORSAction { request = request.body.asJson.map { json = json.asOpt[Feature].map { feature = MaxEntitiyValidator.checkMaxEntitiesFeature(feature).map { rs = f
在验证多个连续性条件时,我经常会遇到很多嵌套的.map和.getOrElse

例如:

def save() = CORSAction { request =>
  request.body.asJson.map { json =>
    json.asOpt[Feature].map { feature =>
      MaxEntitiyValidator.checkMaxEntitiesFeature(feature).map { rs =>
        feature.save.map { feature => 
          Ok(toJson(feature.update).toString)
        }.getOrElse {
          BadRequest(toJson(
            Error(status = BAD_REQUEST,message = "Error creating feature entity")
          ))
        }
      }.getOrElse {
        BadRequest(toJson(
          Error(status = BAD_REQUEST,message = "You have already reached the limit of feature.")
        )) 
      }
    }.getOrElse {
      BadRequest(toJson(
        Error(status = BAD_REQUEST,message = "Invalid feature entity")
      )) 
    }
  }.getOrElse {
    BadRequest(toJson(
      Error(status = BAD_REQUEST,message = "Expecting JSON data")
    )) 
  }
}

你得到这个想法

我只是想知道是否有一些惯用的方法来保持更清楚

解决方法

如果您没有为None案例返回不同的消息,这将是理解的理想用例.在你的情况下,你可能想要使用验证monad,就像在Scalaz中找到的那样.示例( http://scalaz.github.com/scalaz/scalaz-2.9.0-1-6.0/doc.sxr/scalaz/Validation.scala.html).

在函数式编程中,不应该抛出异常,而是让失败的函数返回一个[A,B],其中按照惯例A是失败时的结果类型,B是成功时的结果类型.然后,您可以与左(a)或右(b)匹配来对两种情况进行反复处理.

您可以将验证monad视为扩展名[A,其中将后续功能应用于验证将产生结果或执行链中的第一个失败.

sealed trait Validation[+E,+A] {
  import Scalaz._

  def map[B](f: A => B): Validation[E,B] = this match {
    case Success(a) => Success(f(a))
    case Failure(e) => Failure(e)
  }

  def foreach[U](f: A => U): Unit = this match {
    case Success(a) => f(a)
    case Failure(e) =>
  }

  def flatMap[EE >: E,B](f: A => Validation[EE,B]): Validation[EE,B] = this match {
    case Success(a) => f(a)
    case Failure(e) => Failure(e)
  }

  def either : Either[E,A] = this match {
    case Success(a) => Right(a)
    case Failure(e) => Left(e)
  }

  def isSuccess : Boolean = this match {
    case Success(_) => true
    case Failure(_) => false
  }

  def isFailure : Boolean = !isSuccess

  def toOption : Option[A] = this match {
    case Success(a) => Some(a)
    case Failure(_) => None
  }


}

final case class Success[E,A](a: A) extends Validation[E,A]
final case class Failure[E,A](e: E) extends Validation[E,A]

您的代码现在可以通过将验证单元用于三个验证层来重构.您应该基本上用以下验证来替换地图:

def jsonValidation(request:Request):Validation[BadRequest,String] = request.asJson match {
   case None => Failure(BadRequest(toJson(
      Error(status = BAD_REQUEST,message = "Expecting JSON data")
    )
   case Some(data) => Success(data)
}

def featureValidation(validatedJson:Validation[BadRequest,String]): Validation[BadRequest,Feature] = {
validatedJson.flatMap {
  json=> json.asOpt[Feature] match {
    case Some(feature)=> Success(feature)
    case None => Failure( BadRequest(toJson(
      Error(status = BAD_REQUEST,message = "Invalid feature entity")
        )))
  }
}

}

然后你链接他们像以下featureValidation(jsonValidation(请求))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读