Функциональный стиль программирования сложился в практике решения задач
Методы функционального программирования основаны на формальном математическом языке
представления и
Такое определение будет приведено в шестой лекции, а сейчас необходимо освоить технические
приемы
Функциональное программирование отличается от большинства подходов к программированию тремя важными принципами:
Важная особенность функционального программирования состоит в том, что описание способов обработки
Система функционального программирования допускает, что программа может интерпретировать и/или компилировать программы, представленные в виде
Не все языки функционального программирования в полной мере допускают эту возможность, но для
Наиболее очевидные следствия из выбранных принципов:
Функциональное программирование активно применяется для генерации программ и выполнения динамически конструируемых прототипов программ, а также для систем, применяемых в областях с низкой
Любые
A ATOM ВотВесьмаДлинныйАтомНоЕслиНадоТоАтомМожетБытьЕщеДлинннее Ф4длш139к131б
Одинаково выглядящие атомы не различимы по своим свойствам, хотя проявления этих свойств могут быть обусловлены контекстом использования атомов. Термин
CONS (от слова CAR и CDR, соответственно. (В других языках функционального программирования используются векторы, кортежи, последовательности, потоки, множества, сети и другие структуры данных, обладающие достаточной гибкостью, т.е. способностью к организации единого доступа к любому числу элементов произвольного типа.)
CONS =>> [CAR | CDR]
Бинарный узел, содержащий пару ATOM и NIL, рассматривается как одноэлементный список:
(ATOM) = [ ATOM | NIL ]
Если вместо ATOM рекурсивно подставлять произвольные NIL — произвольные списки, затем вместо ATOM — построенные списки и так далее, то мы получим множество всех возможных списков. NIL играет роль
ATOM (A B) (A B C D E F G H I J K L M N O P R S T U V W X Y Z) (C (A B)) ((A B) C) ((A B) (D C)) ((A B)(D(C E)))
Любой CONS, и любая его часть может быть выделена с помощью подходящей композиции CAR-CDR.
Функция CONS строит
Функция CAR обеспечивает доступ к первому элементу CDR — к укороченному на один элемент списку — его "хвосту", т.е. к тому, что остается после удаления головы.
Функция ATOM позволяет различать составные и атомарные объекты: на
Функция EQ выполняет проверку атомарных объектов на равенство.
NIL. (Во многих языках программирования используется 0 – 1 или идентификаторы True — False и др.)
Если требуется явно изобразить T (true) как стандартное представление, но роль такого значения может выполнить любой, отличный от
Бинарный узел, содержащий пару ATOM1 и ATOM2, можно представить в виде
( ATOM1 . ATOM2 )
| Функциия | Аргументы | Результат |
|---|---|---|
| Конструирование структур данных | ||
CONS |
A и NIL |
(A ) |
CONS |
(A B) и NIL |
((A B) ) |
CONS |
A и (B) |
(A B) |
CONS |
(Результат предыдущего CONS ) и (C) |
((A B) C) |
CONS |
A и (B C) |
(A B C) |
| Доступ к компонентам структуры данных: | ||
| Слева | ||
CAR |
(A B C) |
A |
CAR |
(A (B C)) |
A |
CAR |
((A B) C) |
(A B) |
CAR |
A |
не определен |
| Справа | ||
CDR |
(A ) |
NIL |
CDR |
(A B C D) |
(B C D) |
CDR |
(A (B C)) |
((B C)) |
CDR |
((A B) C) |
(C) |
CDR |
A |
не определен |
| Смешанная обработка данных: | ||
CDR |
(A B C) |
(B C) |
CAR |
результат предыдущего CDR |
B |
CAR |
(A C) |
A |
CAR |
результат предыдущего CAR |
не определен |
CONS |
A и (B) |
(A B) |
CAR |
результат предыдущего CONS |
A |
CONS |
A и (B) |
(A B) |
CDR |
результат предыдущего CONS |
(B) |
| Предикаты: | ||
| Атомарность — неделимость | ||
ATOM |
VeryLongStringOfLetters |
T |
CDR |
(A B) |
(B) |
ATOM |
результат предыдущего CDR |
NIL |
ATOM |
NIL |
T |
ATOM |
( ) |
T |
| Равенство | ||
EQ |
A A |
T |
EQ |
A B |
NIL |
EQ |
A (A B) |
NIL |
EQ |
(A B) (A B) |
не определен |
EQ |
NIL и ( ) |
T |
Если вместо ATOM1, ATOM2 рекурсивно подставлять произвольные атомы, затем построенные из них пары и так далее, то получим множество всех возможных
ATOM (A . B) (C . (A . B)) ((A . B) . C) ((A . B) . (D . C)) ((A . B) . (D . (C . E)))
Любое CONS, и любая его часть может быть выделена с помощью CAR-CDR.
Расширение типа данных, допускаемых в качестве второго аргумента CONS, ни в малейшей степени не усложняет реализацию этой функции, равно как и реализацию функций CAR и CDR, зато их описания становятся проще. Функция CONS строит бинарный узел и заполняет его парой объектов, являющихся значениями пары ее аргументов. Первый аргумент размещается в левой части бинарного узла, а второй — в правой. Функция CAR обеспечивает доступ к объектам, расположенным слева от точки, а функция CDR — справа.
| Функция | Аргументы | Результат |
|---|---|---|
| Конструирование структур данных | ||
CONS |
A и B |
(A . B) |
CONS |
(A . B) и C |
((A . B) . C) |
CONS |
A B |
(A . B) |
CONS |
(результат предыдущего CONS ) и C |
((A . B) . C) |
| Доступ к компонентам структуры данных: | ||
| Слева | ||
CAR |
(A . B) |
A |
CAR |
((A . B) . C) |
(A . B) |
| Справа | ||
CDR |
(A . B) |
B |
CDR |
(A . (B . C)) |
(B . C) |
| Смешанная обработка данных: | ||
CONS |
A и B |
(A . B) |
CAR |
результат предыдущего CONS |
A |
CONS |
A и B |
(A . B) |
CDR |
результат предыдущего CONS |
B |
CDR |
(A . (B . C)) |
(B . C) |
CAR |
результат предыдущего CDR |
B |
CDR |
(A . C) |
C |
CAR |
результат предыдущего CDR |
не определен |
CONS |
два произвольных объекта x и y |
(x . y) |
CAR |
результат предыдущего CONS |
исходный объект x (первый аргумент CONS ) |
CONS |
два произвольных объекта x и y |
(x . y) |
CDR |
результат предыдущего CONS |
исходный объект y (второй аргумент CONS ) |
CAR |
произвольный x |
(CAR x) |
CDR |
тот же самый объект x - не атом |
(CDR x) |
CONS |
результаты предыдущих CAR и CDR |
исходный объект x |
| |
||
| Атомарность — неделимость | ||
ATOM |
(A . B) |
NIL - выполняет роль ложного значения |
CDR |
(A . B) |
B |
ATOM |
результат предыдущего CDR |
T |
| Равенство: | ||
EQ |
(A . B) (A . B) |
не определен |
(A B C D E F G H ). В виде NIL, символизирующий завершение
Атом NIL, рассматриваемый как представление (), играет роль ограничителя в любом (A) идентичен (A . NIL). (A1 A2 ... Ak) может быть представлен как
(A1 . (A2 . ( ... . (Ak . NIL) ... ))).
В памяти это фактически одна и та же
Для многошагового доступа к отдельным элементам такой CAR-CDR. CAR и CDR, соответственно, расположенный между "c" и "r". Указанные таким способом CAR-CDR исполняются с ближайшего к аргументу шага, т.е. в порядке, обратном записи.
| List- |
Dot- |
|---|---|
(A B C) |
(A . (B . (C . NIL))) |
((A B) C) |
((A . (B . NIL)) . (C . NIL)) |
(A B (C E)) |
(A . (B . ((C . (E . NIL)). NIL))) |
(A) |
(A . NIL) |
((A)) |
((A . NIL) . NIL) |
(A (B . C)) |
(A . ((B . C) . NIL)) |
(()) |
(NIL. NIL) |
Многократные CAR-CDR
|
Вычисляются в порядке, обратном записи: | |
|---|---|---|
Caar |
((A) B C) |
A |
Cadr |
(A B C) |
B — CDR затем CAR |
Caddr |
(A B C) |
C — (дважды CDR ) затем CAR |
Cadadr |
(A (B C) D) |
C — два раза ( CDR затем CAR ) |
Гипотезу об универсальности символьных данных, прежде всего, следует проверить при выборе представления форм, возникающих при написании программы и ее основного конструктива —
1)
X Y n Variablel LongSong
2) Более сложные
(функция аргумент1 аргумент2 ... )
Обычно
Теперь можно записывать
(ATOM NIL) (CONS NIL NIL) ((LAMBDA (Y X) (CONS X Y)) NIL(ATOM NIL)) ;= (T) ((LAMBDA (X Y) (CONS X Y)) NIL(ATOM NIL)) ;= (() . T)
";" - начало строчного комментария.
Последние два примера показывают роль порядка
3)
LABEL (отсутствует в LABEL является ее первый аргумент, который становится объектом другой категории. Он меняет свой статус — теперь это
(LABEL третий ; ; имя новой функции
(LAMBDA (x) ; ; параметры функции
(CAR (CDR (CDR x))) ; тело функции
) )
4)
(функция1 (функция2 аргумент21 аргумент22 ... )
аргумент2 ... )
Этих правил достаточно, чтобы более ясно выписать CAR, CDR, CONS, ATOM, EQ над
(CAR (CONS x y)) ; = x (CDR (CONS x y)) ; = y (ATOM (CONS x y)) ; = NIL (CONS (CAR x) (CDR x)) ; = x - для неатомарных x. (EQ x x) ; = T - если x атом (EQ x y) ; = NIL - если x и y различимы
Любые
5) Традиция при изучении функционального программирования избегать знакомства с явными средствами объявления значений SET.
(SET 'PI 3.1415926)
6) NIL и T
В зависимости от контекста одни и те же объекты могут играть роль QUOTE, предохраняющая свой единственный аргумент от вычисления.
(QUOTE A) ;константа атом A (QUOTE (A B C) ) ;константа список (A B C) (ATOM (QUOTE A)) ;= T — аргумент предиката - атом A (ATOM (QUOTE (A B C))) ; = Nil — аргумент предиката - список (A B C) (ATOM A) ;— значение не определено
Оно зависит от вхождения переменной A, а ее значение зависит от контекста и должно быть определено или задано до попытки выяснить, атом ли это.
Можно сказать, что функция QUOTE выполняет в древовидной QUOTE, пометка и контейнер исчезают, и выражение может обрабатываться по общей схеме. Например: (третий (QUOTE (A B C))) — применение функции "третий" к значению, не требующему вычисления.
7)
(condition), аргументами которой являются двухэлементные
(COND (p1 e1) (p2 e2) ... (pk ek) )
pi - предикаты для выбора ветви,
ei - ветви условного выражения
Каждый pi или ветвь ei может быть любой
Обычное (if или (если может быть представлено с помощью функции следующим образом:
(COND (Predicate Then)(T Else))
Разумеется, можно повышать наглядность подбором геометрии текста:
(COND
(Predicate Then)
(T Else)
)
(COND
((EQ (CAR x) (QUOTE A)) (CONS (QUOTE B) (CDR x)) )
(T x)
)
T представляет тождественную истину. Значение всего x на B в том случае, если (CAR x) совпадает с A
Содержательно функции QUOTE, , LAMBDA образуют базовый комплект средств управления программами и процессами, поддерживающий стиль программирования, идеологически близкий структурному программированию [18].
Такие QUOTE, , LAMBDA существенно отличаются от элементарных функций CAR, CDR, CONS, ATOM, EQ правилом обработки аргументов. Обычные функции получают значения аргументов, предварительно вычисленные системой программирования по формулам фактических параметров функции.
8) Определения могут быть рекурсивными.
На практике такие определения обычно имеют глобальные имена, задаваемые с помощью функции LABEL, которую мы вводим здесь для учебных целей (в системе
(LABEL премьер ;имя локальной функции
(LAMBDA (x) ;определение функции
(COND ((ATOM x) x)
(T (премьер (CAR x)))
) ) )
Новая функция "премьер" выбирает первый x является атомом, то он является результатом, иначе функцию "премьер" следует применить к первому элементу значения x, которое получается в результате вычисления формулы (CAR x). На составных x будет выполняться вторая ветвь, выбираемая по тождественно истинному значению встроенной T.
CAR, после которого из этого S-выражения выделится какой-нибудь атом, следовательно, процесс вычисления функции всегда определен, детерминирован и завершится за конечное число шагов. Можно сказать, что для определенности рекурсивной функции следует формулировать условие ее завершения.
Введенные обозначения достаточны, чтобы проследить за формированием значений и преобразованием форм в
((LABEL премьер
(LAMBDA (x)
(COND ((ATOM x) x)
(T (премьер (CAR x)))
) ) ) ; объявлена локальная функция "премьер"
(QUOTE ((A . B) . C) ) ; дан аргумент локальной функции
) ; завершено выражение с локальной функцией
LABEL вырабатывает представление функции, которое тут же может быть применено к аргументу. При этом LABEL дает ((A . B) . C)).
x = ((A . B) . C))
| Вычисляемая форма | Очередной шаг | Результат и комментарии | |
|---|---|---|---|
| Вход в рекурсию | |||
(премьер
(QUOTE ((A . B) . C))) |
Выбор определения функции и | ( |
|
| Первый шаг рекурсии | |||
| выделение параметров функции | (QUOTE ((A . B) . C)) |
||
(QUOTE ((A . B) . C)) |
Вычисление аргумента функции | x = ((A . B) . C) |
|
( |
Перебор | (ATOM x) |
|
(T (премьер (CAR x))) ) |
предикатов: выбор первого | ||
(ATOM x) |
Вычисление первого предиката | NIL = "ложь", т.к. x — не атом. Переход ко второму предикату |
|
T |
Вычисление второго предиката | T = "истина" — константа. Переход к выделенной ветви |
|
| Второй шаг рекурсии | |||
(премьер (CAR x)) |
выделение параметров функции | (CAR x) |
|
(CAR x) |
Вычисление аргумента функции |
Рекурсивный переход к редуцированному аргументу |
|
( |
Перебор предикатов: выбор первого | (ATOM x) |
|
(ATOM x) |
Вычисление предиката первого | NIL = "ложь", т.к. x — не атом. Переход ко второму предикату |
|
T |
Вычисление второго предиката | T = "истина" — константа. Переход ко второй ветви |
|
| Третий шаг рекурсии | |||
(премьер (CAR x)) |
выделение параметров функции | (CAR x) |
|
(CAR x) |
Вычисление аргумента функции |
Рекурсивный переход к редуцированному аргументу |
|
( |
Перебор предикатов: выбор первого | (ATOM x) |
|
(ATOM x) |
Вычисление первого предиката |
Переход к первой ветви |
|
x |
Вычисление значений переменной |
Значение функции получено и вычисление завершено |
|
| Выход из рекурсии | |||
(LABEL Абс
(LAMBDA (x)
(COND
((< x 0 ) (- x))
(T x)
) ) )
(LABEL Факториал
(LAMBDA (N)
(COND
((= N 0 ) 1 )
(T ( * N (Факториал (- N 1 ))) )
) ) )
Это определение не завершается на отрицательных аргументах. Функция, определенная лишь для некоторых значений аргументов естественной области определения, называется частичной функцией.
(+ 1 2 3 4) = 10
(LABEL НОД
(LAMBDA (x y)
(COND
((< x y) (НОД y x))
((= (остаток y x ) 0 ) x )
(T (НОД (остаток y x) x ))
) ) )
Подробное изложение теории функций, определяемых рекурсивными выражениями, можно найти у многих математиков, например [19].
По мнению Дж. Маккарти, даже математики, включая логиков, термин "функция" используют не вполне аккуратно, применяя его к формулам вида "x + y^2" с уверенностью, что читатель, слушатель или собеседник правильно поймет, о чем идет речь. Автоматическая обработка данных, символизирующих функции, требует более точного различия между функциями и формами их применения. Для этих целей выработана система обозначений, известная как "
"Допустим, F — выражение, представляющее функцию двух целочисленных переменных. Необходима возможность приписывать к представлению функции ее аргументы так, чтобы однозначно понимать, каким будет результат применения функции. Традиционная форма F [3, 4] пригодна для функций, значение которых не зависит от порядка аргументов, например, если речь идет о сумме или произведении чисел: сумма [3, 4] = сумма [4, 3] = 7. Выражение "x + y^2 [3, 4]" не удовлетворяет такому требованию. Из его записи не ясно, 13 или 19 является его значением. Поэтому "x + y^2" лучше называть не функцией, а формой, которую можно превратить в функцию, если дать способ точного определения соответствия между переменными, входящими в форму, и аргументами описываемой функции. Именно это и выполняется с помощью так называемого "
лямбда-конструктора ". Любую форму E можно превратить в функцию, если объявить перечень ееформальных аргументов x1,x2,...,xk в виде лямбда-выражения (LAMBDA (x1 x2 ... xk) E). Аргументы такой функции следует перечислять в том же порядке, в каком они перечислены в лямбда-выражении. Например, (LAMBDA (x y) (x + y^2) ) — может работать как функция двух переменных и (LAMBDA (x y) (x + y^2) ) [3, 4] = 3 + 4^2 = 19, а (LAMBDA (y x) (x + y^2) ) [3, 4] = 4 + 3^2 = 13.
Переменные в лямбда-выражении называются номинальными или связанными, потому что их систематическая замена не меняет смысла функции. Таким образом, (LAMBDA (z t) (z + t^2) ) — это то же самое, что и (LAMBDA (x y) (x + y^2) ). Возможны выражения, в которых не всепеременные связаны. Например, в функции двухпеременных (LAMBDA (z t) (z^N + t^N) )переменная N не связана. Это так называемая "свободная"переменная . Ее можно рассматривать как параметр. Если значение такого параметра не задано до попытки вычислить функцию, то значение функции должно быть не определено".
Соответствие между именем функции и ее определением можно задать с помощью более удобной специальной , первый аргумент которой — имя функции, второй — список ее формальных параметров, третий — собственно тело определения функции. , как и LABEL, является ее первый аргумент, который также становится объектом другой категории, но теперь это
(DEFUN третий ; имя новой функции
(x) ; параметры функции
(CAR (CDR (CDR x ))) ; тело функции
)
Новая функция "третий" действует почти так же, как и ранее приведенное определение, но теперь можно функцию рассматривать как глобальную и обращаться к ней в форме.
(третий (QUOTE (A B C)) ) ; — применение новой функции
Вышеописанные лямбда-обозначения не вполне удобны для именования рекурсивных функций, хотя это возможно. Название функции используется внутри , связывающую название функции и с определяющей формой, и со списком
(DEFUN премьер (x)
(COND ((ATOM x) x)
(T (премьер (CAR x)) )
) )
Собственно механизм связывания пока определен не был. Функция использует лямбда-конструктор, чтобы представление функции получалось более естественно и использовалось как единая конструкция. Фактически LABEL и реализуют аналог
премьер = (LAMBDA (x) (COND ((ATOM x) x)
(T (премьер (CAR x)) ) ))
Роль локального связывания имени и LABEL. Если EF — определение, а NF — его имя, то (LABEL NF EF) — функция, знающая свое имя NF. В форме ( используется x — связанное имя
LABEL более логичен, чем : наличие локального механизма формально пригодно и для реализации , отдавая себе отчет в том, что это нечто вроде строительных лесов, помогающих создать более стройное здание. совмещает работу LABEL и LAMBDA — сразу, как и в большинстве языков программирования, позволяет ввести и название функции, и LABEL строит именованную функцию для ее рекурсивного применения внутри текущего выражения, то запоминает определение имени для
CAR, CDR, CONS, ATOM, EQ, и четыре специальных функции, обеспечивающие управление программами и процессами и конструирование функциональных объектов QUOTE, , LAMBDA, LABEL.
EVAL, позволяющей вычислять значения выражений, представленных в виде списков, —
Формально для перехода к самостоятельным упражнениям нужна несколько большая определенность по механизмам исполнения программ, представленных
Функциональный стиль программирования сложился в практике решения задач
Методы функционального программирования основаны на формальном математическом языке
представления и
Такое определение будет приведено в шестой лекции, а сейчас необходимо освоить технические
приемы
Функциональное программирование отличается от большинства подходов к программированию тремя важными принципами:
Важная особенность функционального программирования состоит в том, что описание способов обработки
Система функционального программирования допускает, что программа может интерпретировать и/или компилировать программы, представленные в виде
Не все языки функционального программирования в полной мере допускают эту возможность, но для
Наиболее очевидные следствия из выбранных принципов:
Функциональное программирование активно применяется для генерации программ и выполнения динамически конструируемых прототипов программ, а также для систем, применяемых в областях с низкой
Любые
A ATOM ВотВесьмаДлинныйАтомНоЕслиНадоТоАтомМожетБытьЕщеДлинннее Ф4длш139к131б
Одинаково выглядящие атомы не различимы по своим свойствам, хотя проявления этих свойств могут быть обусловлены контекстом использования атомов. Термин
CONS (от слова CAR и CDR, соответственно. (В других языках функционального программирования используются векторы, кортежи, последовательности, потоки, множества, сети и другие структуры данных, обладающие достаточной гибкостью, т.е. способностью к организации единого доступа к любому числу элементов произвольного типа.)
CONS =>> [CAR | CDR]
Бинарный узел, содержащий пару ATOM и NIL, рассматривается как одноэлементный список:
(ATOM) = [ ATOM | NIL ]
Если вместо ATOM рекурсивно подставлять произвольные NIL — произвольные списки, затем вместо ATOM — построенные списки и так далее, то мы получим множество всех возможных списков. NIL играет роль
ATOM (A B) (A B C D E F G H I J K L M N O P R S T U V W X Y Z) (C (A B)) ((A B) C) ((A B) (D C)) ((A B)(D(C E)))
Любой CONS, и любая его часть может быть выделена с помощью подходящей композиции CAR-CDR.
Функция CONS строит
Функция CAR обеспечивает доступ к первому элементу CDR — к укороченному на один элемент списку — его "хвосту", т.е. к тому, что остается после удаления головы.
Функция ATOM позволяет различать составные и атомарные объекты: на
Функция EQ выполняет проверку атомарных объектов на равенство.
NIL. (Во многих языках программирования используется 0 – 1 или идентификаторы True — False и др.)
Если требуется явно изобразить T (true) как стандартное представление, но роль такого значения может выполнить любой, отличный от
Бинарный узел, содержащий пару ATOM1 и ATOM2, можно представить в виде
( ATOM1 . ATOM2 )
| Функциия | Аргументы | Результат |
|---|---|---|
| Конструирование структур данных | ||
CONS |
A и NIL |
(A ) |
CONS |
(A B) и NIL |
((A B) ) |
CONS |
A и (B) |
(A B) |
CONS |
(Результат предыдущего CONS ) и (C) |
((A B) C) |
CONS |
A и (B C) |
(A B C) |
| Доступ к компонентам структуры данных: | ||
| Слева | ||
CAR |
(A B C) |
A |
CAR |
(A (B C)) |
A |
CAR |
((A B) C) |
(A B) |
CAR |
A |
не определен |
| Справа | ||
CDR |
(A ) |
NIL |
CDR |
(A B C D) |
(B C D) |
CDR |
(A (B C)) |
((B C)) |
CDR |
((A B) C) |
(C) |
CDR |
A |
не определен |
| Смешанная обработка данных: | ||
CDR |
(A B C) |
(B C) |
CAR |
результат предыдущего CDR |
B |
CAR |
(A C) |
A |
CAR |
результат предыдущего CAR |
не определен |
CONS |
A и (B) |
(A B) |
CAR |
результат предыдущего CONS |
A |
CONS |
A и (B) |
(A B) |
CDR |
результат предыдущего CONS |
(B) |
| Предикаты: | ||
| Атомарность — неделимость | ||
ATOM |
VeryLongStringOfLetters |
T |
CDR |
(A B) |
(B) |
ATOM |
результат предыдущего CDR |
NIL |
ATOM |
NIL |
T |
ATOM |
( ) |
T |
| Равенство | ||
EQ |
A A |
T |
EQ |
A B |
NIL |
EQ |
A (A B) |
NIL |
EQ |
(A B) (A B) |
не определен |
EQ |
NIL и ( ) |
T |
Если вместо ATOM1, ATOM2 рекурсивно подставлять произвольные атомы, затем построенные из них пары и так далее, то получим множество всех возможных
ATOM (A . B) (C . (A . B)) ((A . B) . C) ((A . B) . (D . C)) ((A . B) . (D . (C . E)))
Любое CONS, и любая его часть может быть выделена с помощью CAR-CDR.
Расширение типа данных, допускаемых в качестве второго аргумента CONS, ни в малейшей степени не усложняет реализацию этой функции, равно как и реализацию функций CAR и CDR, зато их описания становятся проще. Функция CONS строит бинарный узел и заполняет его парой объектов, являющихся значениями пары ее аргументов. Первый аргумент размещается в левой части бинарного узла, а второй — в правой. Функция CAR обеспечивает доступ к объектам, расположенным слева от точки, а функция CDR — справа.
| Функция | Аргументы | Результат |
|---|---|---|
| Конструирование структур данных | ||
CONS |
A и B |
(A . B) |
CONS |
(A . B) и C |
((A . B) . C) |
CONS |
A B |
(A . B) |
CONS |
(результат предыдущего CONS ) и C |
((A . B) . C) |
| Доступ к компонентам структуры данных: | ||
| Слева | ||
CAR |
(A . B) |
A |
CAR |
((A . B) . C) |
(A . B) |
| Справа | ||
CDR |
(A . B) |
B |
CDR |
(A . (B . C)) |
(B . C) |
| Смешанная обработка данных: | ||
CONS |
A и B |
(A . B) |
CAR |
результат предыдущего CONS |
A |
CONS |
A и B |
(A . B) |
CDR |
результат предыдущего CONS |
B |
CDR |
(A . (B . C)) |
(B . C) |
CAR |
результат предыдущего CDR |
B |
CDR |
(A . C) |
C |
CAR |
результат предыдущего CDR |
не определен |
CONS |
два произвольных объекта x и y |
(x . y) |
CAR |
результат предыдущего CONS |
исходный объект x (первый аргумент CONS ) |
CONS |
два произвольных объекта x и y |
(x . y) |
CDR |
результат предыдущего CONS |
исходный объект y (второй аргумент CONS ) |
CAR |
произвольный x |
(CAR x) |
CDR |
тот же самый объект x - не атом |
(CDR x) |
CONS |
результаты предыдущих CAR и CDR |
исходный объект x |
| |
||
| Атомарность — неделимость | ||
ATOM |
(A . B) |
NIL - выполняет роль ложного значения |
CDR |
(A . B) |
B |
ATOM |
результат предыдущего CDR |
T |
| Равенство: | ||
EQ |
(A . B) (A . B) |
не определен |
(A B C D E F G H ). В виде NIL, символизирующий завершение
Атом NIL, рассматриваемый как представление (), играет роль ограничителя в любом (A) идентичен (A . NIL). (A1 A2 ... Ak) может быть представлен как
(A1 . (A2 . ( ... . (Ak . NIL) ... ))).
В памяти это фактически одна и та же
Для многошагового доступа к отдельным элементам такой CAR-CDR. CAR и CDR, соответственно, расположенный между "c" и "r". Указанные таким способом CAR-CDR исполняются с ближайшего к аргументу шага, т.е. в порядке, обратном записи.
| List- |
Dot- |
|---|---|
(A B C) |
(A . (B . (C . NIL))) |
((A B) C) |
((A . (B . NIL)) . (C . NIL)) |
(A B (C E)) |
(A . (B . ((C . (E . NIL)). NIL))) |
(A) |
(A . NIL) |
((A)) |
((A . NIL) . NIL) |
(A (B . C)) |
(A . ((B . C) . NIL)) |
(()) |
(NIL. NIL) |
Многократные CAR-CDR
|
Вычисляются в порядке, обратном записи: | |
|---|---|---|
Caar |
((A) B C) |
A |
Cadr |
(A B C) |
B — CDR затем CAR |
Caddr |
(A B C) |
C — (дважды CDR ) затем CAR |
Cadadr |
(A (B C) D) |
C — два раза ( CDR затем CAR ) |
Гипотезу об универсальности символьных данных, прежде всего, следует проверить при выборе представления форм, возникающих при написании программы и ее основного конструктива —
1)
X Y n Variablel LongSong
2) Более сложные
(функция аргумент1 аргумент2 ... )
Обычно
Теперь можно записывать
(ATOM NIL) (CONS NIL NIL) ((LAMBDA (Y X) (CONS X Y)) NIL(ATOM NIL)) ;= (T) ((LAMBDA (X Y) (CONS X Y)) NIL(ATOM NIL)) ;= (() . T)
";" - начало строчного комментария.
Последние два примера показывают роль порядка
3)
LABEL (отсутствует в LABEL является ее первый аргумент, который становится объектом другой категории. Он меняет свой статус — теперь это
(LABEL третий ; ; имя новой функции
(LAMBDA (x) ; ; параметры функции
(CAR (CDR (CDR x))) ; тело функции
) )
4)
(функция1 (функция2 аргумент21 аргумент22 ... )
аргумент2 ... )
Этих правил достаточно, чтобы более ясно выписать CAR, CDR, CONS, ATOM, EQ над
(CAR (CONS x y)) ; = x (CDR (CONS x y)) ; = y (ATOM (CONS x y)) ; = NIL (CONS (CAR x) (CDR x)) ; = x - для неатомарных x. (EQ x x) ; = T - если x атом (EQ x y) ; = NIL - если x и y различимы
Любые
5) Традиция при изучении функционального программирования избегать знакомства с явными средствами объявления значений SET.
(SET 'PI 3.1415926)
6) NIL и T
В зависимости от контекста одни и те же объекты могут играть роль QUOTE, предохраняющая свой единственный аргумент от вычисления.
(QUOTE A) ;константа атом A (QUOTE (A B C) ) ;константа список (A B C) (ATOM (QUOTE A)) ;= T — аргумент предиката - атом A (ATOM (QUOTE (A B C))) ; = Nil — аргумент предиката - список (A B C) (ATOM A) ;— значение не определено
Оно зависит от вхождения переменной A, а ее значение зависит от контекста и должно быть определено или задано до попытки выяснить, атом ли это.
Можно сказать, что функция QUOTE выполняет в древовидной QUOTE, пометка и контейнер исчезают, и выражение может обрабатываться по общей схеме. Например: (третий (QUOTE (A B C))) — применение функции "третий" к значению, не требующему вычисления.
7)
(condition), аргументами которой являются двухэлементные
(COND (p1 e1) (p2 e2) ... (pk ek) )
pi - предикаты для выбора ветви,
ei - ветви условного выражения
Каждый pi или ветвь ei может быть любой
Обычное (if или (если может быть представлено с помощью функции следующим образом:
(COND (Predicate Then)(T Else))
Разумеется, можно повышать наглядность подбором геометрии текста:
(COND
(Predicate Then)
(T Else)
)
(COND
((EQ (CAR x) (QUOTE A)) (CONS (QUOTE B) (CDR x)) )
(T x)
)
T представляет тождественную истину. Значение всего x на B в том случае, если (CAR x) совпадает с A
Содержательно функции QUOTE, , LAMBDA образуют базовый комплект средств управления программами и процессами, поддерживающий стиль программирования, идеологически близкий структурному программированию [18].
Такие QUOTE, , LAMBDA существенно отличаются от элементарных функций CAR, CDR, CONS, ATOM, EQ правилом обработки аргументов. Обычные функции получают значения аргументов, предварительно вычисленные системой программирования по формулам фактических параметров функции.
8) Определения могут быть рекурсивными.
На практике такие определения обычно имеют глобальные имена, задаваемые с помощью функции LABEL, которую мы вводим здесь для учебных целей (в системе
(LABEL премьер ;имя локальной функции
(LAMBDA (x) ;определение функции
(COND ((ATOM x) x)
(T (премьер (CAR x)))
) ) )
Новая функция "премьер" выбирает первый x является атомом, то он является результатом, иначе функцию "премьер" следует применить к первому элементу значения x, которое получается в результате вычисления формулы (CAR x). На составных x будет выполняться вторая ветвь, выбираемая по тождественно истинному значению встроенной T.
CAR, после которого из этого S-выражения выделится какой-нибудь атом, следовательно, процесс вычисления функции всегда определен, детерминирован и завершится за конечное число шагов. Можно сказать, что для определенности рекурсивной функции следует формулировать условие ее завершения.
Введенные обозначения достаточны, чтобы проследить за формированием значений и преобразованием форм в
((LABEL премьер
(LAMBDA (x)
(COND ((ATOM x) x)
(T (премьер (CAR x)))
) ) ) ; объявлена локальная функция "премьер"
(QUOTE ((A . B) . C) ) ; дан аргумент локальной функции
) ; завершено выражение с локальной функцией
LABEL вырабатывает представление функции, которое тут же может быть применено к аргументу. При этом LABEL дает ((A . B) . C)).
x = ((A . B) . C))
| Вычисляемая форма | Очередной шаг | Результат и комментарии | |
|---|---|---|---|
| Вход в рекурсию | |||
(премьер
(QUOTE ((A . B) . C))) |
Выбор определения функции и | ( |
|
| Первый шаг рекурсии | |||
| выделение параметров функции | (QUOTE ((A . B) . C)) |
||
(QUOTE ((A . B) . C)) |
Вычисление аргумента функции | x = ((A . B) . C) |
|
( |
Перебор | (ATOM x) |
|
(T (премьер (CAR x))) ) |
предикатов: выбор первого | ||
(ATOM x) |
Вычисление первого предиката | NIL = "ложь", т.к. x — не атом. Переход ко второму предикату |
|
T |
Вычисление второго предиката | T = "истина" — константа. Переход к выделенной ветви |
|
| Второй шаг рекурсии | |||
(премьер (CAR x)) |
выделение параметров функции | (CAR x) |
|
(CAR x) |
Вычисление аргумента функции |
Рекурсивный переход к редуцированному аргументу |
|
( |
Перебор предикатов: выбор первого | (ATOM x) |
|
(ATOM x) |
Вычисление предиката первого | NIL = "ложь", т.к. x — не атом. Переход ко второму предикату |
|
T |
Вычисление второго предиката | T = "истина" — константа. Переход ко второй ветви |
|
| Третий шаг рекурсии | |||
(премьер (CAR x)) |
выделение параметров функции | (CAR x) |
|
(CAR x) |
Вычисление аргумента функции |
Рекурсивный переход к редуцированному аргументу |
|
( |
Перебор предикатов: выбор первого | (ATOM x) |
|
(ATOM x) |
Вычисление первого предиката |
Переход к первой ветви |
|
x |
Вычисление значений переменной |
Значение функции получено и вычисление завершено |
|
| Выход из рекурсии | |||
(LABEL Абс
(LAMBDA (x)
(COND
((< x 0 ) (- x))
(T x)
) ) )
(LABEL Факториал
(LAMBDA (N)
(COND
((= N 0 ) 1 )
(T ( * N (Факториал (- N 1 ))) )
) ) )
Это определение не завершается на отрицательных аргументах. Функция, определенная лишь для некоторых значений аргументов естественной области определения, называется частичной функцией.
(+ 1 2 3 4) = 10
(LABEL НОД
(LAMBDA (x y)
(COND
((< x y) (НОД y x))
((= (остаток y x ) 0 ) x )
(T (НОД (остаток y x) x ))
) ) )
Подробное изложение теории функций, определяемых рекурсивными выражениями, можно найти у многих математиков, например [19].
По мнению Дж. Маккарти, даже математики, включая логиков, термин "функция" используют не вполне аккуратно, применяя его к формулам вида "x + y^2" с уверенностью, что читатель, слушатель или собеседник правильно поймет, о чем идет речь. Автоматическая обработка данных, символизирующих функции, требует более точного различия между функциями и формами их применения. Для этих целей выработана система обозначений, известная как "
"Допустим, F — выражение, представляющее функцию двух целочисленных переменных. Необходима возможность приписывать к представлению функции ее аргументы так, чтобы однозначно понимать, каким будет результат применения функции. Традиционная форма F [3, 4] пригодна для функций, значение которых не зависит от порядка аргументов, например, если речь идет о сумме или произведении чисел: сумма [3, 4] = сумма [4, 3] = 7. Выражение "x + y^2 [3, 4]" не удовлетворяет такому требованию. Из его записи не ясно, 13 или 19 является его значением. Поэтому "x + y^2" лучше называть не функцией, а формой, которую можно превратить в функцию, если дать способ точного определения соответствия между переменными, входящими в форму, и аргументами описываемой функции. Именно это и выполняется с помощью так называемого "
лямбда-конструктора ". Любую форму E можно превратить в функцию, если объявить перечень ееформальных аргументов x1,x2,...,xk в виде лямбда-выражения (LAMBDA (x1 x2 ... xk) E). Аргументы такой функции следует перечислять в том же порядке, в каком они перечислены в лямбда-выражении. Например, (LAMBDA (x y) (x + y^2) ) — может работать как функция двух переменных и (LAMBDA (x y) (x + y^2) ) [3, 4] = 3 + 4^2 = 19, а (LAMBDA (y x) (x + y^2) ) [3, 4] = 4 + 3^2 = 13.
Переменные в лямбда-выражении называются номинальными или связанными, потому что их систематическая замена не меняет смысла функции. Таким образом, (LAMBDA (z t) (z + t^2) ) — это то же самое, что и (LAMBDA (x y) (x + y^2) ). Возможны выражения, в которых не всепеременные связаны. Например, в функции двухпеременных (LAMBDA (z t) (z^N + t^N) )переменная N не связана. Это так называемая "свободная"переменная . Ее можно рассматривать как параметр. Если значение такого параметра не задано до попытки вычислить функцию, то значение функции должно быть не определено".
Соответствие между именем функции и ее определением можно задать с помощью более удобной специальной , первый аргумент которой — имя функции, второй — список ее формальных параметров, третий — собственно тело определения функции. , как и LABEL, является ее первый аргумент, который также становится объектом другой категории, но теперь это
(DEFUN третий ; имя новой функции
(x) ; параметры функции
(CAR (CDR (CDR x ))) ; тело функции
)
Новая функция "третий" действует почти так же, как и ранее приведенное определение, но теперь можно функцию рассматривать как глобальную и обращаться к ней в форме.
(третий (QUOTE (A B C)) ) ; — применение новой функции
Вышеописанные лямбда-обозначения не вполне удобны для именования рекурсивных функций, хотя это возможно. Название функции используется внутри , связывающую название функции и с определяющей формой, и со списком
(DEFUN премьер (x)
(COND ((ATOM x) x)
(T (премьер (CAR x)) )
) )
Собственно механизм связывания пока определен не был. Функция использует лямбда-конструктор, чтобы представление функции получалось более естественно и использовалось как единая конструкция. Фактически LABEL и реализуют аналог
премьер = (LAMBDA (x) (COND ((ATOM x) x)
(T (премьер (CAR x)) ) ))
Роль локального связывания имени и LABEL. Если EF — определение, а NF — его имя, то (LABEL NF EF) — функция, знающая свое имя NF. В форме ( используется x — связанное имя
LABEL более логичен, чем : наличие локального механизма формально пригодно и для реализации , отдавая себе отчет в том, что это нечто вроде строительных лесов, помогающих создать более стройное здание. совмещает работу LABEL и LAMBDA — сразу, как и в большинстве языков программирования, позволяет ввести и название функции, и LABEL строит именованную функцию для ее рекурсивного применения внутри текущего выражения, то запоминает определение имени для
CAR, CDR, CONS, ATOM, EQ, и четыре специальных функции, обеспечивающие управление программами и процессами и конструирование функциональных объектов QUOTE, , LAMBDA, LABEL.
EVAL, позволяющей вычислять значения выражений, представленных в виде списков, —
Формально для перехода к самостоятельным упражнениям нужна несколько большая определенность по механизмам исполнения программ, представленных
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.