在Scala函数中处理副作用和返回值的惯用方法

时间:2017-05-25 07:15:03

标签: scala monads scala-cats

您如何构建一个既想要副作用又返回值的函数? 例如,我想要以下功能:

def futureFromHttpCall: Future[HttpResponse] = 
  doHttpCall.foreach(publishDomainEvent).returnOriginalFuture

(不知怎的,我有一种感觉,monad会出现,所以如果这是我对猫有点熟悉的路径,如果有解决这个问题的那里?)

2 个答案:

答案 0 :(得分:2)

我能想到的最简单的事情不是"隐藏" Future[T]返回方法中的副作用,将其作为未来的延续:

def futureFromHttpCall: Future[HttpResponse] = doHttpCall

然后你可以onComplete作为副作用:

futureFromHttpCall.onComplete {
    case Success(_) => publishDomainEvent
    case Failure(e) => // Stuff
}

使效果明确。或者如果您在演员系统中,您可以pipeTo Future到您的receive方法,并在那里处理成功/失败。

答案 1 :(得分:1)

我认为您的Future只应在推送所有域事件时完成。它们也应该是Future。然后你可以使用Future.sequence等待所有这些完成后再返回。

您的问题有点不清楚,但我认为doHttpCall是某种类型的列表。

def doHttpCall(): Future[Seq[X]] = ???

def publishDomainEvent(x:X): Future[Unit] = ???

def futureFromHttpCall(): Future[Seq[X]] = {

  val firstFuture = ???

  firstFuture.flatMap { xs =>
    val xxs: Seq[Future[Unit]]= xs.map(publishDomainEvent)
    Future.sequence(xxs).map { _ => re }
  }
}

在测试时,所有这些等待都非常有用。