Противопоставление функционального и
С практической точки зрения любые конструкции стандартных языков программирования могут
быть введены как функции, дополняющие исходную систему программирования, что делает их вполне
легальными средствами в рамках
Применение prog-выражений позволяет писать "паскалеподобные" программы, состоящие из операторов, предназначенных для исполнения. (Точнее "алголоподобные", т.к. появились лет за десять до паскаля. Но теперь более известен паскаль.)
Для примера prog-выражения приводится императивное определение функции (
"Это функция одного аргумента L. Она реализуется
программой с двумя рабочими переменными u и v.
Записать число 0 в v.
Записать аргумент L в u.
A: Если u содержит NIL, то программа выполнена и
значением является то, что сейчас записано в v.
Записать в u cdr от того, что сейчас в u.
Записать в v на единицу больше того, что
сейчас записано в v.
Перейти к A"
Эту программу можно записать в виде Паскаль-программы с несколькими подходящими типами данных и
функциями. Строкам описанной выше программы в предположении, что существует библиотека
function LENGTH (L: list) : integer;
label A;
var U: list;
V: integer;
begin
V := 0;
U := L;
A: if null (U) then LENGTH := V;
U := cdr (U);
V := V+1;
goto A;
end;
Переписывая в виде S-выражения, получаем программу:
((DEFUN LENGTH (L)
(PROG (U V)
(SETQ V 0)
(SETQ U L)
A (COND ((NULL U)(RETURN V)))
(SETQ U (CDR U))
(SETQ V (+ 1 V))
(GO A)
) )
(LENGTH '(A B C D))
(LENGTH '((X . Y) A CAR (N B) (X Y Z)))
Последние две строки содержат тесты. Их значения четыре и пять, соответственно. PROG, список
PROG называется списком или (). С LAMBDA. Значение каждой , до
тех пор, пока ей не будет присвоено что-нибудь другое
pi значение 3.14
пишется (SET (QUOTE PI)3.14). SETQ подобна (SETQ PI 3.14) — запись того же присваивания. SETQ обычно удобнее. SETQ могут изменять значения любых
переменных из а-списка более SETQ является значение их второго аргумента.
Обычно
(GO A) указывает, что программа продолжается оператором, помеченным
атомом A, причем это A может быть и из внешнего выражения PROG
Условные выражения в качестве операторов программы обладают полезными особенностями. Если ни одно из
пропозициональных выражений не истинно, то вместо указания на ошибку, происходящего во всех других случаях,
программа продолжается оператором, следующим за условным выражением. Это справедливо лишь для условного
выражения, находящегося на верхнем уровне PROG.
Формы PROG или внутри ,
находящегося на верхнем уровне PROG.
Если программа прошла все свои .
Prog-выражение, как и другие
Функция , обращающая список и все подсписки, столь же естественно пишется с помощью рекурсивного Prog-выражения.
function rev (x: list) :List;
label A, B;
var y, z: list;
begin
A: if null (x) then rev := y;
z := cdr (x);
if atom (z) then goto B;
z := rev (z);
B: y := cons (z, y);
x := cdr (x);
goto A;
end;
Функция обращает все уровни списка, так что от (A ((B C) D)) даст ((D (C B))A).
(DEFUN REV (X)
(PROG (Y Z)
A (COND ((NULL X)(RETURN Y)))
(SETQ Z (CDR X))
(COND ((ATOM Z)(GOTO B)))
(SETQ Z (REV Z))
B (SETQ Y (CONS Z Y))
(SETQ X (CDR X))
(GOTO A)
))
Для того чтобы форма PROG была полностью законна, необходима возможность дополнять а-список
Кроме того, уточнен механизм условных выражений: отсутствие истинного предиката не препятствует формированию
значения . Такое доопределение условного выражения приглянулось и в области обычных функций, где оно часто дает
компактные формулы для рекурсии по списку.
В принципе, SETQ могут быть реализованы с помощью a-списка примерно так же, как и поиск значения, только
с копированием связей, расположенных ранее изменяемой переменной (см. функцию ASSIGN из лекции 3). Более
эффективная реализация будет описана ниже.
(DEFUN SET (X Y) (ASSIGN X Y Alist))
Обратите внимание, что введенное таким образом присваивание работает разнообразнее, чем традиционное: обеспечена вычисляемость левой части присваивания, т.е. можно в программе вычислять имена переменных, значение которых предстоит поменять.
(SETQ X 'Y) (SET X 'NEW) (PRINT X) (PRINT Y)
Напечатается Y и NEW (традиционно атомы печатаются заглавными буквами).
До сих пор атом рассматривался только как уникальный
Каждый атом имеет список свойств. Когда атом читается (вводится) впервые, тогда для него создается пустой
список свойств, который потом можно заполнять. Список свойств устроен как специальная структура, подобная записям в Паскале, но
указатели в такой записи сопровождаются
В первых реализациях
PNAME — EXPR — SUBR — функция, определенная подпрограммой на APVAL — В списке свойств атома было два индикатора, PNAME и APVAL, со значением .
Более детально диаграммы списков свойств приведены в описании Lisp 1.5. .
Здесь достаточно принять к сведению, что реализация атомарных объектов — это сложная структура данных, в свою очередь представленная списками.
(GET x i) можно найти для атома x свойство, i
Значением (GET 'FF 'EXPR) будет (LAMBDA (X) (, если определение FF было предварительно
задано с помощью (.
Свойство с его (.
С середины 70-х годов возникла тенденция повышать эффективность разработкой специальных структур,
отличающихся в разных реализациях. Существуют реализации, например, muLisp, допускающие работу
с представлениями атома как с обычными списками посредством функций CAR, .
Согласно стандарту SYMBOL-FUNCTION и SYMBOL-VALUE. Список произвольных свойств можно получить с использованием
функции SYMBOL-PLIST. Функция
(SETF (GET atom indicator ) property )
До этого момента списки рассматривались на уровне текстового ввода-вывода. В настоящем
разделе анализируется кодовое представление списков внутри машины и
В машине списки хранятся не как последовательности символов, а как структурные формы, построенные из машинных слов как частей деревьев, подобно записям в Паскале при реализации односвязных списков. При изображении структуры списка машинное слово рисуется как прямоугольник, разделенный на две части: адрес и декремент
(рис 1.1) структура спискаКаждая из частей занимает фиксированное число разрядов, представляющее тэг и адрес. Если декремент слова "x" указывает на слово "y", то это можно выразить стрелками на схеме:
(рис 1.2) схемаТеперь можно дать правило представления S-выражений в машине. Представление атомов будет пояснено
ниже. В тех случаях, когда машинное слово в адресе или декременте содержит
(рис 1.3) отображение атома в прямоугольникеПравило представления неатомных S-выражений — начало со слова, содержащего указатель на car
выражения в адресе и указатель на
(рис 1.4) обозначение NILвместо (A . B).
(рис 1.5) (A . B)Непосредственная польза от сопоставления графического вида с представлением списков в памяти поясняется при рассмотрении функций, работающих со списками, на следующем примере из [1]:
((M . N) X (M . N))
(рис 1.8) примерВозможное для списков использование общих фрагментов ((M . N) X (M . N)) может быть представлено графически:
(рис 1.9) графическое представлениеВ точности такую структуру непосредственно текстом представить невозможно, но ее можно построить с помощью одного из выражений выражений:
(LET ((a '(M . N))) (SETQ b (LIST a 'X a)) ) ((LAMBDA (a) (LIST a 'X a) )'(M . N))
Циклические списки обычно не поддерживаются. Такие списки не могут быть введены
(рис 1.10) структураможет распечатываться как ( A B C A B C ... ).
Преимущества структур списков для хранения S-выражений в памяти:
Ниже следует простой пример, иллюстрирующий точность построения структур списка. Показаны два типа
структур списка и описаны на
Предполагается, что дан список вида
L1 = ((A B C)(D E F ) ... (X Y Z))
представленный как
(рис 1.11) точность построения структр спискаи нужно построить список вида
L2 = ((A (B C))(D (E F)) ... (X (Y Z)))
представленный как
(рис 1.12) список видаРассмотрим типичную подструктуру (A (B C)) второго списка.
Она может быть построена из A, B и C с помощью
(CONS 'A (CONS (CONS 'B (CONS 'C NIL)) NIL))
или, используя функцию list, можно то же самое записать как
(LIST 'A (LIST 'B 'C))
В любом случае дан список x из трех атомов x = (A B C), аргументы A, B и C, используемые в предыдущем построении, можно найти как
A = (CAR x) B = (CADR x) C = (CADDR x)
Первый шаг в получении L2 из L1 — это определение функции GRP, строящей (X (Y Z)) из списка вида (X Y Z).
(GRP x) = (LIST (CAR x) (LIST (CADR x) (CADDR x)))
Здесь GRP применяется к списку L1 в предположении, что L1 заданного вида.
Для достижения цели новая функция MLTGRP определяется как
(MLTGRP L) = (COND ((NULL L) NIL)
(T (CONS (GRP (CAR L)) (MLTGRP (CDR L)) )))
Итак, MLTGRP, применяемая к списку L1, перебирает (X Y Z) по очереди и применяет к ним GRP, чтобы
установить их новую форму (X (Y Z)) до тех пор, пока не завершится список L1 и не построится новый
список L2.
Теория рекурсивных функций, изложенная в лекции 2, будет упоминаться далее как строгий, чистый или
элементарный
В частности, элементарный , а она не изменяет существующие списки,
только создает новые. Функции, описанные в SUBST, в действительности не
модифицируют свои аргументы, но делают модификации, копируя оригинал.
Элементарный .
( заменяет адрес из x на y, эквивалент (CAR x) := y. Ее значение — x, но x, несколько
отличающийся от того, что было раньше. На языке значений
(RPLACA x y) = (CONS y (CDR x))
Но действие различное: никакие не вызываются и новые слова не создаются.
(x на y, эквивалент (.
Эти операции должны применяться с осторожностью! Они могут в корне преобразить существующие
определения и EQUAL и SUBST.
, таких как NCONC, и т.п.
Для примера рассмотрим функцию MLTGRP. Это преобразующая список функция,
которая преобразует копию своего аргумента. Подфункция GRP реорганизует подструктуру
(рис 1.13) подструктурав структуру из тех же атомов:
(рис 1.14) структура из тех же атомовИсходная функция делает это, создавая новую структуру и используя четыре . Из-за того,
что в оригинале только три слова, по крайней мере, один необходим, а GRP можно переписать
с помощью
(рис 1.15) новая структураПусть новое машинное слово строит (. Тогда указатель на него встраивается в x при вычислении формы:
(RPLACA (CDR x) (CONS (CADR x) (CDDR x)))
Другое изменение сводится к удалению из второго слова указателя на третье слово.
Это выполняется как вычисление формы (.
Функция PGRP теперь определяется как соотношение:
(PGRP x) = (RPLACD (RPLACA (CDR x) (CONS (CADR x) (CDDR )x))) NIL)
Функция PGRP используется, в сущности, ради ее действия. Ее значением, неиспользуемым, является подструктура ((B C)). Поэтому для MLTGRP необходимо, чтобы PGRP выполнялось, а ее значение игнорировалось. Поскольку верхний
уровень не должен копироваться, MLTGRP не обязана основываться на .
(PMLTGRP L) =(COND ((NULL L) NIL)
(T (PROG2 (PGRP (CDR L))
(PMLTGRP (CDR L)) )))
Значение PMLTGRP — и PMLTGRP —
В любой момент времени только часть памяти, отведенной для структур списков, действительно
используется для хранения S-выражений. Остальные ячейки организованы в простой список,
называемый
Первые реализации действовали по следующей схеме .
Определенный регистр FREE содержит информацию о первой ячейке этого списка. Когда
требуется слово для формирования дополнительной структуры списка, берется первое слово
списка свободной памяти, а код в регистре FREE заменяется на информацию о втором слове
списка свободной памяти. Не требуется никаких программных средств для того, чтобы
пользователь программировал возврат ячеек в CAR-.
Любая ячейка, не достижимая таким образом, недоступна для программы и не активна, поэтому
ее содержимое не представляет интереса. Неактивные, то есть недоступные программе ячейки
восстанавливаются CAR-, метится установлением отрицательного
знака. Где бы ни выявилось отрицательное слово в цепи во время процесса пометки,
Иногда структуры списка указывают на полные слова, такие как
В этом случае проблемы повторного использования памяти решаются расположением полных слов
в зарезервированной области памяти, называемой областью полных слов. Мусорщик должен прекращать
прослеживание, как только покидает
Такая реализация экономична в отношении памяти, но она имеет ряд неприятных следствий:
непредсказуемые длинноты (время работы) при поиске очередной порции ячеек и "перегрев системы", если такие
порции слишком малы для продолжения счета. По мере роста производительности оборудования
разработаны простые и не столь обременительные алгоритмы повторного использования памяти на
базе параллельных процессов и профилактического копирования активных структур данных в
дополнительные
В качестве примера повышения гибкости определений приведено упрощенное определение
Ради
"(ASSOC e al )".
Определения функций хранятся в ассоциативном списке, как и значения переменных.
Функция SUBR — вызывает примитивы, реализованные другими, обычно низкоуровневыми,
средствами. ERROR — выдает сообщения об ошибках и сведения о контексте вычислений,
способствующие поиску источника ошибки. Уточнена работа с
(DEFUN EVAL (e al )
(COND
((EQ e NIL ) NIL )
((ATOM e )((LAMBDA (v )
(COND (v (CDR v ) )
(T (ERROR 'undefvalue )) )
) (ASSOC e al ) )
)
((EQ (CAR e) 'QUOTE ) (CAR (CDR e )) )
((EQ (CAR e) 'FUNCTION )
(LIST 'FUNARG (CADR fn ) al ) )
((EQ (CAR e) 'COND ) (EVCON (CDR e ) al ) )
(T (apply (CAR e)(evlis (CDR e) al ) al ) )
) )
(DEFUN APPLY (fn args al )
(COND
((EQ e NIL ) NIL )
((ATOM fn )
(COND
((MEMBER fn '(CAR CDR CONS ATOM EQ ))
(SUBR fn agrs al ))
(T (APPLY (EVAL fn al ) args al ))
) )
((EQ (CAR fn ) 'LABEL )
(APPLY (CADDR fn )
args
(CONS (CONS (CADR fn )(CADDR fn ))
al ) ) )
((EQ (CAR fn ) 'FUNARG )
(APPLY (CDR fn ) args (CADDR fn)) )
((EQ (CAR fn ) 'LAMBDA )
(EVAL (CADDR fn )
(APPEND (PAIR (CADR fn ) args ) al ))
(T (APPLY (EVAL fn al ) args al ))
) )
Определения ASSOC, APPEND, PAIR, LIST — стандартны.
Примерно то же самое обеспечивают EVAL-P и APPLY-P, рассчитанные на использование списков
свойств атома для хранения CATEGORY
указывает в списке свойств атома на правило интерпретации функций, относящихся к отдельной
категории, — на частный метод построения представления функции. Функция VALUE реализует
методы поиска текущего значения переменной в зависимости от контекста и свойств атомов.
(DEFUN EVAL-P (E C)
(COND ((ATOM E) (VALUE E C))
((ATOM (CAR E))(COND ((GET (CAR E) 'CATEGORY)
((GET (CAR E) 'CATEGORY) (CDR E) C) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
))
(DEFUN APPLY-P (F ARGS C)
(COND ((ATOM F)(APPLY-P (FUNCTION F C) ARGS C))
((ATOM (CAR F))(COND ((GET (CAR F) 'MACRO)
(APPLY-P ((GET (CAR F) 'MACRO)
(CDR F) C) ARGS C))
(T (APPLY-P (EVAL F E) ARGS C))
) )
(T (APPLY-P (EVAL F E) ARGS C))
))
Или то же самое с вынесением общих
(DEFUN EVAL-P (E C)
(COND ((ATOM E) (VALUE E C))
((ATOM (CAR E))
((LAMBDA (V) (COND (V (V(CDR E) C) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
)) (GET (CAR E) 'CATEGORY) ) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
))
(DEFUN APPLY-P (F ARGS C)
(COND ((ATOM F)(APPLY-P (FUNCTION F C) ARGS C))
((ATOM (CAR F))
((LAMBDA (V) (COND (V (APPLY-P (V (CDR F)
C) ARGS C))
(T (APPLY-P (EVAL F E) ARGS C))
))(GET (CAR F) 'MACRO) ))
(T (APPLY-P (EVAL F E) ARGS C))
))
Расширение системы программирования при таком определении интерпретации осуществляется простым введением/удалением соответствующих свойств атомов и функций.
Полученная схема интерпретации допускает разнообразные OPTIONAL, KEY и REST соответственно, размещаемой перед параметрами в LAMBDA списке формальных
аргументов. При этом серийный параметр должен быть последним в списке.
(DEFUN FUNCALL (FN REST AGRS) (APPLY FN ARGS))
Необязательный параметр может иметь начальное значение, устанавливаемое по умолчанию,
т.е. если этот параметр не задан при вызове функции. При отсутствии начального значения
его роль играет .
(DEFUN EX-OPT (space OPTIONAL dot (line 'x)) (LIST space 'of dot 'and- line)) (EX-OPT 'picture) (EX-OPT 'picture 'circle) (EX-OPT 'picture 'circle 'bars)
.
(DEFUN KEYLIST (A KEY X Y Z) (LIST A X Y Z))
(KEYLIST 1 :Y 2) ;= (1 NIL 2 NIL)
(DEFUN LENGTH (L OPTIONAL (V 0))
(COND ((NULL L) V)
(T (+ 1 (LENGTH (CDR L))))
) )
((LENGTH '(1 2) 3) ; = 5
(DEFUN REVERSE (L OPTIONAL (M NIL))
(COND ((NULL L) M)
(T (REVERSE (CDR L) (CONS (CAR L) M) ))
) )
(REVERSE '(1 2 3)) ; = (3 2 1)
(REVERSE '(1 2 3) '(5 6)) ;= (3 2 1 5 6)
Такой подход к работе параметрами часто освобождает от необходимости во вспомогательных функциях,
что упрощает и определение EVAL от обязательности упоминания а-списка. Если воспользоваться сводимостью
( при отсутствии истиного предиката и кое-где использовать отображения, то определение становится совсем компактным.
Противопоставление функционального и
С практической точки зрения любые конструкции стандартных языков программирования могут
быть введены как функции, дополняющие исходную систему программирования, что делает их вполне
легальными средствами в рамках
Применение prog-выражений позволяет писать "паскалеподобные" программы, состоящие из операторов, предназначенных для исполнения. (Точнее "алголоподобные", т.к. появились лет за десять до паскаля. Но теперь более известен паскаль.)
Для примера prog-выражения приводится императивное определение функции (
"Это функция одного аргумента L. Она реализуется
программой с двумя рабочими переменными u и v.
Записать число 0 в v.
Записать аргумент L в u.
A: Если u содержит NIL, то программа выполнена и
значением является то, что сейчас записано в v.
Записать в u cdr от того, что сейчас в u.
Записать в v на единицу больше того, что
сейчас записано в v.
Перейти к A"
Эту программу можно записать в виде Паскаль-программы с несколькими подходящими типами данных и
функциями. Строкам описанной выше программы в предположении, что существует библиотека
function LENGTH (L: list) : integer;
label A;
var U: list;
V: integer;
begin
V := 0;
U := L;
A: if null (U) then LENGTH := V;
U := cdr (U);
V := V+1;
goto A;
end;
Переписывая в виде S-выражения, получаем программу:
((DEFUN LENGTH (L)
(PROG (U V)
(SETQ V 0)
(SETQ U L)
A (COND ((NULL U)(RETURN V)))
(SETQ U (CDR U))
(SETQ V (+ 1 V))
(GO A)
) )
(LENGTH '(A B C D))
(LENGTH '((X . Y) A CAR (N B) (X Y Z)))
Последние две строки содержат тесты. Их значения четыре и пять, соответственно. PROG, список
PROG называется списком или (). С LAMBDA. Значение каждой , до
тех пор, пока ей не будет присвоено что-нибудь другое
pi значение 3.14
пишется (SET (QUOTE PI)3.14). SETQ подобна (SETQ PI 3.14) — запись того же присваивания. SETQ обычно удобнее. SETQ могут изменять значения любых
переменных из а-списка более SETQ является значение их второго аргумента.
Обычно
(GO A) указывает, что программа продолжается оператором, помеченным
атомом A, причем это A может быть и из внешнего выражения PROG
Условные выражения в качестве операторов программы обладают полезными особенностями. Если ни одно из
пропозициональных выражений не истинно, то вместо указания на ошибку, происходящего во всех других случаях,
программа продолжается оператором, следующим за условным выражением. Это справедливо лишь для условного
выражения, находящегося на верхнем уровне PROG.
Формы PROG или внутри ,
находящегося на верхнем уровне PROG.
Если программа прошла все свои .
Prog-выражение, как и другие
Функция , обращающая список и все подсписки, столь же естественно пишется с помощью рекурсивного Prog-выражения.
function rev (x: list) :List;
label A, B;
var y, z: list;
begin
A: if null (x) then rev := y;
z := cdr (x);
if atom (z) then goto B;
z := rev (z);
B: y := cons (z, y);
x := cdr (x);
goto A;
end;
Функция обращает все уровни списка, так что от (A ((B C) D)) даст ((D (C B))A).
(DEFUN REV (X)
(PROG (Y Z)
A (COND ((NULL X)(RETURN Y)))
(SETQ Z (CDR X))
(COND ((ATOM Z)(GOTO B)))
(SETQ Z (REV Z))
B (SETQ Y (CONS Z Y))
(SETQ X (CDR X))
(GOTO A)
))
Для того чтобы форма PROG была полностью законна, необходима возможность дополнять а-список
Кроме того, уточнен механизм условных выражений: отсутствие истинного предиката не препятствует формированию
значения . Такое доопределение условного выражения приглянулось и в области обычных функций, где оно часто дает
компактные формулы для рекурсии по списку.
В принципе, SETQ могут быть реализованы с помощью a-списка примерно так же, как и поиск значения, только
с копированием связей, расположенных ранее изменяемой переменной (см. функцию ASSIGN из лекции 3). Более
эффективная реализация будет описана ниже.
(DEFUN SET (X Y) (ASSIGN X Y Alist))
Обратите внимание, что введенное таким образом присваивание работает разнообразнее, чем традиционное: обеспечена вычисляемость левой части присваивания, т.е. можно в программе вычислять имена переменных, значение которых предстоит поменять.
(SETQ X 'Y) (SET X 'NEW) (PRINT X) (PRINT Y)
Напечатается Y и NEW (традиционно атомы печатаются заглавными буквами).
До сих пор атом рассматривался только как уникальный
Каждый атом имеет список свойств. Когда атом читается (вводится) впервые, тогда для него создается пустой
список свойств, который потом можно заполнять. Список свойств устроен как специальная структура, подобная записям в Паскале, но
указатели в такой записи сопровождаются
В первых реализациях
PNAME — EXPR — SUBR — функция, определенная подпрограммой на APVAL — В списке свойств атома было два индикатора, PNAME и APVAL, со значением .
Более детально диаграммы списков свойств приведены в описании Lisp 1.5. .
Здесь достаточно принять к сведению, что реализация атомарных объектов — это сложная структура данных, в свою очередь представленная списками.
(GET x i) можно найти для атома x свойство, i
Значением (GET 'FF 'EXPR) будет (LAMBDA (X) (, если определение FF было предварительно
задано с помощью (.
Свойство с его (.
С середины 70-х годов возникла тенденция повышать эффективность разработкой специальных структур,
отличающихся в разных реализациях. Существуют реализации, например, muLisp, допускающие работу
с представлениями атома как с обычными списками посредством функций CAR, .
Согласно стандарту SYMBOL-FUNCTION и SYMBOL-VALUE. Список произвольных свойств можно получить с использованием
функции SYMBOL-PLIST. Функция
(SETF (GET atom indicator ) property )
До этого момента списки рассматривались на уровне текстового ввода-вывода. В настоящем
разделе анализируется кодовое представление списков внутри машины и
В машине списки хранятся не как последовательности символов, а как структурные формы, построенные из машинных слов как частей деревьев, подобно записям в Паскале при реализации односвязных списков. При изображении структуры списка машинное слово рисуется как прямоугольник, разделенный на две части: адрес и декремент
(рис 1.1) структура спискаКаждая из частей занимает фиксированное число разрядов, представляющее тэг и адрес. Если декремент слова "x" указывает на слово "y", то это можно выразить стрелками на схеме:
(рис 1.2) схемаТеперь можно дать правило представления S-выражений в машине. Представление атомов будет пояснено
ниже. В тех случаях, когда машинное слово в адресе или декременте содержит
(рис 1.3) отображение атома в прямоугольникеПравило представления неатомных S-выражений — начало со слова, содержащего указатель на car
выражения в адресе и указатель на
(рис 1.4) обозначение NILвместо (A . B).
(рис 1.5) (A . B)Непосредственная польза от сопоставления графического вида с представлением списков в памяти поясняется при рассмотрении функций, работающих со списками, на следующем примере из [1]:
((M . N) X (M . N))
(рис 1.8) примерВозможное для списков использование общих фрагментов ((M . N) X (M . N)) может быть представлено графически:
(рис 1.9) графическое представлениеВ точности такую структуру непосредственно текстом представить невозможно, но ее можно построить с помощью одного из выражений выражений:
(LET ((a '(M . N))) (SETQ b (LIST a 'X a)) ) ((LAMBDA (a) (LIST a 'X a) )'(M . N))
Циклические списки обычно не поддерживаются. Такие списки не могут быть введены
(рис 1.10) структураможет распечатываться как ( A B C A B C ... ).
Преимущества структур списков для хранения S-выражений в памяти:
Ниже следует простой пример, иллюстрирующий точность построения структур списка. Показаны два типа
структур списка и описаны на
Предполагается, что дан список вида
L1 = ((A B C)(D E F ) ... (X Y Z))
представленный как
(рис 1.11) точность построения структр спискаи нужно построить список вида
L2 = ((A (B C))(D (E F)) ... (X (Y Z)))
представленный как
(рис 1.12) список видаРассмотрим типичную подструктуру (A (B C)) второго списка.
Она может быть построена из A, B и C с помощью
(CONS 'A (CONS (CONS 'B (CONS 'C NIL)) NIL))
или, используя функцию list, можно то же самое записать как
(LIST 'A (LIST 'B 'C))
В любом случае дан список x из трех атомов x = (A B C), аргументы A, B и C, используемые в предыдущем построении, можно найти как
A = (CAR x) B = (CADR x) C = (CADDR x)
Первый шаг в получении L2 из L1 — это определение функции GRP, строящей (X (Y Z)) из списка вида (X Y Z).
(GRP x) = (LIST (CAR x) (LIST (CADR x) (CADDR x)))
Здесь GRP применяется к списку L1 в предположении, что L1 заданного вида.
Для достижения цели новая функция MLTGRP определяется как
(MLTGRP L) = (COND ((NULL L) NIL)
(T (CONS (GRP (CAR L)) (MLTGRP (CDR L)) )))
Итак, MLTGRP, применяемая к списку L1, перебирает (X Y Z) по очереди и применяет к ним GRP, чтобы
установить их новую форму (X (Y Z)) до тех пор, пока не завершится список L1 и не построится новый
список L2.
Теория рекурсивных функций, изложенная в лекции 2, будет упоминаться далее как строгий, чистый или
элементарный
В частности, элементарный , а она не изменяет существующие списки,
только создает новые. Функции, описанные в SUBST, в действительности не
модифицируют свои аргументы, но делают модификации, копируя оригинал.
Элементарный .
( заменяет адрес из x на y, эквивалент (CAR x) := y. Ее значение — x, но x, несколько
отличающийся от того, что было раньше. На языке значений
(RPLACA x y) = (CONS y (CDR x))
Но действие различное: никакие не вызываются и новые слова не создаются.
(x на y, эквивалент (.
Эти операции должны применяться с осторожностью! Они могут в корне преобразить существующие
определения и EQUAL и SUBST.
, таких как NCONC, и т.п.
Для примера рассмотрим функцию MLTGRP. Это преобразующая список функция,
которая преобразует копию своего аргумента. Подфункция GRP реорганизует подструктуру
(рис 1.13) подструктурав структуру из тех же атомов:
(рис 1.14) структура из тех же атомовИсходная функция делает это, создавая новую структуру и используя четыре . Из-за того,
что в оригинале только три слова, по крайней мере, один необходим, а GRP можно переписать
с помощью
(рис 1.15) новая структураПусть новое машинное слово строит (. Тогда указатель на него встраивается в x при вычислении формы:
(RPLACA (CDR x) (CONS (CADR x) (CDDR x)))
Другое изменение сводится к удалению из второго слова указателя на третье слово.
Это выполняется как вычисление формы (.
Функция PGRP теперь определяется как соотношение:
(PGRP x) = (RPLACD (RPLACA (CDR x) (CONS (CADR x) (CDDR )x))) NIL)
Функция PGRP используется, в сущности, ради ее действия. Ее значением, неиспользуемым, является подструктура ((B C)). Поэтому для MLTGRP необходимо, чтобы PGRP выполнялось, а ее значение игнорировалось. Поскольку верхний
уровень не должен копироваться, MLTGRP не обязана основываться на .
(PMLTGRP L) =(COND ((NULL L) NIL)
(T (PROG2 (PGRP (CDR L))
(PMLTGRP (CDR L)) )))
Значение PMLTGRP — и PMLTGRP —
В любой момент времени только часть памяти, отведенной для структур списков, действительно
используется для хранения S-выражений. Остальные ячейки организованы в простой список,
называемый
Первые реализации действовали по следующей схеме .
Определенный регистр FREE содержит информацию о первой ячейке этого списка. Когда
требуется слово для формирования дополнительной структуры списка, берется первое слово
списка свободной памяти, а код в регистре FREE заменяется на информацию о втором слове
списка свободной памяти. Не требуется никаких программных средств для того, чтобы
пользователь программировал возврат ячеек в CAR-.
Любая ячейка, не достижимая таким образом, недоступна для программы и не активна, поэтому
ее содержимое не представляет интереса. Неактивные, то есть недоступные программе ячейки
восстанавливаются CAR-, метится установлением отрицательного
знака. Где бы ни выявилось отрицательное слово в цепи во время процесса пометки,
Иногда структуры списка указывают на полные слова, такие как
В этом случае проблемы повторного использования памяти решаются расположением полных слов
в зарезервированной области памяти, называемой областью полных слов. Мусорщик должен прекращать
прослеживание, как только покидает
Такая реализация экономична в отношении памяти, но она имеет ряд неприятных следствий:
непредсказуемые длинноты (время работы) при поиске очередной порции ячеек и "перегрев системы", если такие
порции слишком малы для продолжения счета. По мере роста производительности оборудования
разработаны простые и не столь обременительные алгоритмы повторного использования памяти на
базе параллельных процессов и профилактического копирования активных структур данных в
дополнительные
В качестве примера повышения гибкости определений приведено упрощенное определение
Ради
"(ASSOC e al )".
Определения функций хранятся в ассоциативном списке, как и значения переменных.
Функция SUBR — вызывает примитивы, реализованные другими, обычно низкоуровневыми,
средствами. ERROR — выдает сообщения об ошибках и сведения о контексте вычислений,
способствующие поиску источника ошибки. Уточнена работа с
(DEFUN EVAL (e al )
(COND
((EQ e NIL ) NIL )
((ATOM e )((LAMBDA (v )
(COND (v (CDR v ) )
(T (ERROR 'undefvalue )) )
) (ASSOC e al ) )
)
((EQ (CAR e) 'QUOTE ) (CAR (CDR e )) )
((EQ (CAR e) 'FUNCTION )
(LIST 'FUNARG (CADR fn ) al ) )
((EQ (CAR e) 'COND ) (EVCON (CDR e ) al ) )
(T (apply (CAR e)(evlis (CDR e) al ) al ) )
) )
(DEFUN APPLY (fn args al )
(COND
((EQ e NIL ) NIL )
((ATOM fn )
(COND
((MEMBER fn '(CAR CDR CONS ATOM EQ ))
(SUBR fn agrs al ))
(T (APPLY (EVAL fn al ) args al ))
) )
((EQ (CAR fn ) 'LABEL )
(APPLY (CADDR fn )
args
(CONS (CONS (CADR fn )(CADDR fn ))
al ) ) )
((EQ (CAR fn ) 'FUNARG )
(APPLY (CDR fn ) args (CADDR fn)) )
((EQ (CAR fn ) 'LAMBDA )
(EVAL (CADDR fn )
(APPEND (PAIR (CADR fn ) args ) al ))
(T (APPLY (EVAL fn al ) args al ))
) )
Определения ASSOC, APPEND, PAIR, LIST — стандартны.
Примерно то же самое обеспечивают EVAL-P и APPLY-P, рассчитанные на использование списков
свойств атома для хранения CATEGORY
указывает в списке свойств атома на правило интерпретации функций, относящихся к отдельной
категории, — на частный метод построения представления функции. Функция VALUE реализует
методы поиска текущего значения переменной в зависимости от контекста и свойств атомов.
(DEFUN EVAL-P (E C)
(COND ((ATOM E) (VALUE E C))
((ATOM (CAR E))(COND ((GET (CAR E) 'CATEGORY)
((GET (CAR E) 'CATEGORY) (CDR E) C) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
))
(DEFUN APPLY-P (F ARGS C)
(COND ((ATOM F)(APPLY-P (FUNCTION F C) ARGS C))
((ATOM (CAR F))(COND ((GET (CAR F) 'MACRO)
(APPLY-P ((GET (CAR F) 'MACRO)
(CDR F) C) ARGS C))
(T (APPLY-P (EVAL F E) ARGS C))
) )
(T (APPLY-P (EVAL F E) ARGS C))
))
Или то же самое с вынесением общих
(DEFUN EVAL-P (E C)
(COND ((ATOM E) (VALUE E C))
((ATOM (CAR E))
((LAMBDA (V) (COND (V (V(CDR E) C) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
)) (GET (CAR E) 'CATEGORY) ) )
(T (APPLY-P (CAR E)(EVLIS (CDR E) C) C))
))
(DEFUN APPLY-P (F ARGS C)
(COND ((ATOM F)(APPLY-P (FUNCTION F C) ARGS C))
((ATOM (CAR F))
((LAMBDA (V) (COND (V (APPLY-P (V (CDR F)
C) ARGS C))
(T (APPLY-P (EVAL F E) ARGS C))
))(GET (CAR F) 'MACRO) ))
(T (APPLY-P (EVAL F E) ARGS C))
))
Расширение системы программирования при таком определении интерпретации осуществляется простым введением/удалением соответствующих свойств атомов и функций.
Полученная схема интерпретации допускает разнообразные OPTIONAL, KEY и REST соответственно, размещаемой перед параметрами в LAMBDA списке формальных
аргументов. При этом серийный параметр должен быть последним в списке.
(DEFUN FUNCALL (FN REST AGRS) (APPLY FN ARGS))
Необязательный параметр может иметь начальное значение, устанавливаемое по умолчанию,
т.е. если этот параметр не задан при вызове функции. При отсутствии начального значения
его роль играет .
(DEFUN EX-OPT (space OPTIONAL dot (line 'x)) (LIST space 'of dot 'and- line)) (EX-OPT 'picture) (EX-OPT 'picture 'circle) (EX-OPT 'picture 'circle 'bars)
.
(DEFUN KEYLIST (A KEY X Y Z) (LIST A X Y Z))
(KEYLIST 1 :Y 2) ;= (1 NIL 2 NIL)
(DEFUN LENGTH (L OPTIONAL (V 0))
(COND ((NULL L) V)
(T (+ 1 (LENGTH (CDR L))))
) )
((LENGTH '(1 2) 3) ; = 5
(DEFUN REVERSE (L OPTIONAL (M NIL))
(COND ((NULL L) M)
(T (REVERSE (CDR L) (CONS (CAR L) M) ))
) )
(REVERSE '(1 2 3)) ; = (3 2 1)
(REVERSE '(1 2 3) '(5 6)) ;= (3 2 1 5 6)
Такой подход к работе параметрами часто освобождает от необходимости во вспомогательных функциях,
что упрощает и определение EVAL от обязательности упоминания а-списка. Если воспользоваться сводимостью
( при отсутствии истиного предиката и кое-где использовать отображения, то определение становится совсем компактным.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.