一般问题是除了计算的实际结果之外,如何从方法返回附加信息。但我想,这些信息可以默默地被忽略。
以dropWhile
上的Iterator
方法为例。返回的结果是变异的迭代器。但也许有时我可能会对丢弃的元素数量感兴趣。
在dropWhile
的情况下,可以通过向迭代器添加索引并计算之后丢弃的步骤数来在外部生成此信息。但总的来说这是不可能的。
我简单的解决方案是返回一个包含实际结果和可选信息的元组。但是每当我调用方法时我都需要处理元组 - 即使我对可选信息不感兴趣。
所以问题是,是否有一些聪明的方法来收集这些可选信息?
可能通过Option[X => Unit]
参数和回调函数默认为None
?有更聪明的东西吗?
答案 0 :(得分:15)
这里只是我的两分钱......
您可以声明:
case class RichResult[+A, +B](val result: A, val info: B)
隐式转换为A
:
implicit def unwrapRichResult[A, B](richResult: RichResult[A, B]): A = richResult.result
然后:
def someMethod: RichResult[Int, String] = /* ... */
val richRes = someMethod
val res: Int = someMethod
答案 1 :(得分:5)
这绝对不是更聪明,但你可以创建一个删除附加信息的方法。
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
答案 2 :(得分:3)
这是我的观点(有一些更实际的例子编辑):
package info {
trait Info[T] { var data: Option[T] }
object Info {
implicit def makeInfo[T]: Info[T] = new Info[T] {
var data: Option[T] = None
}
}
}
然后假设你的原始方法(和用例)是这样实现的:
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())
}
要提供和访问信息,代码只会稍微修改一下:
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
}
请注意,由于某种原因,类型推断会受到影响,我必须注释传递给dropWhile
的函数的类型。
答案 3 :(得分:0)
你希望dropWhileM
State
monad通过计算线程计数器。