我如何在scala中使用隐式传递执行上下文,而不进行理解?

时间:2020-06-28 11:38:21

标签: scala future

我有一个使用理解来运行数据库查询的代码:

val totalFeeNoticeAmountFromDB = Future(/..Doing db job../)(executionContext)
val listOfRestrictedFundFromDB = Future(/..Doing db job../)(executionContext)

val res = for {
      totalFeeNoticeAmount <- totalFeeNoticeAmountFromDB
      listOfRestrictedFund <- listOfRestrictedFundFromDB
    } yield (totalFeeNoticeAmount, listOfRestrictedFund) 

我们知道要理解,我们需要传递隐式执行上下文。 但是在这种情况下,我想手动传递执行上下文。
怎么了?

已编辑:

val res = for {
          totalFeeNoticeAmount <-(?:ExecutionContext) totalFeeNoticeAmountFromDB
          listOfRestrictedFund <-(?:ExecutionContext) listOfRestrictedFundFromDB
        } yield (totalFeeNoticeAmount, listOfRestrictedFund) 

totalFeeNoticeAmountFromDBlistOfRestrictedFundFromDB都是已经启动的未来类型。

有什么方法可以通过这里吗 <-(?:ExecutionContext)吗?

3 个答案:

答案 0 :(得分:6)

也许考虑scala-async,它在Scala 2.13.3中获得了experimental compiler support -Xasync,其中具有以下理解力

for {
  a <- Future(41)
  b <- Future(1)
} yield {
  a + b
}

可以改写为

async {
  val a = async(41)(ec)
  val b = async(1)(ec)
  await(a) + await(b)
}(ec)

我们可以在其中显式传递执行上下文ec,而无需求助于flatMap / map。

另一个黑客选项可能是better-monadic-for,它支持在理解中定义隐式内容

val ec: ExecutionContext = ???
(for {
  implicit0(ec: ExecutionContext) <- Future.successful(ec)
  a <- Future(41)(ec)
  b <- Future(1)(ec)
} yield {
  a + b
})(ec)

答案 1 :(得分:3)

您可以重写

val res = for {
  totalFeeNoticeAmount <- totalFeeNoticeAmountFromDB
  listOfRestrictedFund <- listOfRestrictedFundFromDB
} yield (totalFeeNoticeAmount, listOfRestrictedFund)

val res = totalFeeNoticeAmountFromDB.flatMap(totalFeeNoticeAmount =>
  listOfRestrictedFundFromDB.map(listOfRestrictedFund =>
    (totalFeeNoticeAmount, listOfRestrictedFund)
  )
)

例如,如果totalFeeNoticeAmountFromDBlistOfRestrictedFundFromDBFuture,则可以显式传递隐式scala.concurrent.ExecutionContext.Implicits.global

val res = totalFeeNoticeAmountFromDB.flatMap(totalFeeNoticeAmount =>
  listOfRestrictedFundFromDB.map(listOfRestrictedFund =>
    (totalFeeNoticeAmount, listOfRestrictedFund)
  )(scala.concurrent.ExecutionContext.Implicits.global)
)(scala.concurrent.ExecutionContext.Implicits.global)

答案 2 :(得分:2)

我相信解决此问题的最简单方法就是创建一个辅助功能。

library(ggplot2)
ddft=data.frame(month = c("03-2012","04-2012","05-2012","06-2012","07-2012", "08-2012","09-2012","10-2012","11-2012","12-2012","02-2013","03-2013"), frqp = c("12.3", "11.4","44.1","11.3", "1.2","15.1","35.1","12","14.1","15.1","15.1","42.1"))

lastfew <- function(x, n){
  x=as.character(x)
  substr(x, nchar(x)-n+1, nchar(x))
}

yearlabels=lastfew(ddft$month,4)

ddft$yearlabels=yearlabels

Frequency=as.numeric(as.character(ddft$frqp))

minima=as.integer(min(Frequency))-1
maxima=as.integer(max(Frequency))+1
step=5
ggplot(ddft, aes(x=month, y=Frequency))+  
geom_point() +
theme(legend.position="none",axis.ticks.x=element_blank(),axis.title.x=element_blank(),axis.text.x=element_blank(),panel.spacing.x=unit(0.03, "lines"),panel.grid.major = element_blank())+  
 scale_y_continuous(breaks = seq(minima, maxima, step))+facet_wrap(~yearlabels,strip.position = "bottom",scales = "free_x")

这样,当您需要它时,您就可以这样称呼它:def foo(implicit ec: ExecutionContext): Future[(Int, Int)] = { val totalFeeNoticeAmountFromDB = Future(/..Doing db job../) val listOfRestrictedFundFromDB = Future(/..Doing db job../) for { totalFeeNoticeAmount <- totalFeeNoticeAmountFromDB listOfRestrictedFund <- listOfRestrictedFundFromDB } yield (totalFeeNoticeAmount, listOfRestrictedFund) }

相关问题