20

我很好奇 -方法U声明中泛型类型Traversable的意义foreach何在?

def foreach[U](f: A => U): Unit

既然返回类型Function1是协变的,为什么不能这样:

def foreach(f: A => Any): Unit

?

4

2 回答 2

10

不是 Martin Odersky,我只能猜测 :-) 看着 Scaladoc foreach,我看到了:

  /** Applies a function `f` to all elements of this $coll.
   *
   *  @param  f   the function that is applied for its side-effect to every element.
   *              The result of function `f` is discarded.
   *              
   *  @tparam  U  the type parameter describing the result of function `f`. 
   *              This result will always be ignored. Typically `U` is `Unit`,
   *              but this is not necessary.
   *
   *  @usecase def foreach(f: A => Unit): Unit
   */

So the return type of f doesn't matter and its result is always discarded. This, to me, suggests that using a generic type parameter here to mark the return type is just a documentation subtlety, saying "the return type can be anything, really anything, you like". Whereas a return type of Any may suggest to (some) readers some sort of limitation to the function types applicable here.

Another aspect is that Scala was very consciously designed to be generic from the ground up. So - to me - using a generic type parameter here is consistent with the general philosophy of the language, while using Any - although technically usable - would be a definitely non-generic approach which would be at odds with the rest of the language.

于 2012-12-30T21:19:58.947 回答
-5

也许允许你从 a 继承Traversable,并利用返回值Ufrom f: A => U

trait TraversableWithHandler[+A, E <: Option[Throwable]] extends Traversable[A] {
  override def foreach[U](f: A => U): Unit
  def handleError(t: E) 
}

例如,从内部jQuery返回的等价于,任何不同的值都是 a 。falseforeachbreakcontinue

用例

breakable { 
  List(1,2,3).foreach(_ match { 
    case 1 => println("ok")
    case 2 => 
      println("Sort of, soft interrupt?")
      return false
    case 3 => break
  })
}

因为下一个代码(并行),永远不会中断(在这种情况下,stackless throwable 解决方案似乎不理想?):

import scala.util.control.Breaks._

breakable { 
  (0 to 100).toList.par.foreach(_ match { 
    case n if (n <= 50) => 
      println("#" * 100)
      try { break } catch { 
        case t: Throwable => println("" + t); break 
      }
    case n if (n > 50) => 
      println("" + n)
    case _ => "ok" 
  }) 
}
于 2012-12-30T21:13:38.893 回答