Практика мультипарадигмального программирования, 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++, говорили, что писать на этом не будут.

Но всего хаскеля не передать, ибо в хаскеле есть ещё что-то: замыкание, монады. Как-то пытаются монады эмулировать, но это не то.

Монада — это какое-то хитрое преобразование из функции в функцию, причём без изменения профиля. Это вещь, которая работает с бесконечными списками, преобразует их. Зачем это нужно — в хаскеле в их виде оформлен ввод-вывод.

Чтобы понять монады, надо написать что-то мерьёзное. И тут начинаются проблемы. Мануал по хаскелю разделён на две части. Одна понятная, другая имеет заход из математики, но непонятно, как из этого что-то делать.


Практика мультипарадигмального программирования


01 02 03 04 05 06 07 08


Календарь

пн пн пн пн пн
Февраль
12 19
Март
12 19 26
Апрель
02 09 16


Эта статья является конспектом лекции.

Эта статья ещё не вычитана. Пожалуйста, вычитайте её и исправьте ошибки, если они есть.
Личные инструменты
Разделы