Е.И. Большакова, Н.В. Груздева - Основы программирования на языке Лисп, страница 17
Описание файла
PDF-файл из архива "Е.И. Большакова, Н.В. Груздева - Основы программирования на языке Лисп", который расположен в категории "". Всё это находится в предмете "искусственный интеллект" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 17 страницы из PDF
После вывода поясняющей строкииз списка свойств достаётся и выводится увеличенное число, и оностановится итоговым значением функции Plus5.Аналогично, в теле лямбда-выражения, являющегося, по сути,определением безымянной функции, допускается произвольное числовыражений:(lambda (m1 m2 … mk) e1 e2 … en)n≥0, k≥0 .При соответствующем лямбда-вызове((lambda (m1 m2 … mk) e1 e2 … en) p1 p2 … pk)после связывания формальных параметров m1 m2 … mk происходитпоследовательное вычисление выражений-форм е1 … en, и в качестверезультата лямбда-вызова берётся значение последней формы en . Опятьже, в случае пустого тела функции её значение равно NIL.В лисповской конструкции let, позволяющей вводить локальныепеременные и являющейся другой формой записи лямбда-вызова, такжедопускается любое количество вычисляемых выражений.
Общий вид let:(let ((m1 p1)(m2 p2)…(mk pk)) e1 e2 … en)n≥0, k≥1Эта форма эквивалентна лямбда-вызову:((lambda (m1 m2 … mk) e1 e2 … en) p1 p2 … pk)и позволяет завести и связать локальные переменные m1 m2 … mk созначениями p1 p2 … pk на время вычисления форм e1 e2 … ek.Значением обращения к let является значение последней формы en (илиNIL в случае n=0). Отметим, что сначала вычисляются значенияфактических параметров (форм p1 p2 … pn), а затем происходит90одновременное связывание полученных значений с формальнымипараметрами m1 m2 … mk.Опишем ещё одну полезную конструкцию let*, которая аналогичнаlet, но вычисление форм pi и связывание локальных переменных miпроисходит строго последовательно.
Сначала вычисляется p1, иполученное значение связывается с m1, затем вычисляется p2, и егозначение связывается с m2, и т.д. На момент вычисления формы piпеременные m1 … mi-1 уже связаны и их значения могут бытьиспользованы для вычисления выражения pi. Приведём примериспользования этой конструкции:(let* ((X 12) (Y (* X 2)) (Z (+ X Y)) )(print X) (print Y) (print Z) )В результате вычисления этой формы будут выведены последовательночисла 12, 24, 36, а число 36 станет значением формы.Подчеркнём, что использование конструкций defun и let в ихобщей форме предполагает некоторые побочные эффекты при вычислениивходящих в них выражений e1 e2 … en, возможно за исключениемпоследнего en, служащего для определения результирующего значения. Поэтой причине в функциональных программах обычно используется неболее одного выражения e в конструкции let и не более одноговыражения в теле функции при её определении функцией defun.4.4.Определение особых функцийДо сих пор для определения новых функций нами использоваласьфункция defun в основном с обращением(defun F (x1 … xk) e)или, что то же самое (defun F (lambda (x1 … xk) e))При необходимости можно использовать более общий вид:(defun F (x1 … xk) e1 … en ) , n ≥ 0или (defun F (lambda (x1 … xk) e1 … en)) , n ≥ 0 .При этом происходит связывание имени F с определяющимвыражением обычной функции, которая имеет фиксированное количествоаргументов, причем каждый из них вычисляется перед выполнением телафункции.
Хотя в большинстве случаев этого достаточно для решенияпрактических задач, иногда всё же удобно ввести и затем применятьфункцию, имеющую произвольное число аргументов либо невычисляющую аргументы (например, чтобы при обращении к функции ихне квотировать).91Для определения новых особых функций в диалекте MuLispдопускается более общая форма обращения к defun:┌ lambda┐ ┌┐X(defun F (│ nlambda│ │ (x1…xk) │ e1 … en)) .└┘ └┘В этой записи: F – имя функции (символьный атом);X, x1, x2 … xk – формальные параметры (символьные атомы), k ≥ 0;e1 … en – тело функции (лисповские формы), n ≥ 0 .Квадратные скобки обозначают выбор одного из двух альтернативныхвариантов.
Таким образом, имеем 4 возможные комбинации:I. (defun F (lambda (x1 … xk) e1 … en)) или сокращённо(defun F (x1 … xk) e1 … en) – это определение обычнойфункции F (см. предыдущий раздел и раздел 1.3).II. (defun F (lambda X e1 … en)) или сокращённо:(defun F X e1 … en) – определение функции F с произвольнымколичеством вычисляемых аргументов. К определённой такимобразом функции F можно обращаться с любым числомфактических параметров (аргументов). Все они перед выполнениемтела функции вычисляются, и из их значений составляется список,который связывается с формальным параметром X (т.е.
становитсяего значением). Таким образом, в процессе вычисления вызовафункции (F p1…pk) выполняются следующие этапы:1) вычисление фактических параметров: p1=>v1, … , pk=>vk;2) связывание формального параметра: X = (v1 … vk);3) вычисление тела e1 … en при установленном значении (связи) Х.III. (defun F (nlambda (x1 … xk) e1 … en)) – определениефункции F с фиксированным количеством аргументов, и они невычисляются. При вызове функции (F p1…pk) её формальныепараметры x1, … , xk попарно связываются с фактическими p1, … , pkв том виде, как они заданы в обращении. Поскольку вычислениезначений фактических параметров не производится, в итоге остается2 этапа выполнения функционального вызова:1) связывание формальных параметров: x1 = p1, ...
, xk = pk;2) вычисление тела e1 … en при зафиксированных связях xi = pi ; приэтом всюду, где необходимо вычислить xi, в качестве его значенияиспользуется pi.IV. (defun F (nlambda X e1 … en)) – определение функции F спроизвольным количеством невычисляемых аргументов. При вызовеэтой функции (F p1…pk) может быть задано любое количество92фактических параметров-аргументов, и все они не вычисляются.
Изних (в том виде, как они заданы) составляется список, которыйсвязывается с формальным параметром Х. Таким образом, этапывыполнения функционального вызова:1) Связывание формального параметра X = (p1 … pk);2) вычисление тела e1 … en при установленном значении (связи) X.Во всех рассмотренных случаях в качестве значения выполненногофункционального вызова при n>0 берётся вычисленное значение en; апри n=0 значение функции равно NIL.Приведём примеры определений нескольких особых функций (всеони являются встроенными).; определение в MuLisp функции list(defun list(lambda X X))Функция list вычисляет свои аргументы (т.к.
используетсяlambda), их количество произвольно, поэтому с формальным параметромХ связывается список вычисленных аргументов, этот список (значение X)и возвращается в качестве результата list.; определение в MuLisp функции quote(defun quote(nlambda (X) X))Функция quote имеет один аргумент X, и он не вычисляется(используется nlambda); в качестве результата возвращается значение X,т.е. выражение-аргумент в его исходном виде.; определение в MuLisp функции or(defun or(nlambda Y(cond ((null Y)NIL)((eval (car Y)))(T (eval (cons 'or (cdr Y)))))))Функция or не всегда вычисляет все свои аргументы, поэтомуиспользуется nlambda.
Функция имеет произвольное число аргументов, иформальный параметр Y связывается со списком невычисленных еёаргументов. Если список Y пуст, значение функции равно NIL. Иначевычисляется значение первого аргумента or (первого элемента Y), и еслионо отлично от NIL, то возвращается в качестве результата вычислениявызова or. В противном случае (когда значение первого аргумента orравно NIL) строится и вычисляется рекурсивный вызов функции or составшимися аргументами.93; определение в MuLisp функции and(defun and(nlambda Z(cond ((null Z)T)((null (cdr Z))(eval (car Z)))((eval (car Z))(eval (cons 'and (cdr Z)))))))Функция and определяется аналогично функции or, посколькутакже имеет произвольное количество аргументов и не всегда ихвычисляет.
Отличие состоит в возвращаемом ею результате и условиипродолжения рекурсии. Если список аргументов Z пуст, в качествезначения функции and возвращается T, а если в списке Z один элемент –возвращается его значение. В случае, когда в списке Z больше двухэлементов, вычисляется значение первого, и если оно отлично от NIL, тостроится и вычисляется рекурсивный вызов функции and с оставшимисяаргументами.; определение в MuLisp функционала funcall(defun funcall(nlambda L(eval (cons (eval (car L))(cdr L)))))Напомним, функционал funcall имеет произвольное количествовычисляемых аргументов, но не менее одного (значение первого егоаргумента – имя применяемой функции). При определении funcallреализована следующая идея: при вызове функционала аргументы невычисляются и из них образуется список L, на основе которого строится ивычисляется нужный функциональный вызов.
В этом функциональномвызове первым элементом берётся имя применяемой функции – значениепервого элемента списка L, вычисленное вызовом внутренней eval.Остальные элементы функционального вызова – это аргументыприменяемой функции, которые будут вычислены самой этой функцией.Для вычисления построенного функционального вызова служит внешнееобращение к функции eval.В диалекте Common Lisp рассмотренные возможности определенияособых функций (nlambda и список аргументов X) отсутствуют. В то жевремя есть другие средства, позволяющие при помощи функции defunопределить новую функцию с произвольным количеством вычисляемыхаргументов.Список формальных параметров определяемой функции в CommonLisp может содержать так называемые ключевые слова, которыеначинаются со знака &, записываются перед нужными параметрами спискаи позволяют трактовать эти параметры определённым образом.94Ключевое слово &rest используется для описания функции спроизвольным количеством вычисляемых аргументов. Формальныйпараметр, записанный в списке параметров после этого ключевого слова,будет связан со списком фактических параметров, указанных в вызовефункции и несвязанных с другими формальными параметрами.Например, функция list описывается следующим образом:; определение в Common Lisp функции list(defun list (&rest LS) LS) .При вызове этой функции с фактическими параметрами (их количествонеограниченно), они будут вычислены, и из их значений будет составленсписок LS, который и будет выдан в качестве значения функции.По сути, в Common LISP обращение к функции defun вида(defun F (&rest X) e1 … en) , n ≥ 1эквивалентно рассмотренному случаю II определения особой функции вMuLisp:(defun F X e1 … en).Покажем определение в Common LISP ещё одной функции спроизвольным количеством вычисляемых аргументов.; определение в Common Lisp функции funcall(defun funcall(F &rest L)(eval (cons F (Qu L))))(defun Qu(L) ;вспомогательная функция квотирования(cond ((null L) NIL)(T (cons (list 'quote (car L))(Qu (cdr L))))))Для определения в диалекте Common Lisp функций,вычисляющих свои аргументы, необходим механизм макросов.4.5.неМакросредстваЧтобы построить и затем вычислить построенное выражение, можноиспользовать базовую функцию eval (примеры этого были даны ранее).Однако проще и естественнее это сделать с помощью определяемыхпользователем макросов, или макрофункций.