Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Fp_3.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
635.39 Кб
Скачать

3.4 Две функции работы со списками

Как правило – все функции работы со списками рекурсивны.

3.4.1 Например, определим функцию length, (она тоже стандартная) возвращающую количество элементов в списке верхнего уровня.

Здесь рекурсия заключается в суммировании. Пустой список содержит 0 элементов, а любой другой - на 1 больше, чем его хвост.

> (define (length lst)

(if (null? lst) 0 (+ 1 (length (cdr lst)))))

> (length (list 2 3 56 7))

4

> (length '(1 2 (3 4) 5))

4

3.4.2 Аналогично определяется функция sum, вычисляющая сумму всех элементов списка. Если список пуст, она равна 0, иначе - сумме первого элемента и всех остальных.

> (define (sum lst)

(if (null? lst) 0 (+ (car lst) (sum (cdr lst)))))

> (sum ‘(2 3 67))

72

Справедливости ради замети, что мы не проверяем, является ли элемент списка числом. Здесь есть потенциальная ошибка и надо её как-то избегать.

Перейдем к одному из самых замечательных и при этом основных особенностей языка LISP: лямбда-выражениям . (Другое написание: -выражение)

    1. Лямбда-выражения и связывающие формы.

Лямбда-выражения – это способ ввести в S-выражения безликость.

Когда мы определяли функции с помощью define, необходимо было задавать функции имя. Но совершенно очевидно, что бывают случаи, когда функция используется лишь однажды и более она не нужна. Для чего нужно далее помнить её имя? Или используется функция, мнемоника которой, гораздо длиннее по написанию, нежели она сама, например, x+1.

Можно привести и другие доводы в пользу, так называемой, безликости (анонимности). Но самое важное в  исчислении - это мощный, хорошо формализованный математический аппарат. Он, по сути, и явился толчком для появления языка LISP.

Итак, исчисление – это исчисление анонимных функций. Оно дает:

  • Метод представления функций

  • Правило вывода, т.е. правило описывающее получение конечного значения выражения из его формально описанного вида.

Для строгости определения приведем бнф для  нотации

<expr> ::=  <iden>.<expr> | <expr><expr> | (<expr>) | <aexpr>

<aexpr> ::= <const> | <iden> | <aexpr>

<const> ::= произвольная константа

<iden> ::= любой идентификатор

<aexpr> ::= допустимое арифметическое выражение

Примеры правильных  - выражений:

33

(-9)

x.x+1 читается: (заметим, никакого названия у функции нет, она анонимна.)

 - функция

x - от x,

. - которая возвращает

x+1 - выражение x+1 или его значение

x.y.2*(x + y)

читается: функция от x, которая возвращает функцию от y, которая возвращает выражение 2*(x+у) или его значение

Символ, стоящий после символа называется связанной переменной. Другие символы в  выражении называются свободными (не связанными) переменными.

Чтобы получить значение функции аргументы надо связать с конкретными значениями. Если аргументы не связаны, то их значениями будут являться их имена.

Например.

(x.(x + y))3 = 3 + y

Здесь X связывается с 3, а y остаётся свободной

(z.(x + 2*y + z))5 = x + 2*y + 5

Здесь z связывается с 5, остальные переменные оказываются свободными

Процесс упрощения  выражения называется редукцией. Он выражается в изъятии символа соответствующей связанной переменной и подстановкой конкретного значения.

Мы не будем подробно рассматривать эти правила, а только приведем примеры их применения для редукции S-выражений.

Примеры упрощений.

1. (f.(f x)) (y.y) =

Вместо f в тело функции подставляется выражение y.y и поскольку переменная получается связанной, выбрасывается определение функции, т.е. f

= ((y.y) x) =

Теперь можно связать переменную y с её конкретным значением, т.е. x, подставляем в тело функции

= x

2. (x. ( f.f(f x)) (y.(y + 1)) ) 2 =

Видно, что y не может быть связано не с чем, следовательно, должно связываться f с выражением (y.(y + 1))и потом x соответственно с 2.

П равило такое: надо производить самую внутреннюю связку. Значит выражение f(f x)изменится, и получится так:

= (x. ( (y.(y + 1)) ( ( y.(y + 1)) x) ) ) 2 =

Теперь убираем избыточные скобки

= (x. (y.(y + 1)) ( y.(y + 1)) x ) 2 =

Подставляя x, редуцируем самую правую функцию y

= (x. (y.(y + 1)) ( (x + 1)) ) 2 =

Опять убираем избыточные скобки

= (x. (y.(y + 1)) (x + 1) ) 2 =

и редуцируем самую правую функцию y

= (x. ( (x + 1) + 1)) ) 2 =

= (x. ( x + 2 ) ) 2 =

= (2 + 2)

= 4

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]