2. Что такое метапрограммирование?
• Шаблоны и макросы, используемые при
компиляции
• Программа, которая изменяет саму
себя
• Программа, генерирующая другую
программу
• еще варианты ?
3. Что такое метапрограммирование?
1. Это ни каким боком не искусственный интеллект.
2. Метапрограммирование это не что-то новое, вы всегда
его использовали. Нельзя начать, но можно осознать и
применять метапрограммирование осознанно.
3. Без метаданных вообще ничего не происходит в языках
программирования для фоннеймановской архитектуры
(т.е. для архитектуры, в которой данные и инструкции
хранятся в одной памяти, и нужно различать где число,
где строка, где длина строки, где адрес, где инструкция).
5. Что такое метапрограммирование?
«Вот что я имею в виду под производящим произведением или,
как я называл его в прошлый раз, «opera operans».
В философии существует различение между «natura naturata» и
«natura naturans» – порожденная природа и порождающая
природа. По аналогии можно было бы образовать – «cultura
culturata» и «cultura culturans». Скажем, роман «В поисках
утраченного времени» строится не как произведение, а как
«cultura culturans» или «opera operans». Это и есть то, что у
греков называлось Логосом.»
// Мераб Мамардашвили «Лекции по античной философии»
6. Как работает метапрограммирование?
Парадигма программирования,
построенная на программном изменении
структуры и поведения программ
1. Когда происходят изменения?
2. Что именно изменяется?
3. При помощи чего происходят изменения?
7. Как работает метапрограммирование?
Когда происходят изменения?
• во время разработки (Design time)
• во время компиляции (Compile time)
• во время работы приложения (Run time)
• во время выполнения задачи (Just-in-Time)
• между задачами (Lazy)
• по времени (Timer)
• по внешнему вызову (Pull)
• по событию (Push)
8. Как работает метапрограммирование?
Что именно изменяется?
• типы данных и структуры данных
• идентификаторы (имена классов, типов, переменных)
• вызовы (имена методов, динамическое связывание)
• параметры алгоритмов
• подстановка формул, регулярных выражений и т.д.
• динамически интерпретируется сам код
• сериализация/десериализация данных
9. Как работает метапрограммирование?
При помощи чего происходят изменения?
• Парсинг и трансляция синтаксических структур
• Доступ к идентификаторам по имени
• Полная интроспекция
• Индивидуация объектов первого класса:
• функций, через замыкания
• объектов, через динамическое создание и примеси
10. Постановка задачи
Для чего нам нужно метапрограммирование?
• Расширение функциональности,
повышение универсальности ПО
• Динамические предметные области,
когда изменения являются штатным режимом
• Упрощение межсистемной интеграции,
это отдельная тема, но очень помогает
11. Пример 1: данные
var names = [
"Marcus Aurelius Antoninus Augustus",
"Darth Vader",
"Victor Michailovich Glushkov",
"Gottfried Wilhelm von Leibniz",
"Mao Zedong",
"Vladimir Sergeevich Soloviov",
"Ibn Arabi",
"Lev Nikolayevich Tolstoy",
"Muammar Muhammad Abu Minyar al-Gaddafi",
"Rene Descartes",
"Fyodor Mikhailovich Dostoyevsky",
"Benedito de Espinosa"
];
17. Пример 2: метамодель
function iterate(tasks) {
function closureTask(task) { return function () {
console.dir(task);
var source;
if (task.get) source = request.get(task.get);
if (task.load) source = fs.createReadStream(task.load);
if (task.save) source.pipe(fs.createWriteStream(task.save));
if (task.post) source.pipe(request.post(task.post));
if (task.put) source.pipe(request.put(task.put));
} };
for (var i=0; i<tasks.length; i++)
setInterval(closureTask(tasks[i]), duration(tasks[i].interval));
}
18. Пример 2: метамодель (конфигурируемая метаданными)
function iterate(tasks) {
var sources = { get: request.get,
load: fs.createReadStream };
var destinations = { save: fs.createWriteStream,
post: request.post,
put: request.put };
function closureTask(task) { return function () {
console.dir(task);
var verb, source, destination;
for (key in sources)
if (task[key]) source = sources[key](task[key]);
for (key in destinations)
if (task[key]) source.pipe(destinations[key](task[key]));
} };
for (var i=0; i<tasks.length; i++)
setInterval(closureTask(tasks[i]), duration(tasks[i].interval));
}
19. Пример 3: интерпретация
// Parse duration to seconds, example: duration("1d 10h 7m 13s")
function duration(s) {
var result = 0;
if (typeof(s) == 'string') {
var days = s.match(/(d+)s*d/),
hours = s.match(/(d+)s*h/),
minutes = s.match(/(d+)s*m/),
seconds = s.match(/(d+)s*s/);
if (days) result += parseInt(days[1])*86400;
if (hours) result += parseInt(hours[1])*3600;
if (minutes) result += parseInt(minutes[1])*60;
if (seconds) result += parseInt(seconds[1]);
result = result*1000;
} if (typeof(s) == 'number') result = s;
return result;
}
20. Пример 3: интерпретация (конфигурируемая метаданными)
function duration(s) {
if (typeof(s) == 'number') return s;
var units = {
days: { rx:/(d+)s*d/, mul:86400 },
hours: { rx:/(d+)s*h/, mul:3600 },
minutes: { rx:/(d+)s*m/, mul:60 },
seconds: { rx:/(d+)s*s/, mul:1 }
};
var result = 0, unit, match;
if (typeof(s) == 'string') for (var key in units) {
unit = units[key];
match = s.match(unit.rx);
if (match) result += parseInt(match[1])*unit.mul;
}
return result*1000;
}
25. Приемы метапрограммирования
• Стиль описания задачи: декларативный (метаданные),
использование императивных и функциональных вставок
• Хеши (ассоциативные массивы)
заранее не знаем ключ: var a = {}; a[key] = value;
• Интерпретация строк, придумываем свои синтаксисы или
берем общепринятые (json, js, regexp ...)
• Примеси (mixins): заранее не знаем куда добавим
function mixin(a) { a.fn=function(){ ... } }
• Замыкания (closures): персонализируем функции
fn = (function(a) { return function() { return a*2 } })(value)
26. Последствия метапрограммирования
• Размер кода: чаще резко уменьшается,
но иногда может немного увеличиваться
• Быстродействие: незначительно снижаться, но при
грамотной реализации остается примерно тем же
• Гибкость: программный код становится более
универсальным, сфера применения ПО расширяется
• Интеграция: обычно значительно упрощается и требует
меньше изменений кода
• Удовольствие от работы: метапрограммировать интереснее
поэтому удовольствия и мотивации больше
• Скорость разработки: разрабатывать дольше, а поддерживать
значительно проще, экономится уйма времени