Общее программирование против метапрограммирования - PullRequest
17 голосов
/ 15 октября 2010

В чем именно разница?Кажется, что термины можно использовать взаимозаменяемо, но, читая запись в википедии для Objective-c, я натолкнулся на:

В дополнение к процессуальному программированию в стиле C, C ++ напрямую поддерживает определенные формы объектов.-ориентированное программирование, общее программирование и метапрограммирование.

по отношению к C ++.Значит, они разные?

Ответы [ 6 ]

38 голосов
/ 15 октября 2010
  • Программирование : Написание программы, которая создает, преобразовывает, фильтрует, агрегирует и иным образом манипулирует данными.
  • Метапрограммирование : Написание программы, которая создает, преобразовывает, фильтрует, агрегирует и иным образом манипулирует программами .
  • Общее программирование : Написание программы, которая создает, преобразовывает, фильтрует, агрегирует и иным образом манипулирует данными, но делает только минимальные предположения о структуре данных, таким образом максимизируя повторное использование в широком диапазоне типов данных. .

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

Также обратите внимание, что, как знает каждый программист на Лиспе, код и данные - это одно и то же, поэтому на самом деле не существует такой вещи, как «метапрограммирование», это все просто программирование. Опять же, это немного трудно увидеть в C ++, так как вы фактически используете два совершенно разных языка программирования для программирования (C ++, императивный, процедурный, объектно-ориентированный язык в семействе C) и метапрограммирование (Templates, чисто функциональный «случайный»). "язык где-то посередине между чистым лямбда-исчислением и Хаскеллом, с непривлекательным синтаксисом, поскольку на самом деле он никогда не был предназначен для быть языком программирования.)

Многие другие языки используют один и тот же язык для программирования и метапрограммирования (например, Lisp, Template Haskell, Converge, Smalltalk, Newspeak, Ruby, Ioke, Seph).

13 голосов
/ 15 октября 2010

Метапрограммирование, в широком смысле, означает написание программ, которые дают другие программы. Например. Подобные шаблоны в C ++ производят реальный код только при его создании. Можно интерпретировать шаблон как программу, которая принимает тип в качестве входных данных и создает фактическую функцию / класс в качестве выходных данных. Препроцессор - это еще один вид метапрограммирования. Еще один надуманный пример метапрограммирования: программа, которая читает XML и создает некоторые сценарии SQL в соответствии с XML. Опять же, в общем, метапрограмма - это программа, которая выдает другую программу, тогда как общее программирование относится к параметризованным (обычно с другими типами) типам (включая функции).

отредактировано после рассмотрения комментариев к этому ответу

9 голосов
/ 15 октября 2010

Я бы грубо определил метапрограммирование как «написание программ для написания программ», а общее программирование - как «использование функций языка для написания функций, классов и т. Д., Параметризованных для типов данных аргументов или членов».

ByВ этом стандарте шаблоны C ++ полезны как для общего программирования (например, vector, list, sort ...), так и для метапрограммирования (например, Boost и, например, Spirit).Кроме того, я бы сказал, что общее программирование на C ++ (т. Е. Полиморфизм во время компиляции) осуществляется с помощью метапрограммирования (т. Е. Генерация кода из шаблонного кода).

5 голосов
/ 15 октября 2010

Общее программирование обычно относится к функциям, которые могут работать со многими типами. Например. функция сортировки, которая может сортировать коллекцию сопоставимых объектов вместо одной функции сортировки для сортировки массива целых чисел и другую для сортировки вектора строк.

Метапрограммирование означает программную проверку, изменение или создание классов, модулей или функций.

4 голосов
/ 15 октября 2010

Лучше всего взглянуть на другие языки, потому что в C ++ одна функция поддерживает как общее программирование, так и метапрограммирование. (Шаблоны очень мощные).

В Scheme / Lisp вы можете изменить грамматику вашего кода. Люди, вероятно, знают Scheme как «этот префиксный язык с множеством скобок», но он также имеет очень мощные методы метапрограммирования (Hygenic Macros). В частности, try / catch может быть созданным , и даже грамматикой можно манипулировать до некоторой точки (например, вот префиксный преобразователь в инфикс, если вы больше не хотите писать префиксный код: http://github.com/marcomaggi/nausicaa). Это достигается посредством метапрограммирования, кода, который пишет код, который пишет код. Это полезно для экспериментов с новыми парадигмами программирования (оператор AMB играет важную роль в недетерминированном программировании. Я надеюсь, что AMB станет основным следующие 5 лет или около того ...)

В Java / C # вы можете иметь общее программирование с помощью обобщений. Вы можете написать один общий класс, который поддерживает типы многих других классов. Например, в Java вы можете использовать Vector для создания вектора целых чисел. Или Vector, если вы хотите, чтобы это было специфично для вашего собственного класса.

Если что-то становится странным, это шаблоны C ++, предназначенные для общего программирования. Тем не менее, из-за нескольких хитростей, сами шаблоны C ++ являются завершающими. Используя эти приемы, можно добавлять новые функции в язык C ++ с помощью метапрограммирования. Его запутанный, но это работает. Вот пример, который добавляет множественную диспетчеризацию в C ++ через шаблоны. http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html. Более типичным примером является Фибоначчи во время компиляции: http://blog.emptycrate.com/node/271

0 голосов
/ 28 сентября 2017

Общее программирование - очень простая форма метакодирования, хотя обычно она не выполняется. Это больше похоже на препроцессор в C и больше относится к шаблонному программированию в большинстве случаев использования и базовых реализациях.

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

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

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

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

Как возникли обобщения, что не все можно сделать переменными, такими как ожидаемый тип переменной или тип приведения. Часто было много дублирования файлов, когда единственное, что было переменной, - это типы переменных. Это был очень распространенный источник дублирования. Хотя есть способы обойти это или смягчить его, они не особенно удобны. Дженерики стали своего рода переменными, чтобы сделать переменную типа переменной. Поскольку тип переменной обычно выражается на языке программирования, который теперь можно указывать во время выполнения, он также считается метакодированием, хотя и очень простым случаем.

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

Как вы можете себе представить, это довольно дорого. Это было бы очень распространено при использовании любого вида библиотеки хранения объектов повторного использования. Они будут принимать любой объект, но в большинстве случаев люди хотят использовать только один тип объекта. Если вы поместите объект Shop, который расширяет Object, а затем захотите получить его, сигнатура метода в объекте хранилища вернет просто Object, но ваш код будет ожидать объект Shop. Это нарушит компиляцию с понижением класса объекта, если вы не вернете его обратно в магазин. Это поднимает еще одну загадку, так как без обобщений невозможно проверить совместимость и убедиться, что сохраняемый вами объект является классом Shop.

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

Языки программирования, которые предлагают средства метакодирования лаважа, могут быть значительно более продуктивными, чем языки, чем избегать их, исключая особые случаи, рефлексию, полиморфизм ООП и т. Д. Однако для создания непонятных, понятных и поддерживаемых часто требуется гораздо больше навыков и опыта код без ошибок. Для таких языков также часто наблюдается снижение производительности, поскольку C ++ является чем-то странным, потому что он компилируется в native.

...