Урок 6. Предикаты в LISP
Предикаты — это функция, проверяющая, обладают ли аргументы заданным свойством и возвращающая либо T либо NIL. Рассмотрим некоторые предикаты:
- atom — проверяет, является ли аргумент атомом
- listp — проверяет, является ли аргумент списком
- null — проверяет, является ли аргумент пустым списком или NIL
- eq — сравнивает аргументы, возвращает T, если равны и NIL в противном случае
- eql — тоже самое, но для объектов более высокого уровня, чем eq
- equal — еще более хорошее сравнение
- equalp — самое лучшее
С первыми тремя предикатами все понятно, поэтому просто приведем пример их использования:
(atom 1);T
(atom '(1 2));NIL
(listp '1);NIL
(listp '(1 2));T
(null '1);NIL
(null '());T
(null nil);T
Так теперь нужно разобраться с группой «сравнения». Самый первый предикат eq сравнивает ссылки у объектов, т.е он вернет T, только тогда, когда перед нами один и тот же объект:
(eq 1 1);T
(eq 'cybern 'cybern);T
(eq NIL ());T
(eq 1.0 1.0);NIL
(setq x 1)
(setq y 1)
(eq x y);T
(eq x x);T
(setq x '(a b))
(setq y '(a b))
(eq x y);NIL
Таким образом eq смогла сравнить целые числа, NIL и (), строки, но уже не смогла сравнить вещественные числа и значения переменных cложных типов. Понятное дело, что там где справится eq, можно использовать и eql, поэтому мы прогоним eql только на тестах, на которых не справилась eq.
(eql 1.0 1.0);T
(eql 1 1.0);NIL
(setq x '(a b))
(setq y '(a b))
(eql x y);NIL
Функция eql уже смогла сравнить вещественные числа, а в остальном пока что не помогла нам продвинуться вперед. Рассмотрим следующую функцию equal:
(equal 1 1.0);NIL
(setq x '(a b))
(setq y '(a b))
(equal x y);T
Таким образом функция equal может сравнивать объекты одной природы и возвращать правильный результат. Попробуем все таки сравнить объекты разной природы с помощью equalp:
(equalp 1 1.0);T
Таким образом мы можем использовать функция equalp для сравнения объектов даже разной структуры. На этом урок по предикатам закончен, можно переходить к следующему.