В чем преимущество Scala с привязкой к контексту над обычным параметром?

Я читаю о границах контекста и неявных параметрах, которые должны работать как классы типов. Примеры, которые я часто вижу Ordering[T], Что-то вроде:

foo[T : Ordering](a: T, b: T)

который является сахаром для

foo[T](a: T, b: T)(implicit ord: Ordering[T]) 

так что в теле можно сделать что-то вроде

ord.compare(a, b)

Я думал, что понял это раньше, и теперь я рисую пробел... в чем преимущество перед простой передачей вещи в функцию. Например:

foo[T](a: T, b: T, ord: Ordering[T])
/* or */ foo[T](a: T, b: T)(ord: Ordering[T])
foo(a, b, myOrdering)
/* or */ foo(a, b)(myOrdering)

1 ответ

Решение

Я постараюсь ответить подробно ниже. Краткий ответ: не нужно явно передавать неявные значения неявным параметрам другого метода.

Как я понимаю, вы не против синтаксического сахара границ контекста, и вы это понимаете, поэтому я просто пропущу эту часть.

Представьте, что у вас есть два метода сортировки: один сортирует весь массив, другой сортирует только его часть. Они имеют следующие подписи:

sort[T](as: Array[T], ord: Ordering[T]): Unit = sort(as, 0, as.length, ord)
sort[T](as: Array[T], from: Int, to: Int, ord: Ordering[T]): Unit = ???

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

sort[T](as: Array[T])(implicit ord: Ordering[T]): Unit = sort(as, 0, as.length/*)( ord*/)
sort[T](as: Array[T], from: Int, to: Int)(implicit ord: Ordering[T]): Unit = ???

или с границами контекста:

sort[T:Ordering](as: Array[T]): Unit = sort(as, 0, as.length/*)( ord*/)
sort[T:Ordering](as: Array[T], from: Int, to: Int): Unit = ???

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

(Для полноты получения экземпляра с привязкой к контексту: implicitly[Ordering[T]]где-то в ??? реализация.)

Другие вопросы по тегам