Вопрос

Одной из новых особенностей Scala 2.8 являются контекстные границы. Что такое контекст и где это полезно?

Конечно, я искал первым (и, например, найден это) но я не мог найти действительно четкую и подробную информацию.

Это было полезно?

Решение

Вы нашли эта статья? Он охватывает новую контекстную функцию, в контексте улучшений массива.

Как правило, параметр типа с контекст связан имеет форму [T: Bound]; Он расширен до параметра простых типов T вместе с неявным параметром типа Bound[T].

Рассмотрим метод tabulate который образует массив из результатов применения данной функции F в диапазоне чисел от 0 до заданной длины. Вплоть до Scala 2.7, Tabulate можно записать следующим образом:

def tabulate[T](len: Int, f: Int => T) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}

В Scala 2.8 это больше невозможно, потому что информация времени выполнения необходима для создания правильного представления Array[T]. Анкет Нужно предоставить эту информацию, передавая ClassManifest[T] в метод как неявный параметр:

def tabulate[T](len: Int, f: Int => T)(implicit m: ClassManifest[T]) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}

Как сокращенная форма, контекст связан можно использовать на параметре типа T Вместо этого даст:

def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}

Другие советы

Ответ Роберта охватывает технические детали контекстов. Я дам вам свою интерпретацию их значения.

В скала, связанный с видом (A <% B) захватывает концепцию «может рассматриваться как» (тогда как верхняя граница <: Захватывает концепцию «это»). Контекст (связанный (A : C) говорит «имеет» о типе. Вы можете прочитать примеры о манифестах как "T имеет Manifest". Пример, на который вы связали Ordered против Ordering иллюстрирует разницу. Метод

def example[T <% Ordered[T]](param: T)

говорит, что параметр можно рассматривать как Ordered. Анкет Сравнить с

def example[T : Ordering](param: T)

Что говорит, что параметр имеет связанный Ordering.

С точки зрения использования, потребовалось некоторое время, чтобы установить конвенции, но границы контекста предпочтительнее по сравнению с границами зрения (Посмотреть границы теперь устаревают) Одним из предложений является то, что контекстная граница предпочтительнее, когда вам нужно перенести неявное определение из одной области в другую, не обращаясь к ней напрямую (это, безусловно, относится к ClassManifest используется для создания массива).

Другим способом размышлений о границах представления и границах контекста является то, что первые передачи неявных преобразования из сферы абонента. Второй передает неявные объекты из сферы абонента.

(Это примечание в скобках. Сначала прочитайте и понимайте другие ответы.)

Контекстные границы фактически обобщают границы представления.

Итак, учитывая этот код, выраженный с помощью вида:

scala> implicit def int2str(i: Int): String = i.toString
int2str: (i: Int)String

scala> def f1[T <% String](t: T) = 0
f1: [T](t: T)(implicit evidence$1: (T) => String)Int

Это также может быть выражено с контекстом с помощью псевдонима типа, представляющего функции из типа F печатать T.

scala> trait To[T] { type From[F] = F => T }           
defined trait To

scala> def f2[T : To[String]#From](t: T) = 0       
f2: [T](t: T)(implicit evidence$1: (T) => java.lang.String)Int

scala> f2(1)
res1: Int = 0

Контекста должна использоваться с типом конструктором своего рода * => *. Анкет Однако конструктор типа Function1 это добро (*, *) => *. Анкет Использование псевдоним типа частично применяется параметр второго типа с типом String, дает конструктор типа правильного вида для использования в качестве контекста.

Существует предложение, позволяющее вам напрямую выражать частично применяемые типы в Scala без использования псевдонима типа внутри черты. Затем вы можете написать:

def f3[T : [X](X => String)](t: T) = 0 

Это еще одна примечание в скобках.

В качестве Бен указал, контекстная граница представляет собой ограничение «has-a» между параметром типа и классом типа. Иными словами, это представляет собой ограничение, что существует неявное значение определенного класса типа.

При использовании контекстного связанного, часто необходимо вспять это неявное значение. Например, учитывая ограничение T : Ordering, часто нужен экземпляр Ordering[T] это удовлетворяет ограничению. Как показано здесь, можно получить доступ к неявному значению, используя implicitly метод или немного более полезный context Метод:

def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) = 
   xs zip ys map { t => implicitly[Numeric[T]].times(t._1, t._2) }

или же

def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
   xs zip ys map { t => context[T]().times(t._1, t._2) }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top