Scala 3 — Book

Контекстные границы

Language

Во многих ситуациях имя контекстного параметра не нужно указывать явно, поскольку оно используется компилятором только в синтезированных аргументах для других параметров контекста. В этом случае вам не нужно определять имя параметра, а можно просто указать тип.

Предыстория

Например, рассмотрим метод maxElement, возвращающий максимальное значение в коллекции:

def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
  as.reduceLeft(max(_, _)(ord))
def maxElement[A](as: List[A])(using ord: Ord[A]): A =
  as.reduceLeft(max(_, _)(using ord))

Метод maxElement принимает контекстный параметр типа Ord[A] только для того, чтобы передать его в качестве аргумента методу max.

Для полноты приведем определения max и Ord (обратите внимание, что на практике мы будем использовать существующий метод max для List, но мы создали этот пример для иллюстрации):

/** Определяет, как сравнивать значения типа `A` */
trait Ord[A] {
  def greaterThan(a1: A, a2: A): Boolean
}

/** Возвращает максимальное из двух значений */
def max[A](a1: A, a2: A)(implicit ord: Ord[A]): A =
  if (ord.greaterThan(a1, a2)) a1 else a2
/** Определяет, как сравнивать значения типа `A` */
trait Ord[A]:
  def greaterThan(a1: A, a2: A): Boolean

/** Возвращает максимальное из двух значений */
def max[A](a1: A, a2: A)(using ord: Ord[A]): A =
  if ord.greaterThan(a1, a2) then a1 else a2

Обратите внимание, что метод max принимает контекстный параметр типа Ord[A], как и метод maxElement.

Пропуск контекстных аргументов

Так как ord - это контекстный параметр в методе max, компилятор может предоставить его для нас в реализации maxElement при вызове max:

def maxElement[A](as: List[A])(implicit ord: Ord[A]): A =
  as.reduceLeft(max(_, _))
def maxElement[A](as: List[A])(using Ord[A]): A =
  as.reduceLeft(max(_, _))

Обратите внимание: поскольку нам не нужно явно передавать его методу max, мы можем не указывать его имя в определении метода maxElement. Это анонимный параметр контекста.

Границы контекста

Учитывая написанное выше, привязка к контексту — это сокращенный синтаксис для выражения шаблона “параметр контекста, применяемый к параметру типа”.

Используя привязку к контексту, метод maxElement можно записать следующим образом:

def maxElement[A: Ord](as: List[A]): A =
  as.reduceLeft(max(_, _))

Привязка типа : Ord к параметру типа A метода или класса указывает на параметр контекста с типом Ord[A]. Под капотом компилятор преобразует этот синтаксис в тот, который показан в разделе “Предыстория”.

Дополнительные сведения о границах контекста см. в разделе “Что такое границы контекста?” раздел FAQ по Scala.

Contributors to this page: