Подтвердить что ты не робот

Какая точка родового типа в foreach?

Мне интересно - какова точка родового типа U в объявлении метода Traversable foreach?

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

Так как тип возврата Function1 является ковариантным, почему это не может быть справедливым:

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

?

4b9b3361

Ответ 1

Не будучи Мартином Одерским, я могу только догадываться:-) Глядя на 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
   */

Таким образом, тип возврата f не имеет значения, и его результат всегда отбрасывается. Это, как мне кажется, предполагает, что использование параметра типа generic для обозначения возвращаемого типа - это просто тонкость документации, говорящая: "Тип возврата может быть любым, действительно любым, вам нравится". В то время как тип возврата Any может предложить (некоторым) читателям какое-то ограничение для применяемых здесь типов функций.

Другой аспект заключается в том, что Scala был очень сознательно разработан, чтобы быть общим с нуля. Итак, для меня - использование параметра общего типа здесь согласуется с общей философией языка, в то время как использование Any - хотя и технически применимое - было бы определенно неосновным подходом, который был бы несовместим с остальной частью языка.

Ответ 2

Возможно, чтобы вы наследовали от Traversable и использовали некоторое возвращаемое значение U из 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 возврат false изнутри foreach эквивалентен break, любое другое значение равно continue.

Использовать случай

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

Потому что следующий код (параллельный) никогда не ломается (в этом случае бесполезное броское решение кажется неидеальным?):

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" 
  }) 
}