Какая польза от метапрограммирования?

Я читал:

, и я признаюсь, что путаюсь в цели, стоящей за метапрограммирование / генерация кода.

У кого-нибудь есть конкретный пример использования метапрограммирования / генерации кода? Еще лучше было бы сопроводительное объяснение того, почему это было лучше, чем альтернатива.

edit : Будет ли Thistle рассматриваться как метапрограммирование?

69
задан Wayne Werner 12 August 2010 в 20:04
поделиться

9 ответов

Представьте себе парня, который строит автомобили. Скажем, это то же самое, что и компьютер.
В какой-то момент он понимает, что всегда делает одно и то же, более или менее.
Он строит заводы по производству автомобилей, и это намного лучше. Он сейчас программирует!
Тем не менее, снова в какой-то момент он понимает, что в некоторой степени всегда делает одно и то же.
Теперь он решает строить фабрики, которые строят фабрики, производящие автомобили. Это метапрограммирование.

Метапрограммирование невероятно мощно, но один сбой в системе превращает все преимущества в чудовищные трудности. Так что освоите это и используйте ... Или держитесь подальше!

112
ответ дан 24 November 2019 в 13:45
поделиться

Мой недавний (последние 6 месяцев) конкретный пример генерации кода:

  1. У меня есть скрипт SQL Plus, который генерирует, а затем выполняет другие скрипты SQL Plus. Сценарий генерирует запросы к некоторым таблицам с полями с отметками времени, и когда я разрабатывал сценарий, было невозможно узнать, какое временное окно выбрать. Итак, основной скрипт выполняет свою работу и определяет, какие временные диапазоны должны быть во вспомогательных скриптах. Затем он генерирует индексы, записывая их код в файл (и подставляя заполнители для фактического времени начала и окончания). Наконец, он выполняет индекс (ы). Я использовал этот прием в нескольких ситуациях (хотя часто более сложных, чем этот), где структура подшагов зависит от результатов предыдущих шагов.

  2. Однажды я получил электронную таблицу, отображающую элементы из XSD в столбцы таблицы в базе данных. Можно было генерировать XSL-фрагменты и полные запросы из электронной таблицы с использованием макросов и VBA.Эти фрагменты и запросы были скопированы и вставлены (в основном как есть, без каких-либо изменений) в систему, которая их выполнила и обработала результаты. Неприятное решение, но оно определенно сделало очень утомительную работу намного менее утомительной, а код, который в результате был, вероятно, выглядел намного более последовательным, чем если бы я потратил неделю или две на то, чтобы все это писать вручную.

ИТОГО список примеров метапрограммирования: Какие самые крутые примеры метапрограммирования вы видели на C ++?

3
ответ дан 24 November 2019 в 13:45
поделиться

Конкретный пример того, где это может быть полезным подходом.

У вас есть набор сторонних классов, к которым вы хотите добавить общее поведение - например, какой-то вид управления безопасностью / доступом, отображение объектов как JSON и т. Д.

Вы можете написать или сгенерировать подклассы для всего, добавив методы оболочки для добавления в контроль доступа и вызова суперкласса. С помощью метапрограммирования вы можете делать это во время выполнения, а также ваши изменения будут автоматически применяться к любым дополнительным / измененным сторонним классам.

В примере JSON, используя интроспекцию класса, вы должны иметь возможность сгенерировать код для сериализации объекта, а затем добавить его как метод к классу. Другими крайностями будут генерация или написание кода заранее (перед компиляцией) и влияние каждый раз, когда класс изменяется, или полностью общий подход, который использует интроспекцию для каждого отдельного объекта, каждый раз, когда вы хотите его сопоставить.

В зависимости от рассматриваемого языка и среды выполнения, подход метапрогамминга, вероятно, будет быстрее, чем полностью общий / интроспективный, но медленнее, чем предварительный код, так как вы сократили количество операций поиска данных в коде.

Там, где метапрограммирование не существует непосредственно в языке, мне также кажется, что его часто заново изобретают с помощью фреймворков (т.е. контейнеров в стиле IoC, таких как Spring).

1
ответ дан 24 November 2019 в 13:45
поделиться

Я думаю о метапрогамминге как о «программах, которые пишут (или модифицируют) другие программы». (Другой ответ - «фабрики, которые производят фабрики», хорошая аналогия).

Люди находят для этого всевозможные применения: настройка приложений, создание шаблонного кода, оптимизация программы для особых обстоятельств, реализация DSL, вставка кода для обработки Проблемы ортогонального дизайна («аспекты») ...

Что примечательно, так это то, как много различных механизмов было изобретено, чтобы делать это по частям: текстовые шаблоны, макросы, условия препроцессора, дженерики, C ++ - шаблоны, аспекты, отражение, ... И обычно некоторые из этих механизмов встроены в некоторые языки, а другие механизмы на другие языки, и большинство языков вообще не имеют поддержки метапрограммирования. Такое случайное распределение возможностей означает, что вы могли бы виды метапрограммирования на одном языке с ограничениями, но при этом невозможность их выполнения на другом. Это отягощает: -}

Наблюдение, за которым я следил полностью, состоит в том, что можно построить общий машина метапрограммирования, которая работает с любым языком в форме программные преобразования . Преобразование программы - это параметризованный шаблон: «если вы видите этот синтаксис, замените его на тот синтаксис».

Одно преобразование само по себе обычно не впечатляет, но десятки или сотни могут сделать впечатляющие изменения в коде.Поскольку (сложные) программные преобразования могут эффект имитирует машину Тьюринга, они могут выполнять произвольные изменения кода, в том числе все эти точечные техники, которые вы находите разбросанными.

Инструмент, который принимает определения языков. специфичные для языка преобразования и порождает другой инструмент для применения этих преобразований - это мета -метапрограммирование: программа для написания «программ, пишущих программы».

Ценность в том, что вы можете применять такой инструмент для выполнения самых разных изменений. к произвольному коду. И вам не нужен комитет по языковому дизайну, чтобы понять, что вы хотите особого рода поддержку метапрограммирования и поторопитесь предоставить ее так что вы можете продолжить свою работу сегодня.

Интересный урок заключается в том, что такой механизм требует серьезного программного анализа (символ таблицы, контроль и анализ потока данных и т. д.) поддержка, чтобы помочь ему сосредоточиться на проблемах в коде, чтобы метапрограммирование машины могут что-то делать в этот момент (очень слабым примером этого являются точечные спецификации в аспектах, в которых говорится «вносить изменения в такие места»).

ОП попросил привести конкретные примеры применения метапрограммирования.Мы использовали наш «мета» -метапрограммирование ( DMS Software Reengineering Toolkit ) для автоматического выполнения следующих действий на больших базах кода:

  • Миграция языков
  • Реализация Покрытие тестов и профилировщики
  • Реализация обнаружения клонов
  • Массовый реинжиниринг архитектуры
  • Генерация кода для управления фабрикой
  • SOA-реализация встроенных сетевых контроллеров
  • Извлечение архитектуры для программного обеспечения мэйнфрейма
  • Генерация векторных инструкций SIMD из массива вычисления
  • Обратное проектирование кода до концепций

на многих языках, включая Java, C #, C ++, PHP, ...

ОП также спросил: «Почему это было лучше альтернативы?» Ответ связан с масштабом, временем и точностью.

Для больших приложений огромный размер базы кода означает, что у вас нет ресурсов. или время провести такой анализ или внести изменения вручную.

Для задач генерации кода или оптимизации вы можете сделать это вручную, но инструменты могут сделать это намного быстрее и точнее.

По сути, эти инструменты делают то, что люди просто не могут.

Стоит отметить, что инструменты не обладают творческим потенциалом; ты все еще нужно, чтобы люди определяли, что им делать, например, чтобы решать какова задача (см. список примеров выше) и определить как определить анализ / преобразования для достижения эффекта. Вам все еще нужны мета -программисты. Однако когда мета-программист вооружает такой инструмент правильными знаниями, полученный код может кажутся созданными невероятно быстрым, креативным и опытным программистом.

20
ответ дан 24 November 2019 в 13:45
поделиться

Я могу привести свой собственный конкретный пример: Я разрабатываю ABSE , который представляет собой подход метапрограммирования. С помощью ABSE вы создаете модель (фактически, дерево), где каждый элемент является «атомом». Этот атом представляет собой «концепцию» и содержит необходимые метаданные для ее определения.

В ABSE реализация концепции фактически является «мини-программой».

Затем ведущий разработчик моделей ( AtomWeaver , разработанный вместе с ABSE) берет модель и «сплетает» программу-генератор из всех ее атомов. Затем эта программа запускается, генерируя желаемые артефакты (исходный код, данные и т. Д.).

Итак, рабочий процесс ABSE:

  1. Создание дискретной концепции (часть мета-метапрограммы)
  2. Повторное использование этой концепции в модели (эффективное построение метапрограммы).
  3. Разработчик модели хоста переплетает и запускает метапрограмма
  4. Метапрограмма генерирует вашу окончательную программу

На первый взгляд это выглядит как много повторяющейся и сложной работы, но на самом деле это довольно просто, если вы понимаете концепцию.

Преимущества метапрограммирования (не только для ABSE)?:

  • Изменение модели и восстановление полной системы (представьте себе функции рефакторинга вместо исходных текстов).
  • Изменение нескольких определений в модели может привести к созданию отдельных программ (Семейство программных продуктов).
  • Повторно используя шаблоны, вы можете изменить код шаблона, восстановить и изменить свой код в десятках, сотнях мест.
  • Многие другие, на самом деле

Метапрограммирование, генерация кода, преобразование программ - это новые захватывающие миры в разработке программного обеспечения, ИМХО. Однако метапрограммирование требует нового навыка: метамышления.

Мы можем определить метамышление как «размышление о том, как вы думаете о своем собственном развитии». Этакое классовое размышление над собой. На практике вы должны найти свои собственные шаблоны разработки, изолировать их, сделать их общими, а затем превратить их в метапрограммы, используя свой любимый прием, будь то ABSE, DSL, DSM и т. Д.

3
ответ дан 24 November 2019 в 13:45
поделиться

Библиотеки/код на основе метапрограммирования помогают писать непосредственно явный и простой код, который будет генерировать для вас код деталей реализации, в зависимости от используемых параметров.

Boost полон (C++) библиотек, которые демонстрируют, чего можно достичь с помощью метапрограммирования. Некоторые хорошие (и, возможно, трудные для понимания) примеры - Proto, позволяющая реализовать DSL, Spirit, позволяющая написать компилятор, используя EBNF грамматику прямо в коде, и многие другие библиотеки для метапрограммирования.

2
ответ дан 24 November 2019 в 13:45
поделиться

Вы можете посмотреть макросы Common Lisp или шаблоны C ++ и увидеть, как они используются. Оба являются метапрограммированием в том смысле, который вы используете. Вы обнаружите, что оба они активно используются в большом количестве кода.

Макросы Lisp часто используются для переопределения языка. В качестве примера, последняя глава книги Пола Грэма On Lisp создает рабочее объектно-ориентированное расширение для Common Lisp. Другой пример - ныне несуществующий Гранат .

Старая стандартная библиотека шаблонов для C ++ (в основном включенная в стандартную библиотеку) была способом введения большого количества контейнеров и алгоритмов, которые работали так, как если бы они были встроены в язык, по крайней мере, с точки зрения интеграции и эффективности ( не синтаксически).

0
ответ дан 24 November 2019 в 13:45
поделиться

Я больше всего использовал метапрограммирование для наведения мостов между различными API.

Рабочим примером может служить FireBreaths JSAPIAuto 1 , который упрощает написание классов C ++, доступных для JavaScript. Предоставляя средство регистрации для функций, которые должны быть представлены, типы аргументов могут быть проверены и из этого подходящего кода, сгенерированного во время компиляции, который преобразует из типов скриптов API в собственные типы C ++ и обратно, даже напрямую поддерживая карта , вектор и т. Д.

В качестве простого примера рассмотрим открытую функцию add (a, b) , которая использует некоторые типы API сценариев:

ScriptVariant add(const std::vector<ScriptVariant>& values) {
    // have to check argument count
    if(values.size() != 2)
        throw script_error("wrong number of arguments");

    try {
        // have to convert from scripting-API types
        long a = values[0].convert_cast<long>();
        long b = values[0].convert_cast<long>();
        return a+b; // potentially need to convert back too
    } catch(ScriptVariant::bad_cast& e) {
        // need to handle conversion failure
        throw script_error("conversion failed :(");
    }
}

Фактическая логика, скрытая там, состоит только из одной строчки, проверки и преобразования раздражают и излишни.С ранее упомянутым средством регистрации (например, в конструкторе):

registerMethod("add", make_method(this, &MyClass::add));

теперь это можно просто записать как:

long add(long a, long b) {
    return a+b;
}

... и фреймворк позаботится о генерации необходимого кода за вас.

1: Хотя я бы сделал реализацию немного ... чище ... если бы мне пришлось начать заново

5
ответ дан 24 November 2019 в 13:45
поделиться

Запустите Visual Studio (Eclipse, Netbeans и т. Д.). Создайте новый проект. Сюрприз - вы только что использовали метапрограммирование, создав проект из шаблона. Разве это не практично?

1
ответ дан 24 November 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: