Scala в примерах: различия между версиями

Перейти к навигации Перейти к поиску
→‎Неявные(имплицитные) параметры и преобразования: — правка кода, некорректного в оригинальной статье
м (Возврат прежних правок)
(→‎Неявные(имплицитные) параметры и преобразования: — правка кода, некорректного в оригинальной статье)
 
= Неявные(имплицитные) параметры и преобразования =
 
Неявные(имплицитные) параметры и преобразования – это мощные инструменты для настройки существующих библиотек и для создания высокоуровневых абстракций. Например, давайте начнем с абстрактного класса полугрупп, который поддерживает операцию сложения.
 
<font size=3><syntaxhighlight lang=Scala>
abstract class SemiGroup[A] {
def add(x: A, y: A): A
}
</syntaxhighlight></font>
 
А вот подкласс <tt>SemiGroup</tt> — класс <tt>Monoid</tt>, который добавляет поле <tt>unit</tt> (единичный элемент):
 
<font size=3><syntaxhighlight lang=Scala>
abstract class Monoid[A] extends SemiGroup[A] {
def unit: A
}
</syntaxhighlight></font>
 
Вот две реализации моноидов:
 
<font size=3><syntaxhighlight lang=Scala>
object stringMonoid extends Monoid[String] {
def add(x: String, y: String): String = x.concat(y)
def unit: String = ""
}
 
object intMonoid extends Monoid[Int] {
def add(x: Int, y: Int): Int = x + y
def unit: Int = 0
}
</syntaxhighlight></font>
 
Метод суммирования, который работает с произвольными моноидами, может быть написан на чистом Scala следующим образом:
 
<font size=3><syntaxhighlight lang=Scala>
def sum[A](xs: List[A])(m: Monoid[A]): A =
if (xs.isEmpty) m.unit
else m.add(xs.head, sum(xs.tail)(m))
</syntaxhighlight></font>
 
Этот метод может быть вызван, например, так:
 
<font size=3><syntaxhighlight lang=Scala>
sum(List("a", "bc", "def"))(stringMonoid)
sum(List(1, 2, 3))(intMonoid)
</syntaxhighlight></font>
 
Все это работает, но выглядит не очень здорово. Проблема в том, что реализации моноида должны быть переданы в код, который их использует. Порой мы можем захотеть, чтобы система могла вычислить нужные аргументы автоматически, аналогично тому, как это делается при выводе типов аргументов. Это то, чего помогают добиться неявные параметры.
 
 
<font size=3>'''Неявные параметры: основы'''</font>
 
В Scala 2 появилось новое ключевое слово '''<tt>implicit</tt>''', оно может быть использовано в начале списка параметров. Синтаксис:
</syntaxhighlight></font>
 
Основная идея неявных параметров — это то, что аргументы для них могут быть выведены из вызова метода. Если аргументы, отвечающие за секцию неявного параметра, отсутствуют, тогда они выводятся компилятором Scala.
 
Действительные аргументы, которые могут быть переданы в качестве неявного параметра, — это все идентификаторы <tt>X</tt>, которые доступны в точке вызова метода без префикса и которые помечены как неявные.
if (xs.isEmpty || xs.tail.isEmpty) xs
else {
val {(ys, zs}) = xs.splitAt(xs.length / 2)
merge(sort(ys), sort(zs))
}
</syntaxhighlight></font>
else if (ys.isEmpty) xs
else if (xs.head < ys.head) xs.head :: merge(xs.tail, ys)
else if ys.head :: merge(xs, ys.tail)
</syntaxhighlight></font>
 
83

правки

Навигация