Що саме є метапрограмуванням?


128

Я читав статтю про TheServerSide про програмування ployglot на платформі Java . Деякі коментарі до статті називають метапрограмування здатністю генерувати код (можливо, на льоту).

Це метапрограмування здатності генерувати код на льоту або це здатність вводити методи та атрибути в існуючі об’єкти під час виконання (наприклад, що дозволяють деякі динамічні мови, такі як Python, Ruby та Groovy).


7
Ви могли б бути зацікавлені в цьому відповідь stackoverflow.com/questions/2565572 / ...
ewernli

@ewernli: Ця відповідь насправді краща за будь-яку з відповідей тут!
JD

Відповіді:


100

Метапрограмування стосується різноманітних способів, якими програма володіє знаннями про себе або може маніпулювати собою.

У таких мовах, як C #, відображення є формою метапрограмування, оскільки програма може вивчати інформацію про себе. Наприклад, повернення списку всіх властивостей об'єкта.

Такими мовами, як ActionScript, ви можете оцінювати функції під час виконання для створення нових програм, таких як eval ("x" + i). DoSomething () вплине на об'єкт, який називається x1, коли i дорівнює 1, а x2, коли я дорівнює 2.

Нарешті, ще одна поширена форма метапрограмування - це коли програма може змінити себе нетривіально. LISP добре відомий цим, і це те, що Пол Грехем виступав десь десять років тому. Мені доведеться переглянути деякі його конкретні нариси. Але ідея полягає в тому, що програма змінила б іншу частину програми на основі свого стану. Це дозволяє забезпечити рівень гнучкості для прийняття рішень під час виконання, що в більшості популярних мов сьогодні дуже важко.

Варто також зазначити, що ще в добрі дні програмування в прямому зібранні програми, які змінювали себе під час виконання, були необхідними і дуже звичними.

З есе Пола Грема "Що зробило Ліппа різним" :

У багатьох мовах є щось, що називається макросом. Але макроси Lisp унікальні. І вірите чи ні, те, що вони роблять, пов’язане з дужками. Дизайнери Lisp не поставили всі ці дужки в мові, щоб вони були різними. Для програміста Blub код Lisp виглядає дивно. Але ці дужки існують не просто так. Вони є зовнішнім свідченням принципової різниці між Lisp та іншими мовами.

Код Lisp складається з об'єктів даних Lisp. І не в тривіальному сенсі, що вихідні файли містять символи, а рядки є одним із типів даних, підтримуваних мовою. Після прочитання парсером код Lisp складається з структур даних, які можна пройти.

Якщо ви розумієте, як працюють компілятори, те, що відбувається насправді, полягає не стільки в тому, що у Lisp є дивний синтаксис, скільки в Lisp, який не має синтаксису. Ви записуєте програми на дерева розбору, які генеруються в компіляторі під час розбору інших мов. Але ці дерева розбору повністю доступні для ваших програм. Ви можете писати програми, які ними маніпулюють. У Ліспі ці програми називають макросами. Це програми, які пишуть програми.

Програми, які пишуть програми? Коли ти коли-небудь захотів би це зробити? Не дуже часто, якщо думати в Коболі. Весь час, якщо думати в Ліспі. Тут було б зручно, якби я міг навести приклад потужного макросу і сказати там! як щодо цього? Але якби я це зробив, це було б просто схоже на хитрість до того, хто не знав Ліспа; тут немає місця, щоб пояснити все, що потрібно знати, щоб зрозуміти, що це означає. В Ansi Common Lisp я намагався рухати речі так швидко, як тільки міг, і навіть так не потрапив до макросів до сторінки 160.

Але я думаю, що можу навести певний аргумент, який може бути переконливим. Вихідний код редактора Viaweb, ймовірно, мав приблизно 20-25% макросів. Макроси писати складніше, ніж звичайні функції Lisp, і вважати, що це поганий стиль використовувати їх, коли вони не потрібні. Отже, кожен макрос у цьому коді є, тому що він повинен бути. Це означає, що щонайменше 20-25% коду в цій програмі роблять речі, які ви не можете легко зробити жодною іншою мовою. Як би скептично налаштований програміст Блуб щодо моїх претензій на таємничі сили Ліспа, це повинно викликати у нього цікавість. Ми не писали цей код для власної розваги. Ми були крихітними стартапами, програмуючи настільки важко, як могли, щоб поставити технічні бар'єри між нами та нашими конкурентами.

Підозріла людина може почати замислюватися, чи є тут якась кореляція. Великий фрагмент нашого коду робив речі, які дуже важко зробити іншими мовами. Отримане програмне забезпечення робило те, що програмне забезпечення наших конкурентів не могло зробити. Можливо, був якийсь зв’язок. Я закликаю вас слідувати цій темі. Можливо, до цього старого чоловіка більше, ніж на очах, хапається, ніж на очах.


6
Не забувайте про метапрограмування шаблонів на C ++. Можливість виконувати вирази та приймати рішення під час компіляції, а також результати статично збиратись у остаточний виконуваний файл.
Ремі Лебо

1
Я був шокований, in order to put technical barriers between us and our competitorsі це таммаде правильно.
Еван Ху

4
Програми, що маніпулюють собою, є підмножиною всіх метапрограм. Метапрограмування взагалі просто означає програми, що маніпулюють програмами.
JD

55

Чудове запитання. Мені дуже шкода, що жодна з відповідей на даний момент дійсно не відповідає правильно на ваше запитання. Можливо, я можу допомогти ...

Визначення метапрограмування насправді досить просте: воно означає програми, що маніпулюють програмами.

Ваша прийнята відповідь говорить про програми, які маніпулюють собою. Це дійсно метапрограми, але вони є підмножиною всіх метапрограм.

Усі:

  • Парсери
  • Мови, що стосуються домену (DSL)
  • Мови вбудованого домену (EDSL)
  • Компілятори
  • Перекладачі
  • Термінові переписувачі
  • Теорема підтверджує

є метапрограми. Отже компілятор GCC - це метапрограма, інтерпретатор CPython - це метапрограма, комп'ютерна алгебра системи Mathematica - метапрограма, доказ теореми Coq - метапрограма тощо.

Інші відповіді стверджують, що метапрограми - це програми, що генерують інші програми. Це дійсно метапрограми, але, знову ж таки, вони є підмножиною всіх метапрограм. Швидке перетворення Фур'є на Заході (FFTW) бібліотека є прикладом такої метапрограми. Вихідний код написаний здебільшого в OCaml, і він генерує біти коду С (звані коделі), які поєднуються для створення високопродуктивних процедур швидкої трансформації Фур'є , оптимізованих для конкретних машин. Ця бібліотека фактично використовується для надання програм FFT в Matlab. Люди писали програми для створення чисельних методів протягом десятиліть, починаючи з перших днів роботи FORTRAN .

Першою мовою програмування, яка інтегрувала підтримку метапрограмування, була мова LISt Processor (LISP) наприкінці 1950-х. LISP 1.5 включав ряд функцій, які полегшували метапрограмування. По-перше, основним типом даних LISP є вкладені списки, тобто дерева, як (a (b c) d), що означає, що будь-який код LISP може бути вираженим як структура даних. Це відомо як гомоконічність. По-друге, код LISP можна легко перетворити в дані, використовуючи QUOTE. Наприклад, (+ 1 2 3)додає 1 + 2 + 3 і (QUOTE (+ 1 2 3))створює вираз, який додає 1 + 2 + 3 при оцінці. По-третє, LISP надав мета-круговий оцінювач, що дозволяє використовувати хост-інтерпретатор або компілятор для оцінки коду LISP під час виконання, включаючи LISP-код, створений під час виконання. Нащадками LISP є схема і Clojure. У всіх цих мовах метапрограмування найчастіше спостерігається у вигляді програм, що змінюють себе, як правило, використовуючи макроси.

У 1970-х роках Робін Мілнер розробив MetaLanguage (ML), який перетворився на сімейство програмних мов ML, що включає стандартний ML та OCaml і сильно вплинув на Haskell і F # . Ці мови дозволяють легко виражати інші мови. У цих мовах метапрограми найчастіше спостерігаються у вигляді лексерів, аналізаторів, інтерпретаторів та компіляторів.

У 1994 році Ервін Унрух виявив, що система шаблонів C ++ була Тюрінг завершеною і може використовуватися для виконання довільних програм під час компіляції . Метапрограмування шаблонів C ++ принесло метапрограмування немитим масам, які (ab) використовували його для багатьох речей, включаючи створення чисельних методів у бібліотеці Blitz ++ .


33

Ну, метапрограмування - це просто програмування, але в основному це "написання коду, який пише код" .

Здатність, яку ви згадуєте, коли програма може спостерігати та змінювати власну структуру та поведінку, називається відображенням і це тип метапрограмування.

Мови, що динамічно набираються, мають потужні функції відображення часу виконання, що стало можливим завдяки інтерпретованій природі цих мов ...

Статичні мови набору також мають потужні методи метапрограмування, наприклад метапрограмування шаблонів C ++ ...


14

Це лише моя особиста думка, яка, мабуть, є найбільш ліберальним визначенням метапрограмування.

Я думаю, що це включає:

  1. Скомпілювати генерацію коду або генерацію коду виконання (або обидва)
  2. Аспектно-орієнтоване мислення або орієнтоване на аспекти програмування
  3. СУХИЙ Мислення

Я думаю, що ви можете потрапити туди, скориставшись будь-яким із цих варіантів та у поєднанні:

  1. Рефлексія
  2. DSL (мови для домену)
  3. Атрибути (.NET) або Анотації (Java)
  4. Джерела (.NET / Java)
  5. Шаблони (C ++)
  6. method_missing (Ruby)
  7. закриття / функції першого класу / делегати
  8. AOP - орієнтоване на аспекти програмування

дуже лаконічна і продумана відповідь. дав мені гарне меню речей для дослідження. спасибі!
swyx

6

Метапрограмування - це написання програми, яка виводить іншу програму. Це щось, на кшталт Lisp, справді добре. Набагато простіше це зробити мовою, яка підтримує справжні макроси (не макроси C ++, а скоріше ті, які можуть маніпулювати кодом, який вони виводяться), такі як Ruby, Lisp, Scheme тощо, ніж на такій мові, як Java.

Однією з реалізацій є створення "мови, визначеної для домену", яка є способом вдосконалення мови програмування для досягнення конкретного завдання. Це може бути неймовірно потужно, якщо зробити це правильно. Ruby on Rails - хороший приклад такого роду програмувань.

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


5

Метапрограмування - це написання комп'ютерних програм, які записують або маніпулюють іншими програмами (або самими собою) як їх дані, або які виконують частину роботи під час виконання, яка в іншому випадку буде виконана під час компіляції. У багатьох випадках це дозволяє програмістам зробити більше за той самий проміжок часу, що потрібно для написання всього коду вручну, або це надає програмам більшу гнучкість для ефективного вирішення нових ситуацій без перекомпіляції. ( Джерело .)

В основному, це код написання, який видає більше коду, який виконується для досягнення певної мети. Зазвичай це робиться або в межах однієї мови (використовуючи javascript для створення рядка javascript, потім evalце), або для випуску іншої мови (використовуючи .NET для створення пакетного файлу Windows).


4

у wikipedia є приємна стаття на цю тему. Не потрібно робити модифікацій виконання, щоб щось можна було кваліфікувати як метапрограмування. Наприклад, багато людей використовують шаблони C ++ для метапрограмування під час компіляції.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.