Шаг 19.
Функционалы. Интерпретатор языка LISP EVAL

    На этом шаге мы познакомимся с функцией EVAL.

    До сих пор мы рассматривали функции, которые в качестве аргументов получали выражения, не являющиеся функциями.

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

   

Интерпретатор языка LISP EVAL.

    Функция EVAL - это функция, которая может вычислить любое правильно составленное выражение языка LISP. Например:


   $ (EVAL (PLUS 2 3))
   5
   $ (EVAL (LIST (READ) (READ) (READ)))
   PLUS
   2
   3
   5
Говорят, что функция EVAL определяет семантику лисповских форм.

    "Лишний" вызов интерпретатора может, например, снять эффект блокировки вычисления при помощи функции QUOTE или позволяет найти значение значения выражения. Например:


   $ (EVAL (QUOTE (PLUS 1 2)))
   3
QUOTE и EVAL действуют "во взаимно противоположных направлениях" и как-бы аннулируют эффект друг друга.

    Для функции EVAL нет аналогий в языках императивного программирования. Используя EVAL, мы можем выполнить "оператор", который в действительности создан нашей LISP-программой и который может меняться в процессе выполнения программы.


    Замечание 1. Диалог с интерпретатором языка LISP на самом верхнем, командном уровне, можно описать простым циклом:

   (PRINT (QUOTE _))     % Вывод приглашения             %
   (PRINT (EVAL (READ))) % Ввод выражения и              %
                         % вычисление его значения       %
   (PRINT (QUOTE _))     % Повторение вывода приглашения %
      ...    ...
Интерпретатор отвечает на заданный ему вопрос и ждет новое задание.

    Замечание 2. Во многих LISP-системах имеется функция EVAL-QUOTE, которая подобна функции EVAL, за исключением того, что имеет два аргумента. Первый аргумент является именем функции, а второй - списком ее аргументов. Аргументы EVAL-QUOTE не вычисляются. Функция EVAL-QUOTE может быть определена как:


   (EVAL (READ) (READ))

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

    Замечание 4. Опишем семантику функции EVAL для версии muLISP85.

    Если OBJECT - атом, то функция (EVAL OBJECT) возвращает содержимое ячейки значения OBJECT. Т.к. ссылки на новые выбранные атомы автоматические, атомы "вычисляют сами себя" до тех пор, пока не будут связаны с другими значениями.

    Если CAR-элемент OBJECT - это имя вычисляемой функции или LAMBDA, то функция (EVAL OBJECT) вычисляет каждый элемент CDR-части OBJECT и добавляет CAR-элемент OBJECT к списку результатов.

    Если CAR-элемент OBJECT - имя невычисляемой функции, то функция (EVAL OBJECT) добавляет CAR-элемент OBJECT к CDR-элементу OBJECT без вычисления последнего.

    Если CAR-элемент OBJECT - имя макрофункции, то функция (EVAL OBJECT) рекурсивно вычисляет результат добавления CAR-элемента OBJECT к его CDR-элементу.

    Если CAR-элемент OBJECT - не функция, то функция (EVAL OBJECT) вызывает ошибку "Неопределенная функция" (UNDEFINED) и генерирует прерывание по ошибке.




    На следующем шаге мы введем понятие аппликативного функционала.




Предыдущий шаг Содержание Следующий шаг