Scala 如何从方法返回可选信息?

Scala 如何从方法返回可选信息?,scala,Scala,一般的问题是,除了计算的实际结果之外,如何从方法返回附加信息。但是我想,这些信息可以被默默地忽略 以Iterator上的方法dropWhile为例。返回的结果是经过变异的迭代器。但有时我可能对丢弃的元素的数量感兴趣 在dropWhile的情况下,可以通过在迭代器中添加索引并计算之后删除的步骤数,从外部生成此信息。但总的来说,这是不可能的 一个简单的解决方案是返回一个包含实际结果和可选信息的元组。但是,无论何时调用该方法,我都需要处理元组——即使我对可选信息不感兴趣 def removeCharW

一般的问题是,除了计算的实际结果之外,如何从方法返回附加信息。但是我想,这些信息可以被默默地忽略

Iterator
上的方法
dropWhile
为例。返回的结果是经过变异的迭代器。但有时我可能对丢弃的元素的数量感兴趣

dropWhile
的情况下,可以通过在迭代器中添加索引并计算之后删除的步骤数,从外部生成此信息。但总的来说,这是不可能的

一个简单的解决方案是返回一个包含实际结果和可选信息的元组。但是,无论何时调用该方法,我都需要处理元组——即使我对可选信息不感兴趣

def removeCharWithCount(str: String, x: Char): (String, Int) =
  (str.replace(x.toString, ""), str.count(x ==))

// alias that drops the additional return information
def removeChar(str: String, x: Char): String =
  removeCharWithCount(str, x)._1
所以问题是,是否有聪明的方法收集这些可选信息


可能通过
选项[X=>Unit]
参数调用默认为
None
?有更聪明的方法吗?

它肯定不是更聪明,但您可以创建一个方法来删除附加信息

def removeCharWithCount(str: String, x: Char): (String, Int) =
  (str.replace(x.toString, ""), str.count(x ==))

// alias that drops the additional return information
def removeChar(str: String, x: Char): String =
  removeCharWithCount(str, x)._1

这里只有我的两分钱

您可以声明:

case class RichResult[+A, +B](val result: A, val info: B)
隐式转换为
A

implicit def unwrapRichResult[A, B](richResult: RichResult[A, B]): A = richResult.result
然后:

以下是我的观点(用一个更现实的例子进行了一些编辑):

然后假设您的原始方法(和用例)实现如下:

object Test extends App {
  def dropCounterIterator[A](iter: Iterator[A]) = new Iterator[A] {
    def hasNext = iter.hasNext
    def next() = iter.next()
    override def dropWhile(p: (A) => Boolean): Iterator[A] = {
      var count = 0
      var current: Option[A] = None
      while (hasNext && p({current = Some(next()); current.get})) { count += 1 }
      current match {
        case Some(a) => Iterator.single(a) ++ this
        case None => Iterator.empty
      }
    }
  }

  val i = dropCounterIterator(Iterator.from(1))
  val ii = i.dropWhile(_ < 10)
  println(ii.next())
}
对象测试扩展应用程序{
def dropCounterIterator[A](iter:Iterator[A])=新迭代器[A]{
def hasNext=iter.hasNext
def next()=iter.next()
覆盖def dropWhile(p:(A)=>布尔):迭代器[A]={
变量计数=0
var电流:选项[A]=无
而(hasNext&&p({current=Some(next());current.get})){count+=1}
当前匹配{
case Some(a)=>Iterator.single(a)++this
case None=>Iterator.empty
}
}
}
val i=dropCounterIterator(迭代器.from(1))
val ii=i.dropWhile(<10)
println(ii.next())
}
为了提供和访问信息,代码只需稍加修改:

import info.Info // line added

object Test extends App {
  def dropCounterIterator[A](iter: Iterator[A]) = new Iterator[A] {
    def hasNext = iter.hasNext
    def next() = iter.next()
    // note overloaded variant because of extra parameter list, not overriden
    def dropWhile(p: (A) => Boolean)(implicit info: Info[Int]): Iterator[A] = {
      var count = 0
      var current: Option[A] = None
      while (hasNext && p({current = Some(next()); current.get})) { count += 1 }
      info.data = Some(count) // line added here
      current match {
        case Some(a) => Iterator.single(a) ++ this
        case None => Iterator.empty
      }
    }
  }

  val i = dropCounterIterator(Iterator.from(1))
  val info = implicitly[Info[Int]] // line added here
  val ii = i.dropWhile((x: Int) => x < 10)(info) // line modified
  println(ii.next())
  println(info.data.get) // line added here
}
导入信息。信息//添加行
对象测试扩展应用程序{
def dropCounterIterator[A](iter:Iterator[A])=新迭代器[A]{
def hasNext=iter.hasNext
def next()=iter.next()
//注意:由于额外的参数列表,重载变量,而不是重写
def dropWhile(p:(A)=>Boolean)(隐式信息:信息[Int]):迭代器[A]={
变量计数=0
var电流:选项[A]=无
而(hasNext&&p({current=Some(next());current.get})){count+=1}
info.data=Some(count)//此处添加了一行
当前匹配{
case Some(a)=>Iterator.single(a)++this
case None=>Iterator.empty
}
}
}
val i=dropCounterIterator(迭代器.from(1))
val info=隐式[info[Int]]//此处添加了一行
valii=i.dropWhile((x:Int)=>x<10)(info)//行已修改
println(ii.next())
println(info.data.get)//此处添加了一行
}

请注意,由于某种原因,类型推断受到影响,我必须对传递给
dropWhile
的函数类型进行注释,而
dropWhileM
需要使用
状态
单子在计算中穿行计数器。

对此进行了思考。缺点是,当类型注释无法推断
A
时,您需要类型注释。如果要分配给
val
并希望从隐式转换中获益,则无论如何都需要类型注释。顺便说一下,您还可以使用类型归属:
val res=someMethod:Int
。如果我必须对可选类型进行注释/归因,那就更好了。然后我认为这是我的问题的解决方案。如果你想要一个解决方案,你把额外的信息归咎于,你最好使用,这是更多的信息。
import info.Info // line added

object Test extends App {
  def dropCounterIterator[A](iter: Iterator[A]) = new Iterator[A] {
    def hasNext = iter.hasNext
    def next() = iter.next()
    // note overloaded variant because of extra parameter list, not overriden
    def dropWhile(p: (A) => Boolean)(implicit info: Info[Int]): Iterator[A] = {
      var count = 0
      var current: Option[A] = None
      while (hasNext && p({current = Some(next()); current.get})) { count += 1 }
      info.data = Some(count) // line added here
      current match {
        case Some(a) => Iterator.single(a) ++ this
        case None => Iterator.empty
      }
    }
  }

  val i = dropCounterIterator(Iterator.from(1))
  val info = implicitly[Info[Int]] // line added here
  val ii = i.dropWhile((x: Int) => x < 10)(info) // line modified
  println(ii.next())
  println(info.data.get) // line added here
}