Практика мультипарадигмального программирования, 06 лекция (от 02 апреля)
Материал из eSyr's wiki.
Предыдущая лекция | Следующая лекция
[править] Библиотечное моделирование отдельных возможностей
Вот чего-то не хватает в языке, пишем мы на каком-то языке программирования. Если всего хватает, то о многостилевом программировании и речи и идёт, и мы других языков не знаем или не используем. Мультипарадигмальность возникает, когда хочется чего-то ещё, а в языке этого нет. Например, регулярные выражения. Вот в тикле они есть, а в Си нет. Можем мы сделать их в Си? Да, есть не одна библиотека для этого. Являются ли нерег выражения парадигмой? Есть минимум два источникам, в которых они так обозначаются. Влияют ли они на мышление? Да.
Вот берём мы функцию с pattern и regexp. Если мы дерём библиотеку с этой функцией, значит ли это, что у нас в языке появились регвыр? Да, но не в языке, а в системе программирования. Мы внесли парадигму за счёт библиотечного расширения. Но регекспы штука узкая.
Есть С++. Там есть темплейты и прочая. Есть ибиблиотеки, которые вносят новые парадигмы в С++. Во-первых, функция как объект. Во-вторых, лямбда-исчисление.
Но основная проблема в том, что невозможно сделать замыкание, ибо С++ не может работать с именами переменных.
Функтоид — класс, для которого перекрыт (). То есть это класс, который не функция, но объект этоо класса может выступать как функция. Можно сделать композицию (f ∘ g).
Какие есть библиотеки:
- boost::lambda — законченная документация, непонятная
- FAC++T! — непонятная документация
- FC++ — наиболее известное из них, и по ней есть законченная документация
Кроме того, первые две завязаны на STL, он торчит изо всех щелей, последняя же использует STL, но может и без него.
[править] FC++
FC++ явно создавали люди, которые очень любят haskell. Ибо есть хедер, который содержит инклюд всех хедеров, и он называется prelude (так называется стандартная библиотека haskell)
#include "prelude.h"
Но хаскелисты говорят, что это какой-то неправильный хаскель, хотя там многое от хаскеля реализовано.
Чем знаменит haskell:
- Чисто функциональный
- Язык со строгой типизацией
- Карринг
FC++ более-менее соостветствует идеологии хаскеля. Ещё один важный момент — хаскель язык ленивый, что позволяет работать с бесконечными списками. И если в FC++ использовать их структуры данных, то декларируется, что они ленивые, и что они тоже могут быть бесконечными
[править] Примеры
List<int> lr = cons(x, cons(y, cons(t, NIL)));
Получается список, в качестве метки конца списка используется NIL. получается список из ццелых чисел. В хаскеле мы написали что-то вроде такого:
x::y::z::nil
Естественно, cons — темпелйт, и можно записать так:
cons<int>(x ...)
Вместо инта может быть любой тип, для которого определена операция сравнения (и, наверное, копирования)
Что можно сделать с этим списком:
- head
- tail
(аналоги car и cdr в лиспе)
Коль скоро есть функция, можно создать ещё одну функцию:
List<int> res = compose(tail, tail)(li);
Создаём новую функцию как суперпозицию двух функций tail и tail. Но tail ни разу не функция, а темплейт, и compose это макрос. В результат получаем выражение, и к нему применяем операцию вызову функции. Причём применяем их к функтоиду.
Можно работать с бесконечными структурами данных: вот есть же опять свтроенная функция: enumFrom(1); — функция, которая строит бесконечный список целых чисел, начиная с указанного. Что такое бесконечная структура — некоторые данные, а потом указания, как строить дальше. Результатом enumFrom является выражение, которое вполне можно присваивать:
List<int> i = enumFrom(1);
Что можно сделать: например, можно сделать
List<int> evens = filter(even, i);
Функция even — булева, проверяет на чётность. Это обыкновенная функция на С++:
bool even(int x) { return x%2 == 0; }
А filter это уже темплейт, который умеет фильтровать:
filter<T> (bool(*)(T), T) {...}
Получаем список из всех существующих чётных чисел. Конечно, все не хранятся. Хранится первая и указания, как вычислить. Есть функция take (как в хаскеле) — взять n первых элементов.
List<int> e3 = take(3, evens); //взять первые три элемента списка
Тогда они и будут вычислены.
Есть функция map:
map(function, list)
Хаскель:
map: (a → b) → [a] → [b]
Люди пытались сделать то, что они хотели иметь из хаскеля.
Люди продемонстрировали факт: для темплейтов есть более интересные применения, чем для построения контейнерных классов.
Ложка дёгтя: сколько есть знакомых хаскелистов, все говорили при виде FC++, говорили, что писать на этом не будут.
Но всего хаскеля не передать, ибо в хаскеле есть ещё что-то: замыкание, монады. Как-то пытаются монады эмулировать, но это не то.
Монада — это какое-то хитрое преобразование из функции в функцию, причём без изменения профиля. Это вещь, которая работает с бесконечными списками, преобразует их. Зачем это нужно — в хаскеле в их виде оформлен ввод-вывод.
Чтобы понять монады, надо написать что-то мерьёзное. И тут начинаются проблемы. Мануал по хаскелю разделён на две части. Одна понятная, другая имеет заход из математики, но непонятно, как из этого что-то делать.
Монада лучше всего представляется конвейером по которому движется деталь и к ней прямо на конвейере применяются операции (функции) в строгом порядке. Имеется возможность положить объект в монаду - return (положить деталь на конвейер) и передать следующую функцию - операторы >>= и >> (поставить рабочего к конвейеру). Порядок применения функций гарантируется.
Практика мультипарадигмального программирования
Календарь
пн | пн | пн | пн | пн | |
Февраль
| 12 | 19 | |||
Март
| 12 | 19 | 26 | ||
Апрель
| 02 | 09 | 16 |