首页 文章

在Scala中构建具有副作用期货的无状态期货

提问于
浏览
2

虽然组合期货有一个收益结构,一些有副作用,有些没有,我引入了一个竞争条件,因为未来取决于副作用并没有把这个方面的结果影响未来作为一个论点 .

简而言之:

未来b读取由未来a的副作用改变的值,但未来a未明确依赖于未来b的结果,因此可能在b完成读取之前发生 .

为了解决这个问题,我的同事介绍了一个虚拟函数,将 b 的结果作为参数,然后将其丢弃 . 这样做是为了使依赖显式化 .

实际代码在这里:

val futureConnection:Future[(Either[String, (Connection)],Boolean)] =
    for {
      scannerUser <- scanner.orFail("Scanning user not found")
      scannedUser <- futureScannedUser.orFail("Scanned user not found")
      existsInAnyDirection <- connections.existsInAnyDirection(scannerUser, scannedUser)
      connection <- connections.createConnection(scannerUser, scannedUser, form.magicWord, existsInAnyDirection)
    } yield {
      (connection, existsInAnyDirection)
    }

在这种情况下,未来 b

connections.existsInAnyDirection(scannerUser, scannedUser)

和虚拟参数的未来 a

connections.createConnection(scannerUser, scannedUser, form.magicWord, existsInAnyDirection)

请注意,参数 existsInAnyDirection 永远不会在 createConnection 中使用 . 这有效地创建了依赖关系图,在existsInAnyDirection完成之前无法启动createConnection .

现在提问:

是否有更明智的方式使依赖显式?


Bonus Info

我自己的挖掘告诉我,Scala Futures根本不能很好地处理副作用 . The methods on the Future trait处理副作用返回单位,而很可能是从副作用操作中读取的结果,即错误代码,生成的ID,任何其他元信息,真的 .

1 回答

  • 0

    Future 正在处理推迟计算的副作用,如 A => Future[B] .

    你试图混合几个不同的副作用,但只组成其中一个 Future[_] .

    尝试选择第二个容器,这可以是产品或状态,取决于你的副作用,并考虑组成副作用(可能你需要modand变换器) . 在您的代码看起来像(最简单的情况)之后:

    for {
      scannerUser <- scanner.orFail("Scanning ...")
      (scannedUser, magicWord) <- futureScannedUser.orFail("Scanned ...")      
      connection <- connections.createConnection(scannerUser, scannedUser, magicWord)
    } yield {
      (connection, existsInAnyDirection)
    }
    
    // OR
    
    for {
      (scannerUser, state) <- scanner.orFail("Scanning ...")
      (scannedUser, nextState) <- futureScannedUser(state).orFail("Scanned ...")      
      connection <- connections.createConnection(scannerUser, scannedUser, nextState)
    } yield {
      (connection, existsInAnyDirection)
    }
    

相关问题