scalabook

Форк
0
/
write-map.md 
89 строк · 4.1 Кб

Написание своего собственного метода map

Теперь, когда известно, как писать собственные функции высшего порядка, рассмотрим более реальный пример.

Представим, что у класса List

нет метода map
, и есть необходимость его написать. Первым шагом при создании функций является точное определение проблемы. Сосредоточившись только на List[Int]
, получаем:

Необходимо написать метод map

, который можно использовать для применения функции к каждому элементу в List[Int]
, возвращая преобразованные элементы в виде нового списка.

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

в какой-то общий тип A
, поэтому получаем:

def map(f: (Int) => A)

Синтаксис использования универсального типа требует объявления этого символа типа перед списком параметров, поэтому добавляем объявление типа:

def map[A](f: (Int) => A)

Далее известно, что map

также должен принимать List[Int]
:

def map[A](f: (Int) => A, xs: List[Int])

Наконец, также известно, что map

возвращает преобразованный список, содержащий элементы универсального типа A
:

def map[A](f: (Int) => A, xs: List[Int]): List[A] = ???

Теперь все, что нужно сделать, это написать тело метода. Метод map

применяет заданную им функцию к каждому элементу в заданном списке для создания нового преобразованного списка. Один из способов сделать это - использовать выражение for
:

for x <- xs yield f(x)

for

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

Объединив for

с сигнатурой метода, получим автономный метод map
, который работает с List[Int]
:

def map[A](f: (Int) => A, xs: List[Int]): List[A] =
for x <- xs yield f(x)
Обобщим метод map

Обратим внимание, что выражение for

не делает ничего, что зависит от типа Int
внутри списка. Следовательно, можно заменить Int
в сигнатуре типа параметром универсального типа B
:

def map[A, B](f: (B) => A, xs: List[B]): List[A] =
for x <- xs yield f(x)

Получился метод map

, который работает с любым списком.

Демонстрация работы получившегося map

:

def double(i : Int) = i * 2
def strlen(s: String) = s.length
map(double, List(1, 2, 3))
// res0: List[Int] = List(2, 4, 6)
map(strlen, List("a", "bb", "ccc"))
// res1: List[Int] = List(1, 2, 3)

Теперь, когда рассмотрены методы, принимающие функции в качестве входных параметров, перейдем к методам, возвращающим функции.


Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.