Те, о которых я могу думать,
Экзистенциальные типы
def foo(l: List[Option[_]]) = ...
Параметры высшего типа
case class A[K[_],T](a: K[T])
Игнорируемые переменные
val _ = 5
Игнорируемые параметры
List(1, 2, 3) foreach { _ => println("Hi") }
Игнорируемые имена типов самостей
trait MySeq { _: Seq[_] => }
Шаблоны подстановочных знаков
Some(5) match { case Some(_) => println("Yes") }
Шаблоны подстановочных знаков в интерполяциях
"abc" match { case s"a$_c" => }
Подстановочный знак последовательности в шаблонах
C(1, 2, 3) match { case C(vs @ _*) => vs.foreach(f(_)) }
Импорт подстановочных знаков
import java.util._
Сокрытие импорта
import java.util.{ArrayList => _, _}
Письма-присоединения к операторам
def bang_!(x: Int) = 5
Операторы присваивания
def foo_=(x: Int) { ... }
Синтаксис заполнителя
List(1, 2, 3) map (_ + 2)
Значения метода
List(1, 2, 3) foreach println _
Преобразование параметров вызова по имени в функции
def toFunction(callByName: => Int): () => Int = callByName _
Инициализатор по умолчанию
var x: String = _ // unloved syntax may be eliminated
Могут быть и другие, о которых я забыл!
Пример, показывающий, почему foo(_)
и foo _
различаются:
Этот пример происходит от 0 __ :
trait PlaceholderExample {
def process[A](f: A => Unit)
val set: Set[_ => Unit]
set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}
В первом случае process _
представляет метод; Scala использует полиморфный метод и пытается сделать его мономорфным, заполнив параметр типа, но понимает, что не существует type , который можно заполнить для A
, который даст тип (_ => Unit) => ?
(Existential _
не тип).
Во втором случае process(_)
- лямбда; когда пишется лямбда без явного типа аргумента, Scala выводит тип из аргумента, который ожидает foreach
, а _ => Unit
является типом (тогда как просто _
нет), поэтому может быть заменен и выведен.
Возможно, это самая хитрая ошибка в Скале, с которой я когда-либо сталкивался.
Обратите внимание, что этот пример компилируется в 2.13. Проигнорируйте это, как это было назначено, чтобы подчеркнуть.