SlideShare a Scribd company logo
1 of 35
Обработка коллекций:
единая суть и множество
проявлений
Вадим Винник
Об авторе
● 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
● “Истина рождается как ересь, а умирает как предрассудок” (Т.Гексли).
● На конференциях теперь уже звучит как прописная истина.
● Программирование - композиционно.
● Состыковывание сущностей для получения сложных сущностей.
● Базовые сущности и способы их стыковки - очень различны.
● Неизменно одно - композиционная природа программных сущностей.
● Композиции составляют логическую структуру программирования.
● Сущности (объекты, классы, модули) - наполняют эту структуру.
● Композиции - первичны.
● Программные сущности - вторичны, определяются композициями.
Общий ответ: композиционность
4
● Последовательное выполнение, ветвление и цикл.
● Подпрограммы, модули и библиотеки.
● Перенаправление ввода-вывода в Unix shell
○ cat *.txt | grep pattern | wc -l
● DLL. COM. Assembly (.NET).
● Инкапсуляция - композиция данных и алгоритмов в одном объекте.
● Полиморфизм - композиция реализаций под общим интерфейсом.
● RESTful API - композиция клиентов и серверов.
● Интеграция компонентов контейнером IoC.
● Шаблоны ООП (примеры: стратегия, посетитель).
Примеры композиций
5
Отступление о структурализме
● Идея о первичности отношений, пришла из философского течения.
● Привычный подход: первичны вещи, над ними надстроены отношения.
● Противоположный подход: первичны отношения.
● Вещи - лишь узлы в ткани отношений.
● Отношения - форма существования вещей.
● Вещь существует лишь в той мере, в которой находится в определённых
отношениях с другими вещами.
● Вещь в себе - всё равно что не существует.
● Существовать - значит соотноситься.
● Пример. Знание о мире - не сумма фактов, а целостная картина.
● Отдельные факты менее важны, чем структура в целом.
6
От структурализма - к теории программирования
● Сущности индивидуализируются своими отношениями.
● В программировании отношения - это композиции.
● Всё, что можно с сущностями делать, определяется композициями;
○ Как строить новые;
○ Как использовать существующие;
○ Что о сущностях вообще можно знать.
● Каждая прикладная область программирования характеризуется своим
набором композиций.
● Адекватно понять и описать прикладную область программирования -
значит найти систему композиций, вскрывающих её суть.
● Если эта концептуальная задача решена, то кодирование - дело техники.
7
● Показать, как эволюционируют системы композиций.
● На примере одного узкого, но важного семейства задач.
● Цель - не научить итерированию по коллекциям, а показать, что…
● Для одного класса задач существует много систем композиций.
● Некоторые из них скрывают или искажают суть предметной области.
● Некоторые - адекватно отражают эту суть.
● Пользуясь определённым методом, можно от первых перейти к вторым.
Уточнённая постановка задачи
8
Обработка коллекций
● Элементы - однотипны.
○ Полиморфизм не запрещён…
○ но скрыт за единым для всех элементов интерфейсом.
● Элементы образуют линейную последовательность.
○ На уровне внутренней реализации структура данных может быть любой.
○ Однако на уровне интерфейса коллекция выглядит как последовательность.
● Последовательность - не обязательно конечна.
○ В ходе выполнения программы обрабатывается конечное число элементов.
○ Однако оно может не быть ограничено заранее.
○ Бесконечные списки характерны для ленивых языков, особенно - функциональных.
○ Коллекция не хранит элементы, а генерирует их по мере необходимости.
● Однократный поэлементный проход по коллекции.
9
Примеры
● Наибольший, наименьший элемент.
● Сумма, среднее арифметическое.
● Пропуск заданного числа элементов.
● Обрыв последовательности по условию.
● Фильтрация по условию.
● Преобразование значений (map, transform).
10
Примитивные решения: массив и файл
int sum_array(
int const* p,
size_t n
) {
size_t i;
s = 0;
for (i = 0; i != n; ++i)
s += p[i];
return s;
}
int sum_file(int fd)
{
int s = 0;
unsigned char x;
while (1 == read(fd, &x, 1))
s += x;
return s;
}
11
Примитивные решения: список
typedef struct node_t_
{
int value;
struct node_t_ *next;
} node_t;
int sum_list(node_t const* p)
{
int s = 0;
while (NULL != p) {
s += p->value;
p = p->next;
}
return s;
}
12
Примитивные решения
● Простота. Все использованные конструкции и понятия известны
начинающим программистам.
● Концептуально - эти алгоритмы делают одно и то же: вычисляют сумму
линейной последовательности чисел.
● Реализация выглядит совершенно по-разному.
● За различиями проявлений не просматривается единство сути.
● Сильная зависимость от реализации.
● Много кода нужно переписать, если меняется структура данных.
● Алгоритм плохо подходит для повторного использования.
13
Универсальное решение
void traverse(
(*is_end)(void*),
(*shift)(void*),
(*action)(
void* src,
void* state),
void *src,
void *state
)
{
while (!is_end(src))
{
action(src, state);
shift(src);
}
}
14
Универсальное решение: список
typedef struct list_t_
{
node_t *curr;
} list_t;
int lst_end(void *p)
{
list_t *t = (list_t*)p;
return NULL == t->curr;
}
void lst_shift(void *p) {
list_t *t = (list_t*)p;
t->curr = t->curr->next;
}
void lst_sum(void *p, void *q)
{
list_t *t = (list_t*) p;
int *s = (int*) q;
*s += t->curr->value;
}
15
Универсальное решение: список
node_t c = { 30, NULL };
node_t b = { 20, &c };
node_t a = { 10, &b };
list_t list = { &a };
int s1 = 0;
traverse(
lst_end,
lst_shift,
lst_sum,
&list,
&s1);
16
Универсальное решение: массив
typedef struct arr_t_ {
int *data;
size_t len;
size_t idx;
} arr_t;
int arr_end(void *p) {
arr_t *t = (arr_t*) p;
return t->idx == t->len;
}
void arr_shift(void *p) {
arr_t *t = (arr_t*) p;
++ t->idx;
}
void arr_sum(void *p, void *q)
{
arr_t *t = (arr_t*) p;
int *s = (int*) q;
*s += t->data[t->idx];
}
17
Универсальное решение: массив
int m[4] = { 3, 4, 5, 6 };
arr_t arr = {
m, /* data */
4, /* len */
0 /* idx */
};
int s2 = 0;
traverse(
arr_end,
arr_shift,
arr_sum,
&arr,
&s2);
18
Композиция адаптеров. Виртуальная коллекция
typedef struct even_t {
void *src;
int (*is_end)(void*);
void (*shift)(void*);
void (*act)(void*, void*);
} even_t;
int even_end(void *p) {
even_t *t = (even_t*) p;
return t->is_end(t->src);
}
void even_shift(void *p) {
even_t *t = (even_t*) p;
t->shift(t->src);
if (!t->is_end(t->src))
t->shift(t->src);
}
void even_act
(void *p, void *q) {
even_t *t = (even_t*) p;
t->act(t->src, q);
}
19
Композиция доступа. Виртуальная коллекция
even_t even = {
&arr,
arr_end,
arr_shift,
arr_sum
};
int s3 = 0;
traverse engine
even accessor
array accessor
array in memory
20
● Обход различных коллекций выглядит единообразно.
● Различия структур данных инкапсулированы в адаптерах доступа.
● Замена структуры данных требует лишь замены адаптеров.
● Композиция адаптеров позволяет гибко строить виртуальные коллекции.
● Шаблоны проектирования на языке без прямой поддержки ООП.
● Шаблоны “Итератор”, “Стратегия” и “Декоратор”.
● Более сложный для понимания код.
● Концептуально связанные детали разнесены по разным функциям.
● Простота использования - ценой сложной подготовки к использованию.
Анализ
21
● Внутренняя реализация сложна, но смотреть внутрь необходимости нет.
● Можно доверять корректности реализации.
● Единый интерфейс для различных структур данных (список, массив…).
● Единая абстракция: последовательность задана парой итераторов.
● Универсальный алгоритм обхода коллекции: std::for_each.
● Специализированные алгоритмы: count, all_of, accumulate, copy.
● Итератор “ходит” лишь по контейнерному объекту.
● Не хватает виртуальных коллекций (фильтр, преобразователь).
Контейнеры, итераторы и алгоритмы в STL
22
Декоратор для STL своими руками
● Последовательность элементов типа T задана парой итераторов [a, b).
● Задано отношение порядка “<” над объектами типа T.
● Задан унарный предикат p над объектами типа T.
● Найти итератор, указывающий на элемент диапазона [a, b), наименьший
(в смысле отношения “<”) среди тех, что удовлетворяют условию p…
● … или итератор b, если ни один элемент из [a, b) не удовлетворяет p.
● Концептуально:
○ Построить виртуальную последовательность, наложив фильтр по условию p на [a, b).
○ В полученной последовательности найти наименьший элемент.
● Пример: в наборе чисел {131, 17, 200, 507, 64, 7, 92, 108} найти
наименьшее среди нечётных.
23
Идея решения
● Построить новое отношение порядка “≺” с такими свойствами:
○ Если p(x)∧p(y), то x≺y ⇔ x<y.
○ Если ¬p(x)∧¬p(y), то x≺y ⇔ x<y.
○ Если p(x)∧¬p(y), то x≺y.
○ Если ¬p(x)∧p(y), то y≺x.
● Все объекты типа T, удовлетворяющие предикату p, считаются
меньшими (в смысле “≺”), чем не удовлетворяющие предикату.
● В множестве объектов, удовлетворяющих p, сохраняется порядок “<”.
● Остаётся найти наименьший относительно порядка “≺”.
● В терминах программирования: отношение “<” обернуть декоратором.
24
struct trait_min {
static bool select(bool x, bool y) {
return x;
}
};
// also trait_max - returns y
template <
class Pr, // predicate to filter
by
class Re, // ordering relation
class Tr> // trait_(min|max)
class cond_compare {
private:
Pr pred_;
Re rel_;
public:
cond_compare(Pr pred, Re rel)
: pred_(pred), rel_(rel)
{}
template <class T>
bool operator()(
T const& x, T const& y
) const {
bool b1 = pred_(x);
bool b2 = pred_(y);
return b1 == b2
? rel_(x, y)
: Tr::select(b1, b2);
}
};
25
cond_compare<Pr, Re, trait_min> c(pred, compare);
auto i = std::min_element(first, last, c);
● Прост в использовании и несложен в реализации.
● Согласуется с композиционным стилем.
● Может сочетаться с другими декораторами.
● Альтернатива - декоратор итератора, пропускающий элементы.
● Отсутствует в STL.
● Перекрывается возможностями Boost.
Анализ
26
Концептуальные недостатки STL
● В самодостаточные сущности оформлены лишь контейнеры (список,
вектор и др.).
● Диапазон моделируется не объектом, а парой итераторов.
● Для виртуальных коллекций нужны решения ad hoc.
● Понятие итератора одно, а роли - две.
● “Ошибки возникают по двум причинам: одну вещь называют разными
именами или одним именем называют разные вещи”.
● Итератор указывает на элемент или на границу между элементами?
● Подробности - в докладе А.Шёдля [https://youtu.be/vrCtS6FDay8]:
27
Boost.Range. Пример - вместо тысячи слов
void f(std::vector<int> const& v) {
auto w = v
| boost::adaptors::reversed
| boost::adaptors::uniqued
| boost::adaptors::filtered([](int x){ return x%10 > 5; })
| boost::adaptors::transformed([](int x){ return x*x; });
boost::copy(w, std::ostream_iterator<int>(std::cout));
}
28
Свёртка: примеры
● Сумма последовательности чисел s = ∑{a1,…,an}.
● Рекуррентное определение:
○ s0 = 0;
○ sk+1 = sk + ak+1;
○ s = sn.
● Пример: s3 = s2+a3 = (s1+a2)+a3 =(((s0+a1))+a2)+a3 =(((0+a1))+a2)+a3.
● Это - левая свёртка по операции “+” с начальным значением 0.
● Правая свёртка - симметрично.
● Например: a1+(a2+(a3+0))).
29
Свёртка, общее определение
● 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.
● 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.
● Функция высшего порядка: аргумент и значение суть функции.
● Математически - совершенно симметричны.
● Одинаково ли удобны для программной реализации через рекурсию?
30
Сведение различных алгоритмов к свёрткам
● Наибольший элемент последовательности целых:
○ свёртка по функции 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.
31
Поддержка свёрток в C++
● STL: std::accumulate(begin, end, initval, func).
● Для правой свёртки - использовать rbegin и rend.
● Boost: последовательность задана объектом, а не парой итераторов:
● Не хватает - досрочного прерывания (аналог break).
● Прямая поддержка в C++17 для вариадических шаблонов! Пример:
template<typename ...Args> auto sum(Args ...args)
{
return (args + ... + 0);
}
32
Что дальше?
● Обратная операция - развёртка, unfoldr.
○ Поддержка в 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).
● Свёрткиразвёртки естественно обобщаются для деревьев и др.
● Обобщение свёртки - катаморфизм.
● Обобщение развёртки - анаморфизм.
● Развёртка и затем свёртка? Гиломорфизм!
● Широко применяются в функциональном программировании.
● Раз уж C++ приобретает черты функционального языка...
33
Итоги
● Для любой области прикладных задач существует множество решений.
● Решение - это набор структур данных, алгоритмов, функций, классов.
● Решение должно отражать логику, внутренне присущую задачам.
● Если задачу приходится подгонять под инструмент - инструмент плох.
● Качество набора инструментов определяется их композиционностью.
● Композиционная обработка коллекций - в Boost.
● Свёрточно-развёрточный стиль представляет интерес.
● В C++ пока поддерживается слабо.
● Ждём нововведений?
34
}
35

More Related Content

What's hot

Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Nikolay Grebenshikov
 
Лекция 7. Бинарные кучи. Пирамидальная сортировка
Лекция 7. Бинарные кучи. Пирамидальная сортировкаЛекция 7. Бинарные кучи. Пирамидальная сортировка
Лекция 7. Бинарные кучи. Пирамидальная сортировкаMikhail Kurnosov
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Technopark
 
Алгоритмы и структуры данных весна 2014 лекция 2
Алгоритмы и структуры данных весна 2014 лекция 2Алгоритмы и структуры данных весна 2014 лекция 2
Алгоритмы и структуры данных весна 2014 лекция 2Technopark
 
Лекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмовЛекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмовMikhail Kurnosov
 
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Nikolay Grebenshikov
 
Лекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовЛекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовMikhail Kurnosov
 
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...Nikolay Grebenshikov
 
Проблемы 64-битного кода на примерах
Проблемы 64-битного кода на примерахПроблемы 64-битного кода на примерах
Проблемы 64-битного кода на примерахTatyanazaxarova
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Technopark
 
Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)Mikhail Kurnosov
 
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.SmartTools
 
Лекция 4. Стеки и очереди
Лекция 4. Стеки и очередиЛекция 4. Стеки и очереди
Лекция 4. Стеки и очередиMikhail Kurnosov
 
Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Mikhail Kurnosov
 
Лекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовЛекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовMikhail Kurnosov
 
C++ Базовый. Занятие 05.
C++ Базовый. Занятие 05.C++ Базовый. Занятие 05.
C++ Базовый. Занятие 05.Igor Shkulipa
 
Лекция 7: Бинарные кучи (пирамиды)
Лекция 7: Бинарные кучи (пирамиды)Лекция 7: Бинарные кучи (пирамиды)
Лекция 7: Бинарные кучи (пирамиды)Mikhail Kurnosov
 
C++ Базовый. Занятие 12.
C++ Базовый. Занятие 12.C++ Базовый. Занятие 12.
C++ Базовый. Занятие 12.Igor Shkulipa
 
05 динамическое программирование
05 динамическое программирование05 динамическое программирование
05 динамическое программированиеFedor Tsarev
 

What's hot (20)

Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
 
Лекция 7. Бинарные кучи. Пирамидальная сортировка
Лекция 7. Бинарные кучи. Пирамидальная сортировкаЛекция 7. Бинарные кучи. Пирамидальная сортировка
Лекция 7. Бинарные кучи. Пирамидальная сортировка
 
Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2Алгоритмы и структуры данных осень 2013 лекция 2
Алгоритмы и структуры данных осень 2013 лекция 2
 
Алгоритмы и структуры данных весна 2014 лекция 2
Алгоритмы и структуры данных весна 2014 лекция 2Алгоритмы и структуры данных весна 2014 лекция 2
Алгоритмы и структуры данных весна 2014 лекция 2
 
Лекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмовЛекция 11. Методы разработки алгоритмов
Лекция 11. Методы разработки алгоритмов
 
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
Лекция №15. Методы программирования. Предмет "Структуры и алгоритмы обработки...
 
Лекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмовЛекция 1. Анализ эффективности алгоритмов
Лекция 1. Анализ эффективности алгоритмов
 
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...
Лекция №2. Абстрактные типы данных. ООП. Предмет "Структуры и алгоритмы обраб...
 
Проблемы 64-битного кода на примерах
Проблемы 64-битного кода на примерахПроблемы 64-битного кода на примерах
Проблемы 64-битного кода на примерах
 
msumobi2. Лекция 1
msumobi2. Лекция 1msumobi2. Лекция 1
msumobi2. Лекция 1
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1
 
Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)Лекция 1. Амортизационный анализ (amortized analysis)
Лекция 1. Амортизационный анализ (amortized analysis)
 
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
 
Лекция 4. Стеки и очереди
Лекция 4. Стеки и очередиЛекция 4. Стеки и очереди
Лекция 4. Стеки и очереди
 
Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Векторизация кода (семинар 3)
Векторизация кода (семинар 3)
 
Лекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовЛекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмов
 
C++ Базовый. Занятие 05.
C++ Базовый. Занятие 05.C++ Базовый. Занятие 05.
C++ Базовый. Занятие 05.
 
Лекция 7: Бинарные кучи (пирамиды)
Лекция 7: Бинарные кучи (пирамиды)Лекция 7: Бинарные кучи (пирамиды)
Лекция 7: Бинарные кучи (пирамиды)
 
C++ Базовый. Занятие 12.
C++ Базовый. Занятие 12.C++ Базовый. Занятие 12.
C++ Базовый. Занятие 12.
 
05 динамическое программирование
05 динамическое программирование05 динамическое программирование
05 динамическое программирование
 

Similar to Обработка коллекций. Единая суть и множество проявлений

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...corehard_by
 
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...corehard_by
 
D-кучи и их применение
D-кучи и их применениеD-кучи и их применение
D-кучи и их применениеDEVTYPE
 
Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Qrator Labs
 
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Ontico
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
Лекция №8 "Методы снижения размерности пространства"
Лекция №8 "Методы снижения размерности пространства" Лекция №8 "Методы снижения размерности пространства"
Лекция №8 "Методы снижения размерности пространства" Technosphere1
 
Николай Паламарчук "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
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Technopark
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...pgdayrussia
 
Лекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыЛекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыsimple_people
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормозаAlexander Shigin
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.sharikdp
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняAlexander Granin
 
Лекция 13: Трудноразрешимые задачи. NP-полнота.
Лекция 13: Трудноразрешимые задачи. NP-полнота.Лекция 13: Трудноразрешимые задачи. NP-полнота.
Лекция 13: Трудноразрешимые задачи. NP-полнота.Mikhail Kurnosov
 
SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)Ontico
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 

Similar to Обработка коллекций. Единая суть и множество проявлений (20)

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
 
D-кучи и их применение
D-кучи и их применениеD-кучи и их применение
D-кучи и их применение
 
Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]Анализ количества посетителей на сайте [Считаем уникальные элементы]
Анализ количества посетителей на сайте [Считаем уникальные элементы]
 
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
Хочу знать, сколько уникальных посетителей было на моём сайте за произвольный...
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Лекция №8 "Методы снижения размерности пространства"
Лекция №8 "Методы снижения размерности пространства" Лекция №8 "Методы снижения размерности пространства"
Лекция №8 "Методы снижения размерности пространства"
 
Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1
 
Рекурсия. Поиск
Рекурсия. ПоискРекурсия. Поиск
Рекурсия. Поиск
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
 
Лекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмыЛекция 11 Приближенные алгоритмы
Лекция 11 Приближенные алгоритмы
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодня
 
Лекция 13: Трудноразрешимые задачи. NP-полнота.
Лекция 13: Трудноразрешимые задачи. NP-полнота.Лекция 13: Трудноразрешимые задачи. NP-полнота.
Лекция 13: Трудноразрешимые задачи. NP-полнота.
 
SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)
 
Иван Фролков. Tricky SQL
Иван Фролков. Tricky SQLИван Фролков. Tricky SQL
Иван Фролков. Tricky SQL
 
Принципы работы статического анализатора кода 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
 

Обработка коллекций. Единая суть и множество проявлений

  • 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. Постановка общей проблемы ● Сегодняшнее программирование разделено на множество областей. ● Ответвившись от единого истока, эти области далеко разошлись. ● Существует ли вообще концептуально единое программирование? ● На чём держится единство программирования? ● В чём его общезначимая суть, инвариантная во всех подразделах? 3
  • 4. ● “Истина рождается как ересь, а умирает как предрассудок” (Т.Гексли). ● На конференциях теперь уже звучит как прописная истина. ● Программирование - композиционно. ● Состыковывание сущностей для получения сложных сущностей. ● Базовые сущности и способы их стыковки - очень различны. ● Неизменно одно - композиционная природа программных сущностей. ● Композиции составляют логическую структуру программирования. ● Сущности (объекты, классы, модули) - наполняют эту структуру. ● Композиции - первичны. ● Программные сущности - вторичны, определяются композициями. Общий ответ: композиционность 4
  • 5. ● Последовательное выполнение, ветвление и цикл. ● Подпрограммы, модули и библиотеки. ● Перенаправление ввода-вывода в Unix shell ○ cat *.txt | grep pattern | wc -l ● DLL. COM. Assembly (.NET). ● Инкапсуляция - композиция данных и алгоритмов в одном объекте. ● Полиморфизм - композиция реализаций под общим интерфейсом. ● RESTful API - композиция клиентов и серверов. ● Интеграция компонентов контейнером IoC. ● Шаблоны ООП (примеры: стратегия, посетитель). Примеры композиций 5
  • 6. Отступление о структурализме ● Идея о первичности отношений, пришла из философского течения. ● Привычный подход: первичны вещи, над ними надстроены отношения. ● Противоположный подход: первичны отношения. ● Вещи - лишь узлы в ткани отношений. ● Отношения - форма существования вещей. ● Вещь существует лишь в той мере, в которой находится в определённых отношениях с другими вещами. ● Вещь в себе - всё равно что не существует. ● Существовать - значит соотноситься. ● Пример. Знание о мире - не сумма фактов, а целостная картина. ● Отдельные факты менее важны, чем структура в целом. 6
  • 7. От структурализма - к теории программирования ● Сущности индивидуализируются своими отношениями. ● В программировании отношения - это композиции. ● Всё, что можно с сущностями делать, определяется композициями; ○ Как строить новые; ○ Как использовать существующие; ○ Что о сущностях вообще можно знать. ● Каждая прикладная область программирования характеризуется своим набором композиций. ● Адекватно понять и описать прикладную область программирования - значит найти систему композиций, вскрывающих её суть. ● Если эта концептуальная задача решена, то кодирование - дело техники. 7
  • 8. ● Показать, как эволюционируют системы композиций. ● На примере одного узкого, но важного семейства задач. ● Цель - не научить итерированию по коллекциям, а показать, что… ● Для одного класса задач существует много систем композиций. ● Некоторые из них скрывают или искажают суть предметной области. ● Некоторые - адекватно отражают эту суть. ● Пользуясь определённым методом, можно от первых перейти к вторым. Уточнённая постановка задачи 8
  • 9. Обработка коллекций ● Элементы - однотипны. ○ Полиморфизм не запрещён… ○ но скрыт за единым для всех элементов интерфейсом. ● Элементы образуют линейную последовательность. ○ На уровне внутренней реализации структура данных может быть любой. ○ Однако на уровне интерфейса коллекция выглядит как последовательность. ● Последовательность - не обязательно конечна. ○ В ходе выполнения программы обрабатывается конечное число элементов. ○ Однако оно может не быть ограничено заранее. ○ Бесконечные списки характерны для ленивых языков, особенно - функциональных. ○ Коллекция не хранит элементы, а генерирует их по мере необходимости. ● Однократный поэлементный проход по коллекции. 9
  • 10. Примеры ● Наибольший, наименьший элемент. ● Сумма, среднее арифметическое. ● Пропуск заданного числа элементов. ● Обрыв последовательности по условию. ● Фильтрация по условию. ● Преобразование значений (map, transform). 10
  • 11. Примитивные решения: массив и файл int sum_array( int const* p, size_t n ) { size_t i; s = 0; for (i = 0; i != n; ++i) s += p[i]; return s; } int sum_file(int fd) { int s = 0; unsigned char x; while (1 == read(fd, &x, 1)) s += x; return s; } 11
  • 12. Примитивные решения: список typedef struct node_t_ { int value; struct node_t_ *next; } node_t; int sum_list(node_t const* p) { int s = 0; while (NULL != p) { s += p->value; p = p->next; } return s; } 12
  • 13. Примитивные решения ● Простота. Все использованные конструкции и понятия известны начинающим программистам. ● Концептуально - эти алгоритмы делают одно и то же: вычисляют сумму линейной последовательности чисел. ● Реализация выглядит совершенно по-разному. ● За различиями проявлений не просматривается единство сути. ● Сильная зависимость от реализации. ● Много кода нужно переписать, если меняется структура данных. ● Алгоритм плохо подходит для повторного использования. 13
  • 14. Универсальное решение void traverse( (*is_end)(void*), (*shift)(void*), (*action)( void* src, void* state), void *src, void *state ) { while (!is_end(src)) { action(src, state); shift(src); } } 14
  • 15. Универсальное решение: список typedef struct list_t_ { node_t *curr; } list_t; int lst_end(void *p) { list_t *t = (list_t*)p; return NULL == t->curr; } void lst_shift(void *p) { list_t *t = (list_t*)p; t->curr = t->curr->next; } void lst_sum(void *p, void *q) { list_t *t = (list_t*) p; int *s = (int*) q; *s += t->curr->value; } 15
  • 16. Универсальное решение: список node_t c = { 30, NULL }; node_t b = { 20, &c }; node_t a = { 10, &b }; list_t list = { &a }; int s1 = 0; traverse( lst_end, lst_shift, lst_sum, &list, &s1); 16
  • 17. Универсальное решение: массив typedef struct arr_t_ { int *data; size_t len; size_t idx; } arr_t; int arr_end(void *p) { arr_t *t = (arr_t*) p; return t->idx == t->len; } void arr_shift(void *p) { arr_t *t = (arr_t*) p; ++ t->idx; } void arr_sum(void *p, void *q) { arr_t *t = (arr_t*) p; int *s = (int*) q; *s += t->data[t->idx]; } 17
  • 18. Универсальное решение: массив int m[4] = { 3, 4, 5, 6 }; arr_t arr = { m, /* data */ 4, /* len */ 0 /* idx */ }; int s2 = 0; traverse( arr_end, arr_shift, arr_sum, &arr, &s2); 18
  • 19. Композиция адаптеров. Виртуальная коллекция typedef struct even_t { void *src; int (*is_end)(void*); void (*shift)(void*); void (*act)(void*, void*); } even_t; int even_end(void *p) { even_t *t = (even_t*) p; return t->is_end(t->src); } void even_shift(void *p) { even_t *t = (even_t*) p; t->shift(t->src); if (!t->is_end(t->src)) t->shift(t->src); } void even_act (void *p, void *q) { even_t *t = (even_t*) p; t->act(t->src, q); } 19
  • 20. Композиция доступа. Виртуальная коллекция even_t even = { &arr, arr_end, arr_shift, arr_sum }; int s3 = 0; traverse engine even accessor array accessor array in memory 20
  • 21. ● Обход различных коллекций выглядит единообразно. ● Различия структур данных инкапсулированы в адаптерах доступа. ● Замена структуры данных требует лишь замены адаптеров. ● Композиция адаптеров позволяет гибко строить виртуальные коллекции. ● Шаблоны проектирования на языке без прямой поддержки ООП. ● Шаблоны “Итератор”, “Стратегия” и “Декоратор”. ● Более сложный для понимания код. ● Концептуально связанные детали разнесены по разным функциям. ● Простота использования - ценой сложной подготовки к использованию. Анализ 21
  • 22. ● Внутренняя реализация сложна, но смотреть внутрь необходимости нет. ● Можно доверять корректности реализации. ● Единый интерфейс для различных структур данных (список, массив…). ● Единая абстракция: последовательность задана парой итераторов. ● Универсальный алгоритм обхода коллекции: std::for_each. ● Специализированные алгоритмы: count, all_of, accumulate, copy. ● Итератор “ходит” лишь по контейнерному объекту. ● Не хватает виртуальных коллекций (фильтр, преобразователь). Контейнеры, итераторы и алгоритмы в STL 22
  • 23. Декоратор для STL своими руками ● Последовательность элементов типа T задана парой итераторов [a, b). ● Задано отношение порядка “<” над объектами типа T. ● Задан унарный предикат p над объектами типа T. ● Найти итератор, указывающий на элемент диапазона [a, b), наименьший (в смысле отношения “<”) среди тех, что удовлетворяют условию p… ● … или итератор b, если ни один элемент из [a, b) не удовлетворяет p. ● Концептуально: ○ Построить виртуальную последовательность, наложив фильтр по условию p на [a, b). ○ В полученной последовательности найти наименьший элемент. ● Пример: в наборе чисел {131, 17, 200, 507, 64, 7, 92, 108} найти наименьшее среди нечётных. 23
  • 24. Идея решения ● Построить новое отношение порядка “≺” с такими свойствами: ○ Если p(x)∧p(y), то x≺y ⇔ x<y. ○ Если ¬p(x)∧¬p(y), то x≺y ⇔ x<y. ○ Если p(x)∧¬p(y), то x≺y. ○ Если ¬p(x)∧p(y), то y≺x. ● Все объекты типа T, удовлетворяющие предикату p, считаются меньшими (в смысле “≺”), чем не удовлетворяющие предикату. ● В множестве объектов, удовлетворяющих p, сохраняется порядок “<”. ● Остаётся найти наименьший относительно порядка “≺”. ● В терминах программирования: отношение “<” обернуть декоратором. 24
  • 25. struct trait_min { static bool select(bool x, bool y) { return x; } }; // also trait_max - returns y template < class Pr, // predicate to filter by class Re, // ordering relation class Tr> // trait_(min|max) class cond_compare { private: Pr pred_; Re rel_; public: cond_compare(Pr pred, Re rel) : pred_(pred), rel_(rel) {} template <class T> bool operator()( T const& x, T const& y ) const { bool b1 = pred_(x); bool b2 = pred_(y); return b1 == b2 ? rel_(x, y) : Tr::select(b1, b2); } }; 25
  • 26. cond_compare<Pr, Re, trait_min> c(pred, compare); auto i = std::min_element(first, last, c); ● Прост в использовании и несложен в реализации. ● Согласуется с композиционным стилем. ● Может сочетаться с другими декораторами. ● Альтернатива - декоратор итератора, пропускающий элементы. ● Отсутствует в STL. ● Перекрывается возможностями Boost. Анализ 26
  • 27. Концептуальные недостатки STL ● В самодостаточные сущности оформлены лишь контейнеры (список, вектор и др.). ● Диапазон моделируется не объектом, а парой итераторов. ● Для виртуальных коллекций нужны решения ad hoc. ● Понятие итератора одно, а роли - две. ● “Ошибки возникают по двум причинам: одну вещь называют разными именами или одним именем называют разные вещи”. ● Итератор указывает на элемент или на границу между элементами? ● Подробности - в докладе А.Шёдля [https://youtu.be/vrCtS6FDay8]: 27
  • 28. Boost.Range. Пример - вместо тысячи слов void f(std::vector<int> const& v) { auto w = v | boost::adaptors::reversed | boost::adaptors::uniqued | boost::adaptors::filtered([](int x){ return x%10 > 5; }) | boost::adaptors::transformed([](int x){ return x*x; }); boost::copy(w, std::ostream_iterator<int>(std::cout)); } 28
  • 29. Свёртка: примеры ● Сумма последовательности чисел s = ∑{a1,…,an}. ● Рекуррентное определение: ○ s0 = 0; ○ sk+1 = sk + ak+1; ○ s = sn. ● Пример: s3 = s2+a3 = (s1+a2)+a3 =(((s0+a1))+a2)+a3 =(((0+a1))+a2)+a3. ● Это - левая свёртка по операции “+” с начальным значением 0. ● Правая свёртка - симметрично. ● Например: a1+(a2+(a3+0))). 29
  • 30. Свёртка, общее определение ● 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. ● 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. ● Функция высшего порядка: аргумент и значение суть функции. ● Математически - совершенно симметричны. ● Одинаково ли удобны для программной реализации через рекурсию? 30
  • 31. Сведение различных алгоритмов к свёрткам ● Наибольший элемент последовательности целых: ○ свёртка по функции 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. 31
  • 32. Поддержка свёрток в C++ ● STL: std::accumulate(begin, end, initval, func). ● Для правой свёртки - использовать rbegin и rend. ● Boost: последовательность задана объектом, а не парой итераторов: ● Не хватает - досрочного прерывания (аналог break). ● Прямая поддержка в C++17 для вариадических шаблонов! Пример: template<typename ...Args> auto sum(Args ...args) { return (args + ... + 0); } 32
  • 33. Что дальше? ● Обратная операция - развёртка, unfoldr. ○ Поддержка в 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). ● Свёрткиразвёртки естественно обобщаются для деревьев и др. ● Обобщение свёртки - катаморфизм. ● Обобщение развёртки - анаморфизм. ● Развёртка и затем свёртка? Гиломорфизм! ● Широко применяются в функциональном программировании. ● Раз уж C++ приобретает черты функционального языка... 33
  • 34. Итоги ● Для любой области прикладных задач существует множество решений. ● Решение - это набор структур данных, алгоритмов, функций, классов. ● Решение должно отражать логику, внутренне присущую задачам. ● Если задачу приходится подгонять под инструмент - инструмент плох. ● Качество набора инструментов определяется их композиционностью. ● Композиционная обработка коллекций - в Boost. ● Свёрточно-развёрточный стиль представляет интерес. ● В C++ пока поддерживается слабо. ● Ждём нововведений? 34
  • 35. } 35