首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Scala中如何用IO单片实现短路

在Scala中如何用IO单片实现短路
EN

Stack Overflow用户
提问于 2015-03-27 02:14:55
回答 1查看 816关注 0票数 7

我用的是标准的IO单。

在某种程度上,我需要短路。在给定条件下,我不想运行以下ios。

这是我的解决方案,但我发现它过于冗长,不优雅:

代码语言:javascript
复制
  def shortCircuit[A](io: IO[A], continue: Boolean) =
    io.map(a => if (continue) Some(a) else None)

  for {
    a <- io
    b <- shortCircuit(io, a == 1)
    c <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
    d <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
    e <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
  } yield …

例如,对于第3行、第4行和第5行,我需要重复相同的条件。

有更好的办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-27 21:20:46

你在那里什么都没短路。您仍然在运行IOs;只是不捕获值。

此外,标准的IO monad没有定义filter (或withFilter),因此您不能在理解过程中使用保护。

现在,如果您想要的只是您所说的(相同的逻辑,只是更枯燥),您可以始终指定一个临时变量中的理解:

代码语言:javascript
复制
for {
  a <- io
  b <- shortCircuit(io, a == 1)
  continue = b.map(_ == 1).getOrElse(false)
  c <- shortCircuit(io, continue)
  d <- shortCircuit(io, continue)
  e <- shortCircuit(io, continue)
} yield …

但是如果你真的想要短路,你就必须在某种程度上打破这些情况。这里有一种可能性,假设您只想将所有内容打包到一个数组中,因此返回类型是简单的,并且您的IO同伴对象有一个apply方法,您可以使用该方法来创建只返回一个值的东西:

代码语言:javascript
复制
io.flatMap(a =>
  if (a == 1) IO(() => Array(a))
  else io.flatMap(b =>
    if (b == 1) IO(() => Array(a,b))
    else for {
      c <- io
      d <- io
      e <- io
    } yield Array(a,b,c,d,e)
  )
)

如果返回类型比较复杂,则可能需要更努力地指定类型。

FWIW,值得注意的是,如果不使用单片包装的东西,就需要付出代价(例如):

代码语言:javascript
复制
io() match {
  case 1 => Array(1)
  case a => io() match {
    case 1 => Array(a, 1)
    case b => Array(a, b, io(), io(), io())
  }
}

如果你允许回报,你会得到:

代码语言:javascript
复制
val a = io()
if (a == 1) return Array(a)
val b = io()
if (b == 1) return Array(a, b)
Array(a, b, io(), io(), io())

原则上也可以用一些额外的方法来修饰IO monad,但是标准的withFilter无法工作,所以您将无法使用理解语法糖。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29292184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档