Lisp. Базовые Функции

advertisement
Функции
Программирование при
помощи отображений
Функциональные отношения и
базовые функции Lisp
Eugeny L Yakimovitch http://desk.by/~ewger 2008
Понятие функции
В математике функция отображает одно множество в другое.
Записывается: Y = F (x)
Для х из множества определения (Domain) ставится в
соответствие Y из множества значений (range) функции F.
Можно записать:
• У функции может быть любое количество
аргументов,
в том числе их может не быть совсем.
• Функция без аргументов имеет постоянное
значение.
Примеры функций:
abs( -3 ) --> 3 абсолютная величина.
+ ( 2 , 3 ) --> 5 сложение
union ( ( a , b ), ( c , b ) ) --> ( a , b , c ) объединение множеств.
количество_букв ( слово ) --> 5
Обобщение функции
Функция в общем случае
задает отображение из
нескольких множеств в
множество значений.
F ( x, y)  z
F : A B  C
Это функция двух аргументов:
первый х принадлежит А, второй у
принадлежит В, значение z
принадлежит С. В этом случае
говорят, что аргументы и значение
имеют разные типы.
Пример отношения для
аргументов различных типов
F : A B  C
Январь
1
1 января
1{1..31}
Январь

{январь, февраль, .., декабрь }
Иерархия вызовов
В какой последовательности будет
вычислена функция (+ 1 2) :
А) (+ (+ 1 2) 3)
B) (+ 3 (+ 1 2))
?
Иерархия вызовов
1)
2)
3)
4)
5)
6)
7)
8)
9)
10)
11)
12)
13)
14)
15)
16)
17)
CL-USER> (trace +)
WARNING: TRACE: redefining function + in top-level, was defined in C
;; Tracing function +.
(+)
CL-USER> (+ (+ 1 2) 3)
1. Trace: (+ '1 '2)
1. Trace: + ==> 3
1. Trace: (+ '3 '3)
Правило: Первый вызов «изнутри»,
1. Trace: + ==> 6
т.е. первым выполняется самый
6
CL-USER> (+ 3 (+ 1 2)) глубокий (удаленный от вершины)
1. Trace: (+ '1 '2)
лист дерева s-выражения.
1. Trace: + ==> 3
1. Trace: (+ '3 '3)
1. Trace: + ==> 6
6
CL-USER>
Базовые функции
В Лиспе для обработки списков, т.е.
для разбора, анализа и построения
списков существуют базовые функции.
Они образуют систему аксиом языка, к
которым сводятся символьные
вычисления.
В этом смысле их можно сравнить с
основными арифметическими
операциями. Простота базовых функций
и их малое число - одно из достоинств
Лиспа.
Базовые функции

Функции для атомов и пар:
cons

cdr
eq
atom
Объявление и управление:
cond

car
lambda
define
eval
quote
Пример
(lambda (x) (cond ((atom x) x) (T (cons ‘A x))))
function f(x) = if atom(x) then x else cons(“A”,x)

Функции с побочным эффектом
rplaca
rplacd
Блокировка QUOTE
В некоторых случаях не требуется вычисления
значений выражений, а требуются само
выражение. Если прямо ввести ( + 2 3 ) , то 5
получится как значение.
Но можно понимать ( + 2 3 ) не как функцию,
а как список. S-выражения, которые не надо
вычислять, помечают для интерпретатора
апострофом " ' " (quote).
QUOTE - специальная функция с одним
аргументом, которая возвращает в
качестве значения этот аргумент.
Примеры использования Quote



'(+23)
(+23)
'y
y
( QUOTE QUOTE )
QUOTE
Примеры использования Quote



Вместо апострофа можно использовать
функцию QUOTE.
> ( quote ( + 2 3 ) )
( + 2 3 )* ( quote y )
y
>'(ab'(cd))
(a b ( quote c d ) )
Апостроф автоматически преобразуется в
QUOTE.
Примеры использования Quote






Перед константами не надо ставить апостроф, так как
число и его значение совпадают.
>' 3.17
3.17
>( + ' 2 3 )
5
>t
T
>'t
T
>' nil
NIL
Eval

Функция EVAL обеспечивает
дополнительный вызов интерпретатора
Лиспа.

При этом вызов может производится
внутри вычисляемого S-выражения.

Функция EVAL позволяет снять
блокировку QUOTE.
Eval
quote и eval действуют во взаимно
противоположенных направлениях и
аннулируют эффект друг друга.

( quote ( + 1 2 ) )
(+12)

( eval ( quote ( + 1 2 ) ) )
3
Eval
EVAL - это универсальная функция Лиспа,
которая может вычислить любое правильно
составленное s-выражение.
 ( setq x ' ( a b c ) )
(abc)
 x
(abc)
 'x
x
 ( eval ' x )
(abc)
Использование символов в
качестве переменных
В начале работы виртуальной машины символы в Лиспе
не имеют значения, т.к. они не проинициализированы.
Значения имеют только константы.






CL-USER> 1.7
1.7
CL-USER> t
T
CL-USER> nil
NIL
Связывание символов со
значениями


Значения символов хранятся в ячейках, закрепленных
за каждым символом.
Если в эту ячейку положить значение, то символ будет
связан (bind) сo значением. В процедурных языках
говорят "будет присвоено значение".
‘Symbol
1.
2.
3.
4.
Value
CL-USER> (set `duck `donald)
DONALD
CL-USER> duck
DONALD
…
Связывание символов со
значениями
Кроме того, для диалекта Common Lisp, справедливо
следующее:


Не оговаривается, что может хранится в ячейке: целое,
атом, список, массив и т.д. В ячейке может хранится что
угодно.
С одним символом может быть связана неограниченное
число ячеек-значений.
Для связывания символов используется три функции:



SET
SETQ
SETF
Функция SET

В качестве результата функции возвращается второй аргумент.
( set 'a 'b ) => b

Связывает символ в первом аргументе, предварительно
вычислив значение первого аргумента. Если первый аргумент
указан без апострофа, то присваивается (вставляется) по
результату вычисления этого аргумента.
( set ‘b `c) => с
( set ‘a `b) => b
(eval a) => c

( set ‘b `c) => с
( set ‘a b) => с
На значение символа можно сослаться записав его без
апострофа.
SETQ и SETF
(SETQ a ‘b) эквивалентно (SET `a ‘b)
Буква Q означает блокировку и значение первого
аргумента не вычисляется
В ранних версиях диалектов Lisp функция SETF и
обобщенные переменные не были доступны. И роль
функции присваивания выполняла SETQ.
Современная реализация использует макрос SETF для
всех видов присваиваний, и SETQ считается атавизмом.
Но если внимательно посмотреть на работу отладчика,
можно увидеть, что все SETF присваивания будут
заменены на SETQ.
CONS
Функция CONS создает точечную
пару, конс или просто пару.
Конс строит новый список из своих
аргументов:
S-Выражение
CONS
Список
Список
Примеры для CONS











CL-USER> (cons `a `(b c))
(A B C)
CL-USER> (cons '( a b ) '( ( a b ) ) )
((A B) (A B))
CL-USER> (cons '(+ 1 2 ) '(+ 3 4 ) )
((+12)+34)
CL-USER> ( cons ' a nil )
( a ) ; элемент превратился в список
CL-USER> `(C . C) ; пример точечной пары
(C . C)
CL-USER> (CONS A B) ; если (setq a `c) (setq b `c)
(C . C)
История возникновение CAR и CDR


В первые Lisp был реализован на машине IBM 704 (конец 50х).
В архитектура 704 была специальная поддержка разбиения
36-битного машинного слова на четыре части, «адрес»(15
бит), «декремент» (15), «префикс» (3 бита) и «метка» (3
бита).
Address


Decrement
Prefix
Tag
Префиксные курсоры Lisp включали в себя функции car
("Contents of the Address part of Register number"), cdr, cpr и
ctr, каждая из которых выбирала физический адрес аргументы,
загружала соответствующее слово из памяти в процессор, и
извлекало нужные биты. А функция cons собирала отдельные
значения вместе в один список, который легко
трансформировался обратно в машинное слово.
Современная реализация языка поддерживает более понятные
аналоги этих слов first и rest.
Функция CAR


Возвращает голову списка или
ключевой (первый) элемент
точечной пары (конса).
(car `(a b c d)) => A
Первый элемент списка – голова
(head).
Функция CDR


Возвращает хвост списка или
второй элемент точечной пары
(конса).
(cdr `(a b c d)) => (B C D)
Список без головного элемента –
хвост (tail).
Сравнение CONS, CAR, CDR
ТИП
Записывает Возвращает
изменения РЕЗУЛЬТАТ
в
CAR
Селектор
Список
S-Выражение
CDR
Селектор
Список
Список
CONS
Конструктор
S-Выражение Список
Сравнение CONS, CAR, CDR


Список, разбитый с помощью функции CAR и
CDR на голову и хвост, можно восстановить
функцией CONS.
Селекторы CAR и CDR являются обратными для
конструктора CONS .
CAR
(HT)
CONS
CDR
(HT)
Вложенные CAR и CDR










CL-USER>
A
CL-USER>
B
CL-USER>
C
CL-USER>
C
CL-USER>
C
(first `(a b c d e ))
(second `(a b c d e ))
(third `(a b c d e ))
(caddr `(a b c d e ))
(car (cdr (cdr `(a b c d e ))))
Функция номера элемента NTH



(NTH 5 `(1 2 3 4 5 6))
5
Nth для номера 0 эквивалентно
функции car.
Функция LIST
Функция LIST создает и
возвращает список из символьных
выражений (списков или атомов).
(list s-e1 s-e2 s-e3 .. )
Выполняется для любого числа
аргументов.
Функция LENGTH



Возвращает число элементов
списка верхнего уровня или длину
списка.
CL-USER> (Length `(1 (2 3) 4))
3
Арифметика




(+ x1 x2 ... xn) возвращает x1 +
x2 + x3 + ... + xn.
(- x1 x2 ... xn) возвращает x1 - x2
- x3 - ... - xn.
(* y1 y2 ... yn) возвращает y1 *
y2 * y3 * ... * yn.
(/ x1 x2 ... xn) возвращает
x1/x2/... /xn.
Инкремент и декремент
(1+ x)
 (1- x)

Примечание: Здесь знаки “1+” образуют один символ
Степень и логарифм

Функция логарифм имеет следующий прототип (log arg )
и (log arg base)
>(log 2.7)
0.9932518

Хотя для извлечения корня существует функция SQRT,
эту операцию всегда можно выполнить через экспоненту
вызывая функции EXP и EXPT.
> (expt 2 1/2)
1.4142135
>(log (expt 2 8) 2)
8
Задачи
Напишите решения в виде коротких функций,
которые будут возвращать n-ый элемент числовой
последовательности заданной по одному из правил:
a) a(n+1) = a(n) + (n+1);
b) a(n+1) = a(n) * (n+1);
c) f(0)=1; f(1)=1; f(n+2)=f(n)+f(n+1);
d[1]) A(m,n)=
n+1
| m=0;
A(m-1,1)
| m>0, n=0;
A(m-1, A(m,n-1)) | m>0, n>0
При решении считать n  Z . Проверить способы
получения последовательностей используя итерации,
простую рекурсию, хвостовую рекурсию.
[1] Не примитивно рекурсивная функция Аккермана.
Download