Генерация строк и выполнение их как программ во время выполнения
Это сложный вопрос к слову, и я не уверен, что будет правильным термином для него (если есть). Мне любопытно, какие языки позволяют вам "создать" строку во время выполнения программы, а затем выполнить ее как часть программы. Единственный язык, который я знаю, который позволяет вам делать это, это Снобол.
Однако, если вы читаете статью в Википедии для Tcl, возможно, она сможет это сделать?
Я всегда думал, что это отличная особенность, даже если она не может быть использована много. Благодарю.
PS: пометил бы это Snobol, Spitbol, но не имел репутации создавать новые теги.
3 ответа
Мне любопытно, какие языки позволяют вам "создать" строку во время выполнения программы, а затем выполнить ее как часть программы.
Ищите языки, которые поддерживают eval
или, в более общем смысле, метапрограммирование во время выполнения. Практически каждый язык поддерживает eval
(даже строго, статически типизированные языки, такие как Haskell). Многие среды выполнения, созданные для языков, которые в основном реализуются с помощью интерпретации байт-кода (например, Lisp-подобные языки, Erlang или Java), поддерживают возможность вставки нового (байтового) кода во время выполнения. Как только вы можете вставить новый код динамически, вы можете написать eval
или сделайте "исправление обезьян".
Даже в языковых реализациях без специальной поддержки полного метапрограммирования или даже динамического связывания часто есть способы динамически генерировать код под управлением программиста, либо с помощью механизмов отражения, либо библиотек поддержки генерации кода (таких как LLVM).
Вне простой простой стадии eval
в более общем смысле, языки, которые поддерживают многоступенчатые вычисления, позволяют генерировать программы от одного этапа к другому для произвольного числа этапов, что позволяет безопасно, произвольно вкладыватьevals
,
По словам Тахи, чей тезис о многоступенчатых моделях программирования представляет большую часть теории.
Генерация программ - это мощный и распространенный метод разработки программного обеспечения. Он был использован для улучшения повторного использования кода, надежности и удобства обслуживания продукта, производительности и использования ресурсов, а также производительности разработчиков
Языки, которые вы ищете, обычно предоставляют три примитива, в той или иной форме:
- задержка
- сращивание
- бежать
для задержки вычислений на одну стадию (например, цитирование фрагмента в виде строки), объединения его в работающую программу и выполнения этого фрагмента (в Lisp, обратная кавычка, запятая и eval).
Лисп и Эвал
- Маккарти, Джон, История LISP, SIGPLAN Нет. 1978. - вводит
eval
Обобщение eval для многоступенчатого программирования
По многоступенчатому программированию:
- Таха, Многоступенчатое программирование: теория и приложения
- Нильсон, Флемминг и Нильсон, Ханне Риис, Двухуровневые функциональные языки, - представили двухуровневые языки.
- Таха, Валид и Шеард, Тим, Многоступенчатое программирование с явными аннотациями - простые операторы, поддерживающие все методы метапрограммирования во время выполнения.
Предоставление типов многоступенчатому программированию
Формальные описания многоступенчатых вычислений довольно сложны и включают необычные методы (для языков программирования), такие как модальная логика.
Предоставление типов метапрограммам:
- Виклайн, Филип и Ли, Питер и Пфеннинг, Фрэнк и Дэвис, Роуэн, Модальные типы в качестве промежуточных спецификаций для генерации кода во время выполнения.
Проблемы с безопасностью
Хитрость формализации семантики многоступенчатого программирования объясняет, почему они часто путают системы, с которыми работают, и почему eval
может вызвать множество проблем с безопасностью: становится неясно, какой код выполняется, когда и какие именно данные превращаются в код. Перехватить имена с одного этапа на другой довольно сложно, что приводит к атакам с использованием кода. Такая сложность не помогает безопасности.
Определенно может быть сделано на многих интерпретируемых языках сценариев. И некоторые языки специально разработаны для этого. Это может быть сделано, насколько мне известно, в:
- Perl
- PHP
- Лисп (и диалекты, такие как CL, Clojure, Scheme и т. Д.)
- JavaScript
Это можно сделать на всех диалектах Лисп, где эта функция возникла под названием eval
как и в прологе (call/1
) и любое количество других языков. Большинство держат имя eval
и большинство из них являются динамическими языками.
При этом, это вряд ли изящная особенность. Я бы назвал это серьезной проблемой безопасности, учитывая, насколько легко злоупотреблять этой функцией. Если вы хотите динамическое выполнение кода, то написание собственного ограниченного микропереводчика (или использование чего-то вроде Lua) почти всегда является лучшей идеей.