Обработка коллекций наизнанку: как применить много функций к одному аргументу. Вадим Винник. Corehard Spring 2019

This slide intentionally left
blank
There is nothing to read here
Обработка коллекций
наизнанку:
много функций,
один аргумент
Вадим Винник
Мотивация
● Парадигма функционального программирования проникает в C++:
○ operator(), функциональные объекты;
○ оптимизация хвостовой рекурсии;
○ λ-функции;
○ std::function, std::bind;
○ std::transform, std::accumulate - аналоги fmap и foldl/foldr;
○ template metaprogramming - позволяет моделировать классы типов;
● Не просто пополнение новыми инструментами, а парадигмальный сдвиг!
● Понятия и методы ФП остаются малознакомыми широкому сообществу.
● Цель доклада - продемонстрировать логику программирования,
тривиальную для ФП, но безумную с точки зрения традиций ООП.
● Показать, сколь проста её реализация на языке C++.
3
Немного программологии: интенсиональность
● Сущности в программировании выступают в трёх ролях:
○ просто сущности;
○ средства построения сущностей;
○ средства применения средств построения (в частности, средства управления
средствами построения).
● Эта не имманентная характеристика сущности, а внешняя.
● Определяется не сущностью самой по себе, а способом её
использования в конкретном контексте.
● Сущности в программировании - интенсиональны.
● Пример - функция:
○ чаще всего выступает средством построения объектов данных;
○ но в может и сама выступать объектом построения.
4
Немного программологии: композиционность
● Композиции строят более сложные программные сущности из
относительно простых.
○ Чаще всего имеют в виду композиции программ, но не менее важны композиции
данных, данных с программами и т.д.
● Обычно их относят к интенсиональному типу средств построения.
● Не менее важно рассматривать их и как средства применения и, в
частности, управления применением:
○ циклическая композиция управляет выполнением оператора-тела, который выступает
средством построения объектов данных;
○ объект, реализующий идиому RAII, управляет применением заданного действия.
● Композицию можно даже относить к интенсиональному типу 1
(гомоиконичность, LISP), но это далеко уводит от темы доклада.
5
Немного программологии: композиционность
● Всякое ответвление программирования характеризуется своим набором
композиций.
● Эти композиции:
○ выступают инструментами сочленения более сложных единиц из простых;
○ управляют применением частей в составе целого в процессе его работы.
● Именно композиции определяют суть и дух всякого программирования.
● Суть функционального программирования - не в чистоте функций и
отказе от разрушающего присваивания.
● Напротив: чистота функций - средство для поддержки композиций ФП.
6
Проникновение ФП в C++
● Импорт композиций ФП в среду языка C++ и сложившейся вокруг него
культуры программирования.
● Композиции, нашедшие широкое применение в ФП, для человека,
привычного к ООП, могут выглядеть странно и пугающе.
● Композиции ФП часто основаны на λ-исчислении, комбинаторах и теории
категорий (функторы, монады).
● Обобщённая цель доклада: показать, как выгод, которые в ФП
достигаются с помощью монад, можно добиться штатными средствами
языка С++, не упоминая монады в явном виде.
7
Вместо тысячи слов
fmap
x1 x2 xn
f
y1 y2 yn
fsum
f1 f2 fn
x
y
8
Пример
● Пусть дана совокупность функций каждая из которых может дать
искомый результат или неудачу.
● Например:
○ Попытаться извлечь параметр hostname из файла настроек в текущей директории;
○ Попытаться извлечь hostname из настроек в домашней директории пользователя;
○ Попытаться извлечь hostname из глобального файла настроек;
○ Взять hostname по умолчанию, прошитый в программе.
● Каждая, кроме последней, может окончиться неудачей: отсутствует
файл или в файле нет такого параметра.
● Чтобы получить правильный hostname, нужно пытаться применять эти
функции в том же порядке одну за другой до первой удачи.
9
● Если T - тип, то вместо std::optional<T> будем писать T? (возможно, T).
● Специальный объект “отсутствие” (std::nullopt) обозначим ⊥ (дно).
● Рассматриваем функции типа A1,…, Am → T?.
● Функция ⟘ (пустая) - для любых кортежей x правильного типа ⟘(x) = ⊥.
● Всюду определённые функции: t(x) ≠ ⊥ для любых x (Tot).
● Отношение порядка: f ≼ g (“f есть подфункция g”), если для любых x
из f(x) ≠ ⊥ следует g(x) = f(x).
● Функция ⟘ - наименьшая, а любая всюду определённая t -
максимальная (но не наибольшая) относительно порядка ≼.
● Одноточечная функция: p[a, y](x) = y, если x = a; иначе p[a, y](x) = ⊥.
● Совместимость: f ≈ g, если из f(x) ≠ g(x) следует f(x) = ⊥ или g(x) = ⊥.
Немного обозначений для краткости
10
Сумма функций: определение
● Пусть дана совокупность функций f1,…, fn типа A1,…, Am → T?.
● Их сумма h = ∑[f1,…, fn] = f1 ⊕…⊕ fn есть функция того же типа.
● Если fk(x) = ⊥ для всех k ∊ {1, …, n}, то h(x) = ⊥.
● Иначе h(x) = fk(x), где k ∊ {1, …, n} - наименьшее такое число, что
○ fk(x) ≠ ⊥,
○ fi(x) = ⊥ для всех i ∊ {1, …, k-1}.
● Неформально говоря: сумма функций по очереди пробует применять
все функции-слагаемые до первой удачи.
● Сумма функций терпит неудачу, если неудачу терпят все слагаемые.
11
Свойства суммы функций
● Некоммутативность: (p[a, y] ⊕ p[a, z])(a) = y, но (p[a, z] ⊕ p[a, y])(a) = z.
● Коммутативность при условии: если f ≈ g, то f ⊕ g = g ⊕ f.
● Ассоциативность: (f ⊕ g) ⊕ h = f ⊕ (g ⊕ h).
● Левый нуль: ⟘ ⊕ f = f.
● Правый нуль: f ⊕ ⟘ = f.
● Идемпотентность: f ⊕ g ⊕ g = f ⊕ g
○ в программировании работает только для чистых функций.
● Неподвижность максимума слева: если t ∊ Tot, то t ⊕ f = t.
● Сохранение максимума справа: если t ∊ Tot, то (f ⊕ t) ∊ Tot.
● Монотонность: f ≼ f ⊕ g.
● Поглощение меньшего большим: если f ≼ g, то f ⊕ g = g.
12
Рекуррентное определение суммы функций
● База (сумма из 0 слагаемых есть 0):
∑ [ ] = ⟘.
● Шаг: выразить сумму n слагаемого через сумму n-1 слагаемых (n > 0):
h = ∑ [f1,…, fn] - это такая функция, что для любого x:
● Если f1(x) = y ≠ ⊥, то h(x) = y.
● В противном случае h(x) = g(x), где
g = ∑ [f2,…, fn].
13
Реализация
https://github.com/vadimvinnik/xfunctional
14
template <typename R, typename ...Args>
struct default_constf {
using value_t = R;
static R make(Args...) { return {}; }
};
template <typename R, typename ...Args>
struct constf {
using value_t = R;
template <R Value>
static constexpr R make(Args...) { return Value; }
};
template <typename R, typename ...Args>
class constf_t {
R const value_;
public:
using value_t = R;
explicit constf_t(R const& value) : value_(value) {}
R operator()(Args const&...) const { return value_; }
};
Вспомогательные
функции-константы
создаются на этапе
выполнения
создаются на этапе
компиляции
15
template <typename R, typename ...Args>
class single_point_t {
R const value_;
std::tuple<Args...> const args_;
public:
using value_t = R;
using maybe_t = std::optional<R>;
single_point_t(R const& value, Args const&... args) :
value_(value),
args_(args...)
{}
maybe_t operator() (Args ...args) const {
return args_ == std::make_tuple(args...)
? maybe_t {value_}
: std::nullopt;
}
};
одноточечная функция
p[a, y]
16
template <typename R, typename ...Args>
struct fsum {
using maybe_t = std::optional<R>;
using funcptr_t = maybe_t(*)(Args...);
static funcptr_t make() {
return &(default_constf<maybe_t, Args...>::make);
}
template <typename F, typename ...Fs>
static auto make(F f, Fs ...fs) {
return [f, fs...](Args ...args) -> maybe_t {
maybe_t const r = f(args...);
return r.has_value()
? r
: make(fs...)(args...);
};
}
строит сумму функций на
этапе компиляции
прямая реализация
рекуррентного
определения
17
// continued:
// template <typename R, typename ...Args>
// struct fsum {
template <typename I>
static maybe_t exec(I from, I to, Args ...args) {
while (from != to) {
maybe_t const r = (*from)(args...);
if (r.has_value())
return r;
++from;
}
return std::nullopt;
}
};
вычисление значения
суммы функций на этапе
выполнения
18
using sum_t = xfunctional::fsum<number_t, std::string>;
auto string_to_number = sum_t::make(
decimal_to_number,
english_numeral_to_number,
roman_to_number);
assert(string_to_number("2019") == 2019);
assert(string_to_number("twelve") == 12);
assert(string_to_number("XIV") == 14);
assert(string_to_number("sieben") == std::nullopt);
пример использования
19
using sum_t = xfunctional::fsum<int>;
int count = 0;
auto chain = sum_t::make(
[&count]() { ++count; return std::nullopt; },
[&count]() { ++count; return std::nullopt; },
[&count]() { ++count; return std::nullopt; },
[&count]() { ++count; return 7; },
[&count]() { ++count; return std::nullopt; },
[&count]() { ++count; return 3; }
);
auto const value = chain();
assert(value == 7);
assert(count == 4);
демонстрация хода
вычислений
20
using func_t = xfunctional::single_point_t<std::string, int>;
using sum_t = xfunctional::fsum<std::string, int>;
auto int_to_string = sum_t::make(
func_t { "zero" , 0 },
func_t { "one" , 1 },
func_t { "two" , 2 },
func_t { "zero2", 0 }, // !
func_t { "three", 3 }
);
assert(int_to_string(0) == "zero");
assert(int_to_string(2) == "two");
assert(int_to_string(3) == "three");
assert(int_to_string(4) == std::nullopt);
окончание по первому
успеху
21
Итоги и дальнейшие вопросы
● Связь с шаблонами “Chain of Responsibility” и “Composite”.
● Этот код работает на production.
● Для ряда практических задач стиль ФП - наиболее адекватное средство
выражения их естественной логики.
● Если функция f имеет побочные эффекты, то бесконечная сумма
∑ [f, f, …] представляет собой… что?
● Предел бесконечной монотонной последовательности и заодно
неподвижная точка операции ⊕f - это цикл!
● А теперь вывернем наизнанку! Применять следующую функцию к
результату предыдущей до первой неудачи.
● Получим монаду Maybe - но это уже совсем другая история.
22
} // the talk
1 of 23

Recommended

Python by
PythonPython
PythonОля Ефимова
3.8K views58 slides
Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30... by
Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30...Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30...
Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30...Dev2Dev
897 views74 slides
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы by
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципыHappyDev
1K views62 slides
паскаль. часть1 by
паскаль. часть1паскаль. часть1
паскаль. часть1igorm9so
4.1K views159 slides
математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск... by
математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск...математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск...
математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск...etyumentcev
3.1K views71 slides

More Related Content

What's hot

Алгоритмы и языки программирования by
Алгоритмы и языки программированияАлгоритмы и языки программирования
Алгоритмы и языки программированияTheoretical mechanics department
1.6K views74 slides
82 by
8282
82Kirrrr123
274 views10 slides
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж... by
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
1.8K views86 slides
87 by
8787
87Kirrrr123
262 views90 slides
Математическое обоснование S.O.L.I.D принципов by
Математическое обоснование S.O.L.I.D принциповМатематическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принциповetyumentcev
1.7K views61 slides
структура программы by
структура программыструктура программы
структура программыЕлена Ключева
541 views10 slides

What's hot(20)

Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж... by Alexey Paznikov
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Alexey Paznikov1.8K views
Математическое обоснование S.O.L.I.D принципов by etyumentcev
Математическое обоснование S.O.L.I.D принциповМатематическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принципов
etyumentcev1.7K views
Запись вспомогательный алгоритмов на языка Паскаль by Andrey Dolinin
Запись вспомогательный алгоритмов на языка ПаскальЗапись вспомогательный алгоритмов на языка Паскаль
Запись вспомогательный алгоритмов на языка Паскаль
Andrey Dolinin1.3K views
Конкурентные ассоциативные контейнеры by corehard_by
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
corehard_by341 views
Лекция 4. Производные типы данных в стандарте MPI by Alexey Paznikov
Лекция 4. Производные типы данных в стандарте MPIЛекция 4. Производные типы данных в стандарте MPI
Лекция 4. Производные типы данных в стандарте MPI
Alexey Paznikov1.2K views
19 pascal urok_3 by Ann Eres
19 pascal urok_319 pascal urok_3
19 pascal urok_3
Ann Eres791 views
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks by Mikhail Kurnosov
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov1.6K views
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель... by Alexey Paznikov
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Лекция 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллель...
Alexey Paznikov2.7K views
Языки программирования by paulsmirnov
Языки программированияЯзыки программирования
Языки программирования
paulsmirnov687 views
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками! by Yandex
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Yandex2.6K views
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI... by Alexey Paznikov
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Alexey Paznikov2.4K views
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы. by Roman Orlov
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Roman Orlov427 views

Similar to Обработка коллекций наизнанку: как применить много функций к одному аргументу. Вадим Винник. Corehard Spring 2019

Обработка коллекций. Единая суть и множество проявлений by
Обработка коллекций. Единая суть и множество проявленийОбработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявленийcorehard_by
178 views35 slides
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео... by
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Nikolay Grebenshikov
2K views37 slides
Back to the future: Функциональное программирование вчера и сегодня by
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняAlexander Granin
945 views50 slides
Николай Паламарчук "Functional Programming basics for PHP developers" by
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Fwdays
326 views60 slides
Лекция о языке программирования Haskell by
Лекция о языке программирования HaskellЛекция о языке программирования Haskell
Лекция о языке программирования Haskellhusniyarova
748 views47 slides
Pyton – пробуем функциональный стиль by
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
3.9K views50 slides

Similar to Обработка коллекций наизнанку: как применить много функций к одному аргументу. Вадим Винник. Corehard Spring 2019(20)

Обработка коллекций. Единая суть и множество проявлений by corehard_by
Обработка коллекций. Единая суть и множество проявленийОбработка коллекций. Единая суть и множество проявлений
Обработка коллекций. Единая суть и множество проявлений
corehard_by178 views
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео... by Nikolay Grebenshikov
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Back to the future: Функциональное программирование вчера и сегодня by Alexander Granin
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодня
Alexander Granin945 views
Николай Паламарчук "Functional Programming basics for PHP developers" by Fwdays
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"
Fwdays326 views
Лекция о языке программирования Haskell by husniyarova
Лекция о языке программирования HaskellЛекция о языке программирования Haskell
Лекция о языке программирования Haskell
husniyarova748 views
Pyton – пробуем функциональный стиль by Python Meetup
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
Python Meetup3.9K views
Как приручить дракона: введение в LLVM by Tech Talks @NSU
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
Tech Talks @NSU351 views
Tech Talks @NSU: Как приручить дракона: введение в LLVM by Tech Talks @NSU
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU184 views
О-символика by DEVTYPE
О-символикаО-символика
О-символика
DEVTYPE2K views
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур... by Tech Talks @NSU
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU209 views
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе" by Yandex
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Yandex1.9K views
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr... by OdessaFrontend
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
OdessaFrontend214 views
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления by Alexey Paznikov
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисленияПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
Alexey Paznikov1K views
Haskell Type System with Dzmitry Ivashnev. by Sergey Tihon
Haskell Type System with Dzmitry Ivashnev.Haskell Type System with Dzmitry Ivashnev.
Haskell Type System with Dzmitry Ivashnev.
Sergey Tihon561 views
Характерные черты функциональных языков программирования by Alex.Kolonitsky
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
Alex.Kolonitsky1.4K views
Fields of Experts (доклад) by romovpa
Fields of Experts (доклад)Fields of Experts (доклад)
Fields of Experts (доклад)
romovpa500 views
Алгоритмы и структуры данных осень 2013 лекция 1 by Technopark
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1
Technopark1.5K views

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan... by
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...corehard_by
643 views44 slides
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про... by
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...corehard_by
492 views16 slides
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников 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 ... - Евгений Охотниковcorehard_by
117 views69 slides
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов by
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титовcorehard_by
162 views20 slides
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген... by
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...corehard_by
84 views47 slides
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков by
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
235 views49 slides

More from corehard_by(20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan... by corehard_by
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
corehard_by643 views
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про... by corehard_by
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
corehard_by492 views
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников by 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 ... - Евгений Охотников
corehard_by117 views
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов by corehard_by
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
corehard_by162 views
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген... by corehard_by
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
corehard_by84 views
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков by corehard_by
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
corehard_by235 views
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви... by corehard_by
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
corehard_by154 views
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С... by corehard_by
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
corehard_by91 views
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ... by corehard_by
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
corehard_by99 views
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ... by corehard_by
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
corehard_by64 views
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -... by 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 -...
corehard_by181 views
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов by corehard_by
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
corehard_by56 views
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić by 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ć
corehard_by95 views
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova by corehard_by
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
corehard_by35 views
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин by corehard_by
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
corehard_by52 views
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L... by 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...
corehard_by38 views
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019 by corehard_by
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
corehard_by54 views
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019 by corehard_by
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
corehard_by82 views
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019 by corehard_by
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
corehard_by54 views
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019 by corehard_by
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
corehard_by228 views

Обработка коллекций наизнанку: как применить много функций к одному аргументу. Вадим Винник. Corehard Spring 2019

  • 1. This slide intentionally left blank There is nothing to read here
  • 3. Мотивация ● Парадигма функционального программирования проникает в C++: ○ operator(), функциональные объекты; ○ оптимизация хвостовой рекурсии; ○ λ-функции; ○ std::function, std::bind; ○ std::transform, std::accumulate - аналоги fmap и foldl/foldr; ○ template metaprogramming - позволяет моделировать классы типов; ● Не просто пополнение новыми инструментами, а парадигмальный сдвиг! ● Понятия и методы ФП остаются малознакомыми широкому сообществу. ● Цель доклада - продемонстрировать логику программирования, тривиальную для ФП, но безумную с точки зрения традиций ООП. ● Показать, сколь проста её реализация на языке C++. 3
  • 4. Немного программологии: интенсиональность ● Сущности в программировании выступают в трёх ролях: ○ просто сущности; ○ средства построения сущностей; ○ средства применения средств построения (в частности, средства управления средствами построения). ● Эта не имманентная характеристика сущности, а внешняя. ● Определяется не сущностью самой по себе, а способом её использования в конкретном контексте. ● Сущности в программировании - интенсиональны. ● Пример - функция: ○ чаще всего выступает средством построения объектов данных; ○ но в может и сама выступать объектом построения. 4
  • 5. Немного программологии: композиционность ● Композиции строят более сложные программные сущности из относительно простых. ○ Чаще всего имеют в виду композиции программ, но не менее важны композиции данных, данных с программами и т.д. ● Обычно их относят к интенсиональному типу средств построения. ● Не менее важно рассматривать их и как средства применения и, в частности, управления применением: ○ циклическая композиция управляет выполнением оператора-тела, который выступает средством построения объектов данных; ○ объект, реализующий идиому RAII, управляет применением заданного действия. ● Композицию можно даже относить к интенсиональному типу 1 (гомоиконичность, LISP), но это далеко уводит от темы доклада. 5
  • 6. Немного программологии: композиционность ● Всякое ответвление программирования характеризуется своим набором композиций. ● Эти композиции: ○ выступают инструментами сочленения более сложных единиц из простых; ○ управляют применением частей в составе целого в процессе его работы. ● Именно композиции определяют суть и дух всякого программирования. ● Суть функционального программирования - не в чистоте функций и отказе от разрушающего присваивания. ● Напротив: чистота функций - средство для поддержки композиций ФП. 6
  • 7. Проникновение ФП в C++ ● Импорт композиций ФП в среду языка C++ и сложившейся вокруг него культуры программирования. ● Композиции, нашедшие широкое применение в ФП, для человека, привычного к ООП, могут выглядеть странно и пугающе. ● Композиции ФП часто основаны на λ-исчислении, комбинаторах и теории категорий (функторы, монады). ● Обобщённая цель доклада: показать, как выгод, которые в ФП достигаются с помощью монад, можно добиться штатными средствами языка С++, не упоминая монады в явном виде. 7
  • 8. Вместо тысячи слов fmap x1 x2 xn f y1 y2 yn fsum f1 f2 fn x y 8
  • 9. Пример ● Пусть дана совокупность функций каждая из которых может дать искомый результат или неудачу. ● Например: ○ Попытаться извлечь параметр hostname из файла настроек в текущей директории; ○ Попытаться извлечь hostname из настроек в домашней директории пользователя; ○ Попытаться извлечь hostname из глобального файла настроек; ○ Взять hostname по умолчанию, прошитый в программе. ● Каждая, кроме последней, может окончиться неудачей: отсутствует файл или в файле нет такого параметра. ● Чтобы получить правильный hostname, нужно пытаться применять эти функции в том же порядке одну за другой до первой удачи. 9
  • 10. ● Если T - тип, то вместо std::optional<T> будем писать T? (возможно, T). ● Специальный объект “отсутствие” (std::nullopt) обозначим ⊥ (дно). ● Рассматриваем функции типа A1,…, Am → T?. ● Функция ⟘ (пустая) - для любых кортежей x правильного типа ⟘(x) = ⊥. ● Всюду определённые функции: t(x) ≠ ⊥ для любых x (Tot). ● Отношение порядка: f ≼ g (“f есть подфункция g”), если для любых x из f(x) ≠ ⊥ следует g(x) = f(x). ● Функция ⟘ - наименьшая, а любая всюду определённая t - максимальная (но не наибольшая) относительно порядка ≼. ● Одноточечная функция: p[a, y](x) = y, если x = a; иначе p[a, y](x) = ⊥. ● Совместимость: f ≈ g, если из f(x) ≠ g(x) следует f(x) = ⊥ или g(x) = ⊥. Немного обозначений для краткости 10
  • 11. Сумма функций: определение ● Пусть дана совокупность функций f1,…, fn типа A1,…, Am → T?. ● Их сумма h = ∑[f1,…, fn] = f1 ⊕…⊕ fn есть функция того же типа. ● Если fk(x) = ⊥ для всех k ∊ {1, …, n}, то h(x) = ⊥. ● Иначе h(x) = fk(x), где k ∊ {1, …, n} - наименьшее такое число, что ○ fk(x) ≠ ⊥, ○ fi(x) = ⊥ для всех i ∊ {1, …, k-1}. ● Неформально говоря: сумма функций по очереди пробует применять все функции-слагаемые до первой удачи. ● Сумма функций терпит неудачу, если неудачу терпят все слагаемые. 11
  • 12. Свойства суммы функций ● Некоммутативность: (p[a, y] ⊕ p[a, z])(a) = y, но (p[a, z] ⊕ p[a, y])(a) = z. ● Коммутативность при условии: если f ≈ g, то f ⊕ g = g ⊕ f. ● Ассоциативность: (f ⊕ g) ⊕ h = f ⊕ (g ⊕ h). ● Левый нуль: ⟘ ⊕ f = f. ● Правый нуль: f ⊕ ⟘ = f. ● Идемпотентность: f ⊕ g ⊕ g = f ⊕ g ○ в программировании работает только для чистых функций. ● Неподвижность максимума слева: если t ∊ Tot, то t ⊕ f = t. ● Сохранение максимума справа: если t ∊ Tot, то (f ⊕ t) ∊ Tot. ● Монотонность: f ≼ f ⊕ g. ● Поглощение меньшего большим: если f ≼ g, то f ⊕ g = g. 12
  • 13. Рекуррентное определение суммы функций ● База (сумма из 0 слагаемых есть 0): ∑ [ ] = ⟘. ● Шаг: выразить сумму n слагаемого через сумму n-1 слагаемых (n > 0): h = ∑ [f1,…, fn] - это такая функция, что для любого x: ● Если f1(x) = y ≠ ⊥, то h(x) = y. ● В противном случае h(x) = g(x), где g = ∑ [f2,…, fn]. 13
  • 15. template <typename R, typename ...Args> struct default_constf { using value_t = R; static R make(Args...) { return {}; } }; template <typename R, typename ...Args> struct constf { using value_t = R; template <R Value> static constexpr R make(Args...) { return Value; } }; template <typename R, typename ...Args> class constf_t { R const value_; public: using value_t = R; explicit constf_t(R const& value) : value_(value) {} R operator()(Args const&...) const { return value_; } }; Вспомогательные функции-константы создаются на этапе выполнения создаются на этапе компиляции 15
  • 16. template <typename R, typename ...Args> class single_point_t { R const value_; std::tuple<Args...> const args_; public: using value_t = R; using maybe_t = std::optional<R>; single_point_t(R const& value, Args const&... args) : value_(value), args_(args...) {} maybe_t operator() (Args ...args) const { return args_ == std::make_tuple(args...) ? maybe_t {value_} : std::nullopt; } }; одноточечная функция p[a, y] 16
  • 17. template <typename R, typename ...Args> struct fsum { using maybe_t = std::optional<R>; using funcptr_t = maybe_t(*)(Args...); static funcptr_t make() { return &(default_constf<maybe_t, Args...>::make); } template <typename F, typename ...Fs> static auto make(F f, Fs ...fs) { return [f, fs...](Args ...args) -> maybe_t { maybe_t const r = f(args...); return r.has_value() ? r : make(fs...)(args...); }; } строит сумму функций на этапе компиляции прямая реализация рекуррентного определения 17
  • 18. // continued: // template <typename R, typename ...Args> // struct fsum { template <typename I> static maybe_t exec(I from, I to, Args ...args) { while (from != to) { maybe_t const r = (*from)(args...); if (r.has_value()) return r; ++from; } return std::nullopt; } }; вычисление значения суммы функций на этапе выполнения 18
  • 19. using sum_t = xfunctional::fsum<number_t, std::string>; auto string_to_number = sum_t::make( decimal_to_number, english_numeral_to_number, roman_to_number); assert(string_to_number("2019") == 2019); assert(string_to_number("twelve") == 12); assert(string_to_number("XIV") == 14); assert(string_to_number("sieben") == std::nullopt); пример использования 19
  • 20. using sum_t = xfunctional::fsum<int>; int count = 0; auto chain = sum_t::make( [&count]() { ++count; return std::nullopt; }, [&count]() { ++count; return std::nullopt; }, [&count]() { ++count; return std::nullopt; }, [&count]() { ++count; return 7; }, [&count]() { ++count; return std::nullopt; }, [&count]() { ++count; return 3; } ); auto const value = chain(); assert(value == 7); assert(count == 4); демонстрация хода вычислений 20
  • 21. using func_t = xfunctional::single_point_t<std::string, int>; using sum_t = xfunctional::fsum<std::string, int>; auto int_to_string = sum_t::make( func_t { "zero" , 0 }, func_t { "one" , 1 }, func_t { "two" , 2 }, func_t { "zero2", 0 }, // ! func_t { "three", 3 } ); assert(int_to_string(0) == "zero"); assert(int_to_string(2) == "two"); assert(int_to_string(3) == "three"); assert(int_to_string(4) == std::nullopt); окончание по первому успеху 21
  • 22. Итоги и дальнейшие вопросы ● Связь с шаблонами “Chain of Responsibility” и “Composite”. ● Этот код работает на production. ● Для ряда практических задач стиль ФП - наиболее адекватное средство выражения их естественной логики. ● Если функция f имеет побочные эффекты, то бесконечная сумма ∑ [f, f, …] представляет собой… что? ● Предел бесконечной монотонной последовательности и заодно неподвижная точка операции ⊕f - это цикл! ● А теперь вывернем наизнанку! Применять следующую функцию к результату предыдущей до первой неудачи. ● Получим монаду Maybe - но это уже совсем другая история. 22
  • 23. } // the talk