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

scala – 是否有类似延续的类型来包装执行块,如(Ctx => R)=&g

发布时间:2020-12-16 18:28:29 所属栏目:安全 来源:网络整理
导读:我正在寻找这样一种类型,它允许我表示一个上下文,其中运行一段代码.例如: def withinContext[R]: ((= R) = R) = (inner) = { initializeSomeResource() try { inner } finally { releaseTheResource() } } 然后,我可以简单地使用 withinContext { ...} 或者
我正在寻找这样一种类型,它允许我表示一个上下文,其中运行一段代码.例如:

def withinContext[R]: ((=> R) => R) =
  (inner) => {
    initializeSomeResource()
    try {
      inner
    } finally {
      releaseTheResource()
    }
  }

然后,我可以简单地使用

withinContext {
  ...
}

或者,如果内部代码块需要来自上下文的一些信息,则将其概括为

def withinContext[R]: ((Ctx => R) => R) = ...

他们的用例大致对应于Haskell的bracket_bracket.

我可以使用类型(=> R)=> R和(A => R)=> R直接,但是我没有用于组合这些上下文包装器的实用程序函数,所以我想知道,Scala生态系统中是否存在类似的东西?

我知道关闭的东西是scala.util.control.Exception.Catch,它为构造和组合Catch实例提供了很好的功能,但是在内部块执行之前似乎没有办法运行任何初始化.另外(这对我的用例来说不是那么重要)它不允许给内部计算提供参数,例如在案例中(A => R)=> R.

类型(A => R)=> R是延续monad,对应于Haskell的ContT r IO a,但我找不到任何标准Scala库中的continuation monad的实现(也许它隐藏在Scalaz深处,我错过了它).

解决方法

我经常使用这种方法与Specs2测试代码一起使用.基本上我们希望设置一些上下文来包围代码块.我用的成语是这样的:

def contextName[TYPE,RSRC](doit: (RSRC) => TYPE) : TYPE = {
  val thing : RSRC = acquireResource(args)
  try doit(thing)
  finally releaseResource(thing)
}

我意识到你正试图继续延续,但我不得不问:为什么?我刚刚给出的成语是类型的连续monad(RSRC => TYPE)=> TYPE,它可以像你在withContext中建议的那样使用.例如,我写的ReactiveMongo上下文对象的真实用例:

def withDatabase[T](dbName: String)(doit: (DefaultDB) => T) : T = {
  val db = connection.db(dbName)
  try doit(db)
  finally db.drop()
}

这将获取一个数据库,将其传递给continuation,然后在完成后删除数据库,即使continuation抛出异常.它像这样使用:

val numCollections = withDatabase("foo") { db => 
  db.collectionNames.map { list => list.size } 
}

它只是使用数据库来获取数据库中的(未来)数量的集合.

希望这可以帮助.

(编辑:李大同)

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

    推荐文章
      热点阅读