SlideShare a Scribd company logo
1 of 28
Обработка коллекций в
функциональном стиле: от
рекурсий к гиломорфизмам
Вадим Винник
Об авторе
● SolarWinds MSP.
● Technical lead developer.
● C++, C# for work.
● Haskell just for fun.
● Domains:
○ Network traffic filtering.
○ Data backup and recovery.
○ Business process simulation.
● Ph.D., lecturer in universities.
● vadym.vinnyk@solarwinds.com.
● vadim.vinnik@gmail.com.
2
Предпосылки
● Язык С++, эволюционируя, приобретает черты функционального.
○ Вспомните вчерашний мастер-класс.
● Функциональное программирование набирает популярность.
○ Перестаёт быть лабораторной диковинкой.
● В функциональных языках хорошо развиты средства обработки списков.
○ LISP = LISt Processing.
○ Три кита ФП: чистые функции, алгебраические типы данных и категория типов.
● Ряд средств для обработки последовательностей в функциональном
стиле уже есть:
○ Boost Ranges, range-v3, think-cell range.
● Но остаётся одна недостаточно хорошо покрытая область...
3
Обработка коллекций
● Элементы - однотипны.
○ Полиморфизм не запрещён…
○ но скрыт за единым для всех элементов интерфейсом.
● Элементы образуют линейную последовательность.
○ На уровне внутренней реализации структура данных может быть любой.
○ Однако на уровне интерфейса коллекция выглядит как последовательность.
● Последовательность - не обязательно конечна.
○ В ходе выполнения программы обрабатывается конечное число элементов.
○ Однако оно может не быть ограничено заранее.
○ Бесконечные списки характерны для ленивых языков, особенно - функциональных.
○ Коллекция не хранит элементы, а генерирует их по мере необходимости.
● Однократный поэлементный проход по коллекции.
4
Примеры
● Отыскать наибольший, наименьший элемент.
● Вычислить сумму элементов.
● Пропустить заданное число элементов.
● Отсечь после заданного числа элементов.
● Обрыв последовательности по условию.
● Отфильтровать элементы, удовлетворяющие условию.
● Преобразовать элементы (map, transform).
5
Как обработать коллекцию
● Цикл for с целочисленным индексом
○ ниже всякой критики и недостойно упоминания здесь;
● Цикл for с итераторами
○ ниже границы допустимого;
● Цикл for по диапазону (range-based for)
○ просто плохо в большинстве случаев;
● Высокоуровневые алгоритмы из std:: (copy, all_of, find_if)
○ нормально
● Свёртки
○ полностью универсально, но, пока не столь хорошо знакомо широким массам…
■ для того этот доклад и предназначен!
6
● Сумма последовательности чисел s = ∑{a1,…,an}.
● Рекуррентное определение:
○ s0 = 0;
○ sk+1 = sk + ak+1.
● Пример: s3 = s2+a3 = (s1+a2)+a3 =(((s0+a1))+a2)+a3 =(((0+a1))+a2)+a3.
● Это - левая свёртка по операции “+” с начальным значением 0.
● Правая свёртка - симметрично: a1+(a2+(a3+0))).
● Существует std::accumulate
○ Определена в #include <numeric>, явно неудачно.
○ Гораздо мощнее и универсальнее, чем принято думать.
○ Лишь очень частный случай из стройной системы понятий, разработанных в ФП.
Свёртка: начальный уровень
7
Сведение различных алгоритмов к свёрткам
● Наибольший элемент последовательности целых:
○ свёртка по функции std::max<int>
○ с начальным значением std::numeric_limits<int>::min().
● Удовлетворяют ли все элементы типа T предикату p:
○ свёртка по [p](bool b, T x) { return b && p(x); },
○ начальное значением true.
● Переворачивание контейнера:
○ свёртка по [](std::list<T> x, T y) { x.push_front(y); return x; },
○ начальное значение std::list<T>().
● Применение последовательности функций, fn(...f2(f1(x))...):
○ свёртка по [](T x, std::function<T(T)> f) { return f(x); },
○ начальное значение - x.
8
Свёртка, общее определение (псевдокод)
● f : U×T → U.
● a ∊ U.
● (foldl f a) : [T] → U.
● (foldl f a) [] = a.
● (foldl f a) (t:ts) = (foldl f (f a t)) ts.
● foldl : (U×T→U) × U → ([T]→U)
● g : T×U → U.
● a ∊ U.
● (foldr g a) : [T] → U.
● (foldr g a) [] = a.
● (foldr g a) (t:ts) = g t (foldr g a) ts.
● foldr : (T×U→U) × U → ([T]→U).
● Функция высшего порядка: аргумент и значение суть функции.
● Математически - совершенно симметричны.
● Одинаково ли удобны для программной реализации через рекурсию?
9
Левая и правая свёртки
● В случае левой свёртки - хвостовая рекурсия.
● Хорошо оптимизируется.
10
template <typename Result, typename Func, typename FwIt>
Result foldr(Func func, FwIt const from, FwIt const to, Result const seed)
{
if (from == to)
return seed;
auto const item = *from;
auto const next = advance(from); // replacement for from+1 and ++from
auto const rest = foldr(func, next, to, seed);
return func(item, rest);
}
Возможная реализация правой свёртки
11
Почти эквивалентно
return from == to
? seed
: func(
*from,
foldr(
func,
advance(from),
to,
seed));
12
Возможная реализация левой свёртки
template <typename Result, typename Func, typename FwIt>
Result foldl(Func func, FwIt const from, FwIt const to, Result const seed)
{
if (from == to)
return seed;
auto const new_seed = func(*from, seed);
auto const next = advance(from);
return foldl(func, next, to, new_seed);
}
13
Почти эквивалентно
return from == to
? seed
: foldl(
func,
advance(from),
to,
func(
*from,
seed));
14
Использование
std::string append_int(int x, std::string const& s) {
return s + std::to_string(x) + " ";
}
std::list<int> data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout
<< foldl<std::string>(append_int, std::begin(data), std::end(data), "")
<< std::endl // 0 1 2 3 4 5 6 7 8 9
<< foldr<std::string>(append_int, std::begin(data), std::end(data), "")
<< std::endl; // 9 8 7 6 5 4 3 2 1 0
15
Обобщение свёртки - катаморфизм
● Предыдущий вариант работает для пары итераторов.
● А вдруг структура данных играет роль контейнера, но итераторами в
стиле STL не обладает?
○ Самодельный связный список, например.
● Тогда функция обобщённой свёртки должна принимать:
○ состояние прохода по контейнеру;
○ функцию-распознаватель окончания прохода;
○ функцию-выделитель очередного элемента из состояния;
○ функцию-продвигатель состояния на следующий элемент.
● Альтернатива:
○ Конец прохода представлен отсутствием состояния (std::optional);
○ Распознавать конец прохода, выделять очередной элемент и переходить к следующему
одним действием.
16
template <
typename Result,
typename Func,
typename Unconser,
typename State>
Result foldl(
Func func,
Unconser unconser,
State state,
Result const& seed)
{
Возможная реализация
17
auto const maybe_uncons = unconser(state);
return !maybe_uncons.has_value()
? seed
: foldl(
func,
unconser,
maybe_uncons.value().second,
func(
*maybe_uncons.value().first,
seed));
}
Использование-1: пара итераторов как состояние
template <typename Container>
constexpr
container_range_t<Container> to_range(Container const& container)
noexcept
{
return std::make_pair(std::cbegin(container), std::cend(container));
}
18
Использование-2: деконструкция диапазона
template <typename ForwardIt>
maybe_t<ForwardIt> uncons_range(range_t<ForwardIt> const range) {
return range.first == range.second
? std::nullopt
: std::make_optional(
std::make_pair(
range.first,
std::make_pair(
advance(range.first),
range.second)));
}
19
Операция, обратная к свёртке, - развёртка
● Поддержка в C++ не обнаружена.
● Зато есть в Haskell.
● Тип: (b → Maybe (a, b)) → b → [a],
● Если (f x) == Nothing, то (unfoldr f x) == [],
● Иначе (f x) == Just (u, y), тогда (unfoldr f x) == u : (unfoldr f y).
20
Примеры развёрток
● Целое число n преобразовать в список
○ чисел [0, n);
○ разрядов двоичного или десятичного представления;
○ простых делителей;
○ чисел Фибоначчи до n-го включительно;
● Строку (длины n) преобразовать в список
○ символов;
○ лексем между заданными разделителями;
○ подстрок от символа номер k до конца строки, k ∊ [0, n);
○ вариантов синтаксического разбора (согласно некоторой неоднозначной грамматики).
21
Гиломорфизмы
● Композиция развёртки (анаморфизма) и свёртки (катаморфизма).
● Развернуть первоначальное значение в контейнер x → [a1, a2,…, an]…
● …и свернуть заново, по иной операции: [a1, a2,…, an] → y.
● Может быть определён и как самостоятельное понятие. Даны:
○ типы A (исходный), B (промежуточный), C (результат);
○ константа c ∊ C;
○ предикат p : A → Boolean (условие окончания развёртки);
○ функция f : A → A × B (развёртыватель);
○ функция g: B × C → C (свёртыватель).
● Тогда гиломорфизм h есть функция типа A → C.
○ Если p(a), то h(a) = c;
○ Иначе - пусть (a, b’) = f(a), тогда h(a) = f(b, h(a’)).
22
Как реализовать гиломорфизм на C++
template <
typename Result,
typename Unfolder,
typename Combiner,
typename Seed>
Result unfoldl(
Unfolder unfolder,
Combiner combiner,
Result const& initial,
Seed const& seed)
{
23
auto maybe_unfolded = unfolder(seed);
return !maybe_unfolded.has_value()
? initial
: unfoldl(
unfolder,
combiner,
combiner(
maybe_unfolded.value().first,
initial),
maybe_unfolded.value().second);
}
Как реализовать развёртку на C++
● Гиломорфизм определяют как развёртку и последующую свёртку…
● Но мы сделаем наоборот!
● Подставим в гиломорфизм тривиальную свёртку, которая накапливает
промежуточные значения b в контейнере.
● Тем самым, развёртка сведена к гиломорфизму.
24
Пример: генератор последовательности чисел
struct int_ascending_splitter {
int_ascending_splitter(int _upper_bound): upper_bound(_upper_bound) {}
std::optional<std::pair<int, int>> operator()(int x) const {
return x < upper_bound
? std::make_optional(std::make_pair(x, x + 1))
: std::nullopt;
}
int const upper_bound;
};
25
Пример: использование генератора
int_ascending_splitter generator(10);
auto s = unfoldl<std::string>(generator, append_int, "", 0);
// 0 1 2 3 4 5 6 7 8 9
26
Итоги и перспективы
● Подходы и идиомы, обычно характерные для языков функционального
программирования, вполне можно реализовать и использовать в C++.
● Традиционно сильными сторонами функциональных языков считались
гарантия корректности и лёгкость обработки сложно структурированных
данных. Добро пожаловать в C++.
● Больше перегрузок богу перегрузок! Чтобы *морфизмами стало удобно
пользоваться в ещё более разнообразных сценариях.
● Вопросы эффективности. Нужно добавить досрочный прерыватель
свёртки. Сколь бы ни сближался язык C++ с функциональной
парадигмой, вряд ли порядок вычисления станет ленивым.
27
}
28

More Related Content

What's hot

Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Nikolay Grebenshikov
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
 
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Nikolay Grebenshikov
 
Обработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявленийОбработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявленийcorehard_by
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksMikhail Kurnosov
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыcorehard_by
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...corehard_by
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
Лекция 4: Стек. Очередь
Лекция 4: Стек. ОчередьЛекция 4: Стек. Очередь
Лекция 4: Стек. ОчередьMikhail Kurnosov
 
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Platonov Sergey
 
теория рекурсивных функций
теория рекурсивных функцийтеория рекурсивных функций
теория рекурсивных функцийMariya_Lastochkina
 
Презентация на тему: ЕГЭ информатика
Презентация на тему: ЕГЭ информатикаПрезентация на тему: ЕГЭ информатика
Презентация на тему: ЕГЭ информатика2berkas
 
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...Alexey Paznikov
 
Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Fwdays
 
Лекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыЛекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыsimple_people
 
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Ontico
 
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Roman Orlov
 
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Platonov Sergey
 
Программирование линейных алгоритмов
Программирование линейных алгоритмовПрограммирование линейных алгоритмов
Программирование линейных алгоритмовAndrey Dolinin
 
Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Семинар 3. Многопоточное программирование на OpenMP (часть 3)Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Семинар 3. Многопоточное программирование на OpenMP (часть 3)Mikhail Kurnosov
 

What's hot (20)

Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
 
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
 
Обработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявленийОбработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявлений
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Лекция 4: Стек. Очередь
Лекция 4: Стек. ОчередьЛекция 4: Стек. Очередь
Лекция 4: Стек. Очередь
 
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
 
теория рекурсивных функций
теория рекурсивных функцийтеория рекурсивных функций
теория рекурсивных функций
 
Презентация на тему: ЕГЭ информатика
Презентация на тему: ЕГЭ информатикаПрезентация на тему: ЕГЭ информатика
Презентация на тему: ЕГЭ информатика
 
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
 
Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"
 
Лекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыЛекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмы
 
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
 
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
 
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
 
Программирование линейных алгоритмов
Программирование линейных алгоритмовПрограммирование линейных алгоритмов
Программирование линейных алгоритмов
 
Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Семинар 3. Многопоточное программирование на OpenMP (часть 3)Семинар 3. Многопоточное программирование на OpenMP (часть 3)
Семинар 3. Многопоточное программирование на OpenMP (часть 3)
 

Similar to C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - Вадим Винник

Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...Ontico
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013ScalaNsk
 
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ScalaNsk
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
Глава 3: примитивные типы и операции с ними в Java
Глава 3: примитивные типы и операции с ними в JavaГлава 3: примитивные типы и операции с ними в Java
Глава 3: примитивные типы и операции с ними в Javametaform
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Roman Brovko
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормозаAlexander Shigin
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.sharikdp
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.Igor Shkulipa
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Technopark
 
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...corehard_by
 
Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Qrator Labs
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняAlexander Granin
 
Лекция о языке программирования Haskell
Лекция о языке программирования HaskellЛекция о языке программирования Haskell
Лекция о языке программирования Haskellhusniyarova
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 

Similar to C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - Вадим Винник (20)

Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
 
алгоритм
алгоритмалгоритм
алгоритм
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
 
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
Глава 3: примитивные типы и операции с ними в Java
Глава 3: примитивные типы и операции с ними в JavaГлава 3: примитивные типы и операции с ними в Java
Глава 3: примитивные типы и операции с ними в Java
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1
 
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...
Этюды о буферизации: асинхронные оповещения, репликация обновлений, объединен...
 
Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодня
 
Рекурсия. Поиск
Рекурсия. ПоискРекурсия. Поиск
Рекурсия. Поиск
 
Лекция о языке программирования Haskell
Лекция о языке программирования HaskellЛекция о языке программирования Haskell
Лекция о языке программирования Haskell
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотниковcorehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титовcorehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...corehard_by
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филоновcorehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukićcorehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakovacorehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019corehard_by
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - Вадим Винник

  • 1. Обработка коллекций в функциональном стиле: от рекурсий к гиломорфизмам Вадим Винник
  • 2. Об авторе ● SolarWinds MSP. ● Technical lead developer. ● C++, C# for work. ● Haskell just for fun. ● Domains: ○ Network traffic filtering. ○ Data backup and recovery. ○ Business process simulation. ● Ph.D., lecturer in universities. ● vadym.vinnyk@solarwinds.com. ● vadim.vinnik@gmail.com. 2
  • 3. Предпосылки ● Язык С++, эволюционируя, приобретает черты функционального. ○ Вспомните вчерашний мастер-класс. ● Функциональное программирование набирает популярность. ○ Перестаёт быть лабораторной диковинкой. ● В функциональных языках хорошо развиты средства обработки списков. ○ LISP = LISt Processing. ○ Три кита ФП: чистые функции, алгебраические типы данных и категория типов. ● Ряд средств для обработки последовательностей в функциональном стиле уже есть: ○ Boost Ranges, range-v3, think-cell range. ● Но остаётся одна недостаточно хорошо покрытая область... 3
  • 4. Обработка коллекций ● Элементы - однотипны. ○ Полиморфизм не запрещён… ○ но скрыт за единым для всех элементов интерфейсом. ● Элементы образуют линейную последовательность. ○ На уровне внутренней реализации структура данных может быть любой. ○ Однако на уровне интерфейса коллекция выглядит как последовательность. ● Последовательность - не обязательно конечна. ○ В ходе выполнения программы обрабатывается конечное число элементов. ○ Однако оно может не быть ограничено заранее. ○ Бесконечные списки характерны для ленивых языков, особенно - функциональных. ○ Коллекция не хранит элементы, а генерирует их по мере необходимости. ● Однократный поэлементный проход по коллекции. 4
  • 5. Примеры ● Отыскать наибольший, наименьший элемент. ● Вычислить сумму элементов. ● Пропустить заданное число элементов. ● Отсечь после заданного числа элементов. ● Обрыв последовательности по условию. ● Отфильтровать элементы, удовлетворяющие условию. ● Преобразовать элементы (map, transform). 5
  • 6. Как обработать коллекцию ● Цикл for с целочисленным индексом ○ ниже всякой критики и недостойно упоминания здесь; ● Цикл for с итераторами ○ ниже границы допустимого; ● Цикл for по диапазону (range-based for) ○ просто плохо в большинстве случаев; ● Высокоуровневые алгоритмы из std:: (copy, all_of, find_if) ○ нормально ● Свёртки ○ полностью универсально, но, пока не столь хорошо знакомо широким массам… ■ для того этот доклад и предназначен! 6
  • 7. ● Сумма последовательности чисел s = ∑{a1,…,an}. ● Рекуррентное определение: ○ s0 = 0; ○ sk+1 = sk + ak+1. ● Пример: s3 = s2+a3 = (s1+a2)+a3 =(((s0+a1))+a2)+a3 =(((0+a1))+a2)+a3. ● Это - левая свёртка по операции “+” с начальным значением 0. ● Правая свёртка - симметрично: a1+(a2+(a3+0))). ● Существует std::accumulate ○ Определена в #include <numeric>, явно неудачно. ○ Гораздо мощнее и универсальнее, чем принято думать. ○ Лишь очень частный случай из стройной системы понятий, разработанных в ФП. Свёртка: начальный уровень 7
  • 8. Сведение различных алгоритмов к свёрткам ● Наибольший элемент последовательности целых: ○ свёртка по функции std::max<int> ○ с начальным значением std::numeric_limits<int>::min(). ● Удовлетворяют ли все элементы типа T предикату p: ○ свёртка по [p](bool b, T x) { return b && p(x); }, ○ начальное значением true. ● Переворачивание контейнера: ○ свёртка по [](std::list<T> x, T y) { x.push_front(y); return x; }, ○ начальное значение std::list<T>(). ● Применение последовательности функций, fn(...f2(f1(x))...): ○ свёртка по [](T x, std::function<T(T)> f) { return f(x); }, ○ начальное значение - x. 8
  • 9. Свёртка, общее определение (псевдокод) ● f : U×T → U. ● a ∊ U. ● (foldl f a) : [T] → U. ● (foldl f a) [] = a. ● (foldl f a) (t:ts) = (foldl f (f a t)) ts. ● foldl : (U×T→U) × U → ([T]→U) ● g : T×U → U. ● a ∊ U. ● (foldr g a) : [T] → U. ● (foldr g a) [] = a. ● (foldr g a) (t:ts) = g t (foldr g a) ts. ● foldr : (T×U→U) × U → ([T]→U). ● Функция высшего порядка: аргумент и значение суть функции. ● Математически - совершенно симметричны. ● Одинаково ли удобны для программной реализации через рекурсию? 9
  • 10. Левая и правая свёртки ● В случае левой свёртки - хвостовая рекурсия. ● Хорошо оптимизируется. 10
  • 11. template <typename Result, typename Func, typename FwIt> Result foldr(Func func, FwIt const from, FwIt const to, Result const seed) { if (from == to) return seed; auto const item = *from; auto const next = advance(from); // replacement for from+1 and ++from auto const rest = foldr(func, next, to, seed); return func(item, rest); } Возможная реализация правой свёртки 11
  • 12. Почти эквивалентно return from == to ? seed : func( *from, foldr( func, advance(from), to, seed)); 12
  • 13. Возможная реализация левой свёртки template <typename Result, typename Func, typename FwIt> Result foldl(Func func, FwIt const from, FwIt const to, Result const seed) { if (from == to) return seed; auto const new_seed = func(*from, seed); auto const next = advance(from); return foldl(func, next, to, new_seed); } 13
  • 14. Почти эквивалентно return from == to ? seed : foldl( func, advance(from), to, func( *from, seed)); 14
  • 15. Использование std::string append_int(int x, std::string const& s) { return s + std::to_string(x) + " "; } std::list<int> data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::cout << foldl<std::string>(append_int, std::begin(data), std::end(data), "") << std::endl // 0 1 2 3 4 5 6 7 8 9 << foldr<std::string>(append_int, std::begin(data), std::end(data), "") << std::endl; // 9 8 7 6 5 4 3 2 1 0 15
  • 16. Обобщение свёртки - катаморфизм ● Предыдущий вариант работает для пары итераторов. ● А вдруг структура данных играет роль контейнера, но итераторами в стиле STL не обладает? ○ Самодельный связный список, например. ● Тогда функция обобщённой свёртки должна принимать: ○ состояние прохода по контейнеру; ○ функцию-распознаватель окончания прохода; ○ функцию-выделитель очередного элемента из состояния; ○ функцию-продвигатель состояния на следующий элемент. ● Альтернатива: ○ Конец прохода представлен отсутствием состояния (std::optional); ○ Распознавать конец прохода, выделять очередной элемент и переходить к следующему одним действием. 16
  • 17. template < typename Result, typename Func, typename Unconser, typename State> Result foldl( Func func, Unconser unconser, State state, Result const& seed) { Возможная реализация 17 auto const maybe_uncons = unconser(state); return !maybe_uncons.has_value() ? seed : foldl( func, unconser, maybe_uncons.value().second, func( *maybe_uncons.value().first, seed)); }
  • 18. Использование-1: пара итераторов как состояние template <typename Container> constexpr container_range_t<Container> to_range(Container const& container) noexcept { return std::make_pair(std::cbegin(container), std::cend(container)); } 18
  • 19. Использование-2: деконструкция диапазона template <typename ForwardIt> maybe_t<ForwardIt> uncons_range(range_t<ForwardIt> const range) { return range.first == range.second ? std::nullopt : std::make_optional( std::make_pair( range.first, std::make_pair( advance(range.first), range.second))); } 19
  • 20. Операция, обратная к свёртке, - развёртка ● Поддержка в C++ не обнаружена. ● Зато есть в Haskell. ● Тип: (b → Maybe (a, b)) → b → [a], ● Если (f x) == Nothing, то (unfoldr f x) == [], ● Иначе (f x) == Just (u, y), тогда (unfoldr f x) == u : (unfoldr f y). 20
  • 21. Примеры развёрток ● Целое число n преобразовать в список ○ чисел [0, n); ○ разрядов двоичного или десятичного представления; ○ простых делителей; ○ чисел Фибоначчи до n-го включительно; ● Строку (длины n) преобразовать в список ○ символов; ○ лексем между заданными разделителями; ○ подстрок от символа номер k до конца строки, k ∊ [0, n); ○ вариантов синтаксического разбора (согласно некоторой неоднозначной грамматики). 21
  • 22. Гиломорфизмы ● Композиция развёртки (анаморфизма) и свёртки (катаморфизма). ● Развернуть первоначальное значение в контейнер x → [a1, a2,…, an]… ● …и свернуть заново, по иной операции: [a1, a2,…, an] → y. ● Может быть определён и как самостоятельное понятие. Даны: ○ типы A (исходный), B (промежуточный), C (результат); ○ константа c ∊ C; ○ предикат p : A → Boolean (условие окончания развёртки); ○ функция f : A → A × B (развёртыватель); ○ функция g: B × C → C (свёртыватель). ● Тогда гиломорфизм h есть функция типа A → C. ○ Если p(a), то h(a) = c; ○ Иначе - пусть (a, b’) = f(a), тогда h(a) = f(b, h(a’)). 22
  • 23. Как реализовать гиломорфизм на C++ template < typename Result, typename Unfolder, typename Combiner, typename Seed> Result unfoldl( Unfolder unfolder, Combiner combiner, Result const& initial, Seed const& seed) { 23 auto maybe_unfolded = unfolder(seed); return !maybe_unfolded.has_value() ? initial : unfoldl( unfolder, combiner, combiner( maybe_unfolded.value().first, initial), maybe_unfolded.value().second); }
  • 24. Как реализовать развёртку на C++ ● Гиломорфизм определяют как развёртку и последующую свёртку… ● Но мы сделаем наоборот! ● Подставим в гиломорфизм тривиальную свёртку, которая накапливает промежуточные значения b в контейнере. ● Тем самым, развёртка сведена к гиломорфизму. 24
  • 25. Пример: генератор последовательности чисел struct int_ascending_splitter { int_ascending_splitter(int _upper_bound): upper_bound(_upper_bound) {} std::optional<std::pair<int, int>> operator()(int x) const { return x < upper_bound ? std::make_optional(std::make_pair(x, x + 1)) : std::nullopt; } int const upper_bound; }; 25
  • 26. Пример: использование генератора int_ascending_splitter generator(10); auto s = unfoldl<std::string>(generator, append_int, "", 0); // 0 1 2 3 4 5 6 7 8 9 26
  • 27. Итоги и перспективы ● Подходы и идиомы, обычно характерные для языков функционального программирования, вполне можно реализовать и использовать в C++. ● Традиционно сильными сторонами функциональных языков считались гарантия корректности и лёгкость обработки сложно структурированных данных. Добро пожаловать в C++. ● Больше перегрузок богу перегрузок! Чтобы *морфизмами стало удобно пользоваться в ещё более разнообразных сценариях. ● Вопросы эффективности. Нужно добавить досрочный прерыватель свёртки. Сколь бы ни сближался язык C++ с функциональной парадигмой, вряд ли порядок вычисления станет ленивым. 27
  • 28. } 28