На этом шаге мы введем понятие функций-компараторов.
Функции-компараторы - это функции, используемые для сравнения обьектов данных muLISP. Все они требуют двух или более аргументов и, за исключением функции MEMBER, возвращают значение Т или NIL, т.е. являются предикатами.
Проверяет, находятся ли объекты в одной и той же области памяти. | |
Ппроверяет тождественность двух S-выражений. | |
Проверяет, входит ли данный объект в список. | |
Проверяет, какой из числовых аргументов меньше. | |
Проверяет, какой из числовых аргументов больше. | |
Проверяет порядок следования аргументов. |
1. Функция EQ. Предикат EQ определяет, представлены ли два объекта
языка LISP в памяти компьютера физически одной и той же структурой, т.е.
находятся ли в одном и том же месте памяти. Например:
$ (EQ 5 5) $ (EQ A A)
T T
Так как EQ определен лишь для атомов, то для сравнения двух
выражений, прежде всего надо определить, являются ли они атомами. Если хотя
бы один из аргументов является списком, то предикат EQ нельзя использовать для логического
сравнения. Например:
$ (EQ (1 2 3) (1 2 3))
NIL
В начало таблицы
2. Функция EQUAL. Предикат EQUAL проверяет тождественность двух S-выражений
(их логическую эквививалентность). Например:
$ (EQUAL (1 2 3) (1 2 3))
T
Предикат EQUAL является обобщением функции EQ: он применяется к произвольным
списковым структурам. Используйте его в тех случаях, когда нет уверенности в
типе сравниваемых объектов или в корректности использования предиката EQ.
В начало таблицы
3. Функция MEMBER. Синтаксис функции таков:
(MEMBER OBJECT LIST)
Предикат MEMBER проверяет, входит ли данный объект OBJECT в список
LIST. При этом недостаточно, чтобы первый аргумент был где-то "похоронен"
во втором аргументе: требуется, чтобы это был элемент верхнего уровня второго аргумента.
Например:
$ (MEMBER A ((A B) (C D)))
NIL
Заметим, что функции EQ, EQUAL, MEMBER иногда называют примитивными
функциями сопоставления с образцом.
В начало таблицы
4. Функция LESSP. Предикат LESSP проверяет для числовых аргументов какой из
них меньше.
В начало таблицы
5. Функция GREATERP. Предикат GREATERP проверяет для числовых аргументов какой
из них больше.
В начало таблицы
6. Функция ORDERP. Предикат ORDERP имеет два аргумента (оба могут быть либо атомами, либо числами, либо точечными парами). Предикат возвращает T, если первый аргумент "располагается перед" вторым аргументом, иначе функция возвращает NIL.
При этом учтите, что числа "располагаются перед" атомами; они в свою очередь располагаются
перед точечными парами. Два числа располагаются в порядке возрастания. Два атома
"располагаются" согласно результату сравнения их адресов в физической памяти
(т.е. согласно порядку их ввода). Аналогично располагаются и две точечные пары.
Например:
$ (ORDERP 5 9) $ (ORDERP DOG CAT)
T T
$ (ORDERP DOG 5) $ (ORDERP CAT DOG)
NIL NIL
Функция ORDERP обеспечивает оптимальное "хронологическое" расположение атомов при написании программ сортировки.
В начало таблицы
В версии muLISP85 существуют еще несколько функций-компараторов: EQL, MEMBER-IF, =, /=, <, >, <=, >=, MISMATCH. Остановимся на них более подробно.
Проверка на идентичность двух объектов. | |
Проверка на идентичность двух объектов. | |
Проверка на идентичность двух объектов. | |
Поиск элемента в списке. | |
Попарная проверка на равенство аргументов. | |
Попарная проверка на неравенство аргументов. | |
Попарная проверка на возрастание аргументов. | |
Попарная проверка на убывание аргументов. | |
Попарная проверка на невозрастание аргументов. | |
Попарная проверка на неубывание аргументов. | |
Сравнение элементов списка. |
1. Если OBJECT1 идентичен OBJECT2, то функция (EQ OBJECT1 OBJECT2) возвращает Т, иначе - NIL.
Функция (NEQ OBJECT1 OBJECT2) эквивалентна функции (NOT (EQ OBJECT1 OBJECT2)).
Функция EQ проверяет на идентичность два своих аргумента (указывают ли она на одинаковых обьекта данных в памяти).
Т.к. символы и малые целые числа (т.е. целые числа, меньше
65536 по абсолютной величине) определяются уникально, то функция EQ
является хорошим способом определения, являются ли два символа или два малых целых числа равными друг другу.
Например:
$ (EQ 'Alice 'Alice) $ (EQ FOO BAR)
T T
$ (SETQ FOO '(A B C)) $ (EQ 7 (+ 3 4))
(A B C) T
$ (EQ FOO '(A B C)) $ (EQ 100000 100000)
NIL NIL
$ (SETQ BAR FOO)
(A B C)
Приведем код функции:
(DEFUN EQ (OBJ1 OBJ2)
(= (LOCATION OBJ1) (LOCATION OBJ2))
)
В начало таблицы
2. Если OBJECT1 идентичен OBJECT2 или если оба аргумента являются числами с одинаковыми значениями, то функция (EQL OBJECT1 OBJECT2) возвращает Т, иначе - NIL.
Функция (NEQL OBJECT1 OBJECT2) эквивалентна функции (NOT (EQL OBJECT1 OBJECT2)).
Т.к. большие целые числа (целые числа, большие 65536 по абсолютной
величине) и дробные числа не определяются уникально, то функция EQL по сравнению
с функцией EQ может быть гораздо эффективнее при определении эквивалентности
двух чисел. Аргументы-неатомы являются эквивалентными тогда и только тогда,
когда они указывают на одинаковые точечные пары в памяти. Например:
$ (EQL 'Alice 'Alice) $ (EQL 100000 100000)
T T
$ (EQL 7 (+ 3 4)) $ (EQL '(A B) '(A B))
T NIL
Приведем код функции:
(DEFUN EQL (OBJ1 OBJ2)
( (AND (NUMBERP OBJ1) (NUMBERP OBJ2))
(= OBJ1 OBJ2) )
(= (LOCATION OBJ1) (LOCATION OBJ2))
)
В начало таблицы
3. Если OBJECT1 эквивалентен OBJECT2, то функция (EQUAL OBJECT1 OBJECT2) возвращает Т, иначе - NIL. Функция EQUAL проверяет на эквивалентность два своих аргумента.
Если один или оба аргумента являются атомами, то функция EQUAL действует аналогично функции EQL.
Два аргумента-неатома находятся в отношении EQUAL, если они являются изоморфными
структурами данных: и CAR-ветви, и CDR-ветви есть EQUAL. Две
EQUAL-структуры данных при печати изображаются одинаково. Т.к. EQL работает
быстрее, эту функцию лучше использовать вместо EQUAL там, где известно, что
по крайней мере один из аргументов является атомом. Например:
$ (EQUAL 'A 'A)
T
$ (EQUAL '(A B C) '(A B C))
T
$ (EQUAL '(A B C) '(C B A))
NIL
Приведем код функции:
(DEFUN EQUAL (OBJ1 OBJ2)
( (ATOM OBJ1) (EQL OBJ1 OBJ2) )
( (ATOM OBJ2) NIL )
( (EQUAL (CAR OBJ1) (CDR OBJ2))
(EQUAL (CDR OBJ1) (CDR OBJ2)) )
)
В начало таблицы
4. Функция (MEMBER OBJECT LIST TEST) выполняет линейный поиск в LIST элемента, для которого признак сравнения с OBJECT по тесту TEST не равен NIL. Если TEST-аргумент есть NIL или не задан, то функция MEMBER использует EQL-тест.
Функция (MEMBER-IF TEST LIST) выполняет поиск в списке LIST
элемента, для которого признак проверки по тесту TEST есть не NIL.
Для обеих функций, если элемент, удовлетворяющий тесту TEST, найден, выдается
хвост списка LIST, начиная с данного элемента. Иначе возвращается NIL.
Например:
$ (MEMBER 'A '(B C D))
NIL
$ (MEMBER 'A '(B A D))
(A D)
$ (MEMBER-IF 'NUMBERP '(A B 3 C (-7)))
(3 C (-7))
$ (MEMBER-IF 'MINUSP '(A B 3 C (-7)))
NIL
Код функции таков:
(DEFUN MEMBER (OBJ LST TEST)
( (ATOM LST) NIL)
( ( (NULL TEST) (SETQ TEST 'EQL) )
( (FUNCALL TEST OBJ (CAR LST)) LST )
(MEMBER OBJ (CDR LST) TEST)
)
В начало таблицы
5. Если N1 равно N2, N2 равно N3,..., Nm-1
равно Nm, то функция (= N1 N2 ... Nm) возвращает Т, иначе -
NIL. Функция вызывает прерывание "Нечисловой аргумент", если какой-либо
аргумент не является числом. Например:
$ (= 5 9) $ (= 3 3.0)
NIL T
$ (= 4 4 -7) $ (= 0.75 6/8)
NIL T
В начало таблицы
6. Если N1 не равно N2, N2 не равно N3,...,Nm-1
не равно Nm, то функция (/= N1 N2 ... Nm) возвращает Т,
иначе - NIL. Например:
$ (/= 5 9) $ (/= 3 3.0)
T NIL
$ (/= 4 4 -7) $ (/= 0.75 6/8)
NIL NIL
Отметим, что если функция возвращает Т, то это означает, что нет ни одной
пары смежных равных аргументов. Однако это может быть и в том случае, когда два
аргумента равны, но не являются смежными. Например:
$ (/= 6 -2 6)
T
Если какой-либо аргумент не является числом, возникает прерывание по ошибке "Нечисловой аргумент".
Приведем реализацию функции:
(DEFUN /= LST
( (NULL LST) )
( (NULL (CDR LST)) )
( (AND (NUMBER (CAR LST)) (NUMBER (CADR LST)))
((= (CAR LST) (CADR LST)) NIL)
(APPLY '/= (CDR LST)) )
((BREAK (LIST '/= (CAR LST) (CADR LST))
'Nonnumeric Argument") NIL)
(APPLY '/= (CDR LST))
)
В начало таблицы
7. Если N1<N2, N2<N3,..., Nm-1<Nm, то функция (< N1 N2 ... Nm)
возвращает Т, иначе - NIL. Например:
$ (< 5 9) $ (< 3 3.0)
T NIL
$ (< 4 -7) $ (< 3/5 2/3)
NIL T
Если какой-либо аргумент не является числом, то возникает прерывание по ошибке "Нечисловой аргумент".
Функцию удобно использовать в том случае, когда нужно определить, лежит ли число
внутри данного интервала; при этом она вызывается с тремя аргументами: числом и
границами интервала. Например, ниже показано, как определить, является ли значение
CHAR:
числом: (< 47 (ASCII CHAR) 58)
прописной буквой: (< 64 (ASCII CHAR) 91)
строчной буквой: (< 96 (ASCII CHAR) 123)
В начало таблицы
8. Если N1>N2, N2>N3,..., Nm-1>Nm, то функция (gt N1 N2 ... Nm)
возвращает Т, иначе - NIL. Например:
Например:
$ (> 5 9) $ (> 3 3.0)
NIL NIL
$ (> 4 -7) $ (> 3/5 2/3)
T NIL
Если какой-либо аргумент не является числом, то возникает прерывание по ошибке "Нечисловой аргумент".
В начало таблицы
9. Если N1<=N2, N2<=N3,..., Nm-1<=Nm, то функция (<= N1 N2 ... Nm)
возвращает Т, иначе - NIL. Например:
$ (<= 5 9) $ (<= 3 3.0)
T T
$ (<= 4 -7) $ (<= 3/5 2/3)
NIL T
Если какой-либо аргумент не является числом, то возникает прерывание по ошибке "Нечисловой аргумент".
Приведем код функции:
(DEFUN <= LST
((NULL LST))
((NULL (CDR LST)))
((AND (NUMBERP (CAR LST)) (NUMBERP (CADR LST)))
((> (CAR LST) (CADR LST)) NIL)
(APPLY '<= (CDR LST)) )
((BREAK (LIST '<= (CAR LST) (CADR LST))
'"Nonnumeric Argument")
(APPLY '<= (CDR LST)) )
)
В начало таблицы
10. Если N1>=N2, N2>=N3,..., Nm-1>=Nm, то функция (>= N1 N2 ... Nm)
возвращает Т, иначе - NIL. Например:
$ (>= 5 9) $ (>= 3 3.0)
NIL T
$ (>= 4 -7) $ (>= 3/5 2/3)
T NIL
Данная функция генерирует прерывание по ошибке "Нечисловой аргумент", если какой-либо аргумент не является числом.
В начало таблицы
11. Функция (MISMATCH LIST1 LIST2 TEST) сравнивает элементы списков LIST1 и LIST2, используя двухэлементный предикат TEST, до тех пор, пока не встретится несоответствие (т.е. пока предикат не вернет NIL) или пока не будет достигнут конец одного или обоих списков. Если TEST есть NIL или не задан, то функция MISMATCH использует EQL-тест.
Если списки имеют равную длину и несоответствие не найдено, то функция возвращает NIL.
Если списки имеют неодинаковую длину, а несоответствие не находится, то функция
возвращает длину более короткого списка. В противном случае функция возвращает порядковый
номер, начиная с нулевого, первой пары элементов списков, которые не соответствуют
друг другу. Например:
$ (MISMATCH '(A B C D E) '(A B C D E))
2
$ (MISMATCH '(5 -4 6 2 ) '(7 -3 9 8) '<)
NIL
В начало таблицы
На следующем шаге мы начнем изучать функции, используемые для работы со списками.