Введение

Языки программирования с расширяемостью во время выполнения

В информатике динамический язык программирования — это класс языков программирования высокого уровня, которые выполняют многие общие операции во время выполнения, которые статические языки программирования выполняют во время компиляции. Эти операции могут включать расширение программы путем добавления нового кода, расширения объектов и определений или изменения системы типов. Хотя подобные возможности можно эмулировать практически на любом языке, с разной степенью сложности, и с разными затратами на производительность, динамические языки предоставляют прямые инструменты для их реализации. Многие из этих возможностей впервые были реализованы как встроенные функции в языке программирования Lisp. Большинство динамических языков также динамически типизированы, но не все. Динамические языки часто (но не всегда) называют скриптовыми языками, хотя этот термин в узком смысле относится к языкам, предназначенным для конкретной среды выполнения.

Эваль

Некоторые динамические языки предоставляют функцию `eval`. Эта функция принимает строку или абстрактное синтаксическое дерево, содержащее код на этом языке, и выполняет его. Если этот код представляет собой выражение, возвращается результат его вычисления. Эрик Мейер и Питер Дрейтон проводят различие между генерацией кода во время выполнения, обеспечиваемой функцией `eval`, и динамической загрузкой, обеспечиваемой общими библиотеками, и предупреждают, что во многих случаях `eval` используется лишь для реализации функций высшего порядка (путем передачи функций в виде строк) или десериализации.

Изменение времени выполнения объекта

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

Вывод типа

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

Размещение переменной памяти

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

Отражение

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

Макрофайлы

Ограниченное число динамических языков программирования предоставляют возможности, объединяющие интроспекцию кода (способность исследовать классы, функции и ключевые слова, чтобы понять их сущность, назначение и данные) и функцию `eval` в рамках механизма, называемого макросами. Большинство программистов, знакомых с термином "макрос", встречали их в C или C++, где макросы представляют собой статическую функцию, встроенную в небольшое подмножество языка, способную лишь на текстовую подстановку в исходном коде программы. Однако в динамических языках макросы обеспечивают доступ к внутренним механизмам компилятора и полный доступ к интерпретатору, виртуальной машине или среде выполнения, позволяя определять конструкции, подобные языковым, которые могут оптимизировать код или изменять синтаксис или грамматику языка. Языки ассемблера, C, C++, ранние версии Java и Fortran обычно не подпадают под эту категорию.

Пример кода

Следующие примеры демонстрируют динамические возможности, использующие язык Common Lisp и его объектно-ориентированную систему Common Lisp (CLOS).