ТОП 10:

EQL сравнивает числа одинаковых типов



Более общим, по сравнению с EQ, является предикат EQL, который работает так же, как EQ, но дополнительно позволяет сравнивать однотипные числа (и элементы строк).

 

_(eql 3 3) ; сравниваются два целых числа

T

_(eql 3.0 3.0) ; сравниваются два вещественных числа

T

_(eql 3 3.0) ; не годится для разных типов

NIL

Предикат EQL, как правило, используется во многих встроенных функциях, осуществляющих более сложные операции сравнения. Его использование для сравнения списков – это часто встречающаяся ошибка.

 

 

Предикат = сравнивает числа различных типов

Сложности, возникающие при сравнении чисел, легко преодолимы с помощью предиката =, значением которого является Т в случае равенства чисел независимо от их типов и внешнего вида записи:

 

_(= 3 3.0)

Т

_(= 3.00 0.3Е1)

Т

Обеспечить применение предиката к числовым аргументам может предикат NUMBERP, который истинен для чисел:

 

_(numberp 3e-34)

T

_(numberp t)

NIL

 

 

EQUAL проверяет идентичность записей

Обобщением EQL является предикат EQUAL. Он работает как EQL, но, кроме того, проверяет одинаковость двух списков:

 

_(equal ’ x ’ x)

T

_(equal ’ (x y z) ’ (x y z))

T

_(equal ’ (a b c) ( cons ’ a ’ (b c)))

T

_(equal ’ (nil) ’ ((nil)))

NIL

Принцип работы предиката EQUAL состоит в следующем: если внешняя структура двух лисповских объектов одинакова, то эти объекты между собой равны в смысле EQUAL. Предикат EQUAL также применим к числам и к другим типам данных (например, к строкам). Заметим, что в соответствии со своим принципом работы он не подходит для сравнения разнотипных чисел, так как их внешние представления различаются:

 

_(equal 3.00 3) ; различное внешнее представление

NIL

_(= 3.00 3)

T

EQUALP проверяет наиболее общее логическое равенство

Наиболее общим предикатом, проверяющим в Коммон Лиспе наличие логического равенства, является EQUALP, с помощью которого можно сравнивать произвольные лисповские объекты, будь то числа различных типов, выражения или другие объекты. Этот предикат может потребоваться, когда нет уверенности в типе сравниваемых объектов или в корректности использования других предикатов сравнения.

Недостатком универсальных предикатов и функций типа EQUALP является то, что их применение требует от системы несколько большего объема вычислений, чем использование специализированных предикатов и функций.

 

 

Другие примитивы

Несмотря на то, что обычную обработку списков всегда можно свести к описанным ранее трем базовым функциям (CONS, CAR, CDR) и двум базовым предикатам (АТОМ и EQ), программирование лишь с их использованием было бы очень примитивным и похожим на программирование на внутреннем машинном языке. Поэтому в Лисп-систему включено множество встроенных функций для различных действий и различных ситуаций. Далее мы рассмотрим некоторые такие примитивы.

 

 

NULL проверяет на пустой список

Встроенная функция NULL проверяет, является ли аргумент пустым списком:

 

_(null ’ ())

T

_(null ( cddr ’ (a b c)))

NIL

_(null NIL)

T

_(null T)

NIL

Из последних двух примеров видно, что NULL работает как логическое отрицание, у которого в Лиспе есть и свой, принадлежащий логическим функциям, предикат (NOT x):

 

_(not (null nil))

NIL

Функции NULL и NOT можно выразить через EQ:

 

(NULL x) ó (EQ NIL x)

Вложенные вызовы CAR и CDR можно записывать в сокращенном виде

Комбинируя селекторы CAR и CDR, можно выделить произвольный элемент списка. Например:

 

_(cdr (cdr (car ’ ((a b c) (d e) (f)))))

(C)

Комбинации вызовов CAR и CDR образуют уходящие в глубину списка обращения, и в Лиспе используется для этого более короткая запись: желаемую комбинацию вызовов CAR и CDR можно записать в виде одного вызова функции:

 

(С…R список)

Вместо многоточия записывается нужная комбинация из букв А (для функции CAR) и D (для функции CDR):

 

(cadr x) ó (car (cdr x))

(cddar x) ó (cdr (cdr (car x)))

Например:

 

_(cadr ’ (программировать на Лиспе просто?))

НА

_(caddr ’ ((a b c) (d e) (f)))

(F)

_(cadar (cons ’ (a b) nil))

B

Для функций CAR, CADR, CADDR, CADDDR и т.д. в Коммон Лиспе используются и более наглядные имена FIRST, SECOND, THIRD и т.д. Можно воспользоваться и наиболее общей функцией NTH, выделяющей n-й элемент списка:

 

(NTH n список )

_(nth 2 ’ (1 2 3)) ; индексы начинаются с нуля

_(third (cons 1 (cons 2 (cons 3 nil))))

_(fourth ’ (1 2 3))

NIL

Последний элемент списка можно выделить с помощью функции LAST:

 

(LAST x)

LIST создает список из элементов

Другой, часто используемой, встроенной функцией является

 

(LIST x1 x2 x3 …),

 

которая возвращает в качестве своего значения список из значений аргументов. Количество аргументов функции LIST произвольно:

 

_(list 1 2)

(1 2)

_(list ’ a ’ b (+ 1 2))

(A B 3)

_(list ’a ’ (b c) ’d)

(A (B C) D)

_(list NIL)

(NIL)

Построение списков нетрудно свести к вложенным вызовам функции CONS, причем вторым аргументом последнего вызова является NIL, служащий основой для наращивания списка:

 

_(cons ’c NIL)

(C) ; ó (list ’c)

_(cons ’b (cons ’c NIL)) ; ó (list ’b ’c)

(B C)

_(cons ’a (cons ’b (cons ’c NIL)))

(A B C)

 

 

ЛАБОРАТОРНАЯ РАБОТА №3

 

1. Перечислите базовые функции языка Лисп. Каковы типы их аргументов, и какие значения они возвращают в качестве результата?

 

2. Запишите последовательности вызовов CAR и CDR, выделяющие из приведенных ниже списков символ «цель». Упростите эти вызовы с помощью функций C…R.

a) (1 2 цель 3 4)

b) ((1) (2 цель) (3 (4)))

c) ((1 (2 (3 4 цель))))

 

3. Вычислите значения следующих выражений.

a) cons nil ’(суть пустой список))

b) (cons nil nil)

c) (cons ’(nil) ’(nil))

d) (cons (car ’(a b)) (cdr ’(a b)))

e) (car ’(car (a b c)))

f) (cdr (car (cdr ’(a b c))))

g) (list (list ’a ’b) ’(car (c d)))

 

4. Какие из следующих вызовов возвращают значение Т?

a) (atom ’(cdr nil))

b) (equal ’(a b) (cons ’(a) ’(b)))

c) (atom (* 2 (+ 2 3)))

d) (null (null t))

e) (eq nil (null nil))

f) (eq1 2.0 2)

g) (equal 2.0 2)

h) (= 2.0 2)

i) (equalp 2.0 2)

j) (equalp (atom nil) (caar ’((t))))

 

ИМЯ И ЗНАЧЕНИЕ СИМВОЛА

Значением константы является сама константа

Символ может обозначать произвольное выражение

SET вычисляет имя и связывает его

SETQ связывает имя, не вычисляя его

SETF – обобщенная функция присваивания

Побочный эффект псевдофункции

Вызов интерпретатора EVAL вычисляет значение значения

Основной цикл: READ-EVAL-PRINT

 

Значением константы является сама константы

Так же как выражение, являющееся вызовом функции, без предшествующего апострофа представляет значение выражения, а не само выражение, так и атомы могут использоваться для обозначения каких-нибудь значений. Мы уже обращали внимание на то, что перед лисповскими константами (числами и символами Е и NIL) не надо ставить апостроф. Как константы они обозначают самих себя. Если мы введем константу, то интерпретатор в качестве результата выдаст саму эту константу:

 

_t

T

_’t

T

_nil

NIL

_3.14

3.14

 

Символ может обозначать произвольное выражение

Символы можно использовать как переменные. В этом случае они могут обозначать некоторые выражения. У символов изначально нет какого-нибудь значения, как у констант. Если, например, введем символ ФУНКЦИИ, то мы получим сообщение об ошибке:

 

_функции ; у символа нет значения

Error: Unbound atom ФУНКЦИИ

Интерпретатор здесь не может вычислить значение символа, поскольку его у него нет.

 

 

SET вычисляет имя и связывает его

При помощи функции SET символу можно присвоить (set) или связать (bind) с ним некоторое значение. Если, например, мы хотим, чтобы символ ФУНКЦИИ обозначал базовые функции Лиспа, то введем:

 

_(set ’функции ’(car cdr cons atom eq))

(CAR CDR CONS ATOM EQ)

 

Теперь между символом ФУНКЦИИ и значением (CAR CDR CONS ATOM EQ) образована связь (binding), которая действительна до окончания работы, если, конечно, этому имени функцией SET не будет присвоено новое значение. После присваивания интерпретатор уже может вычислить значение символа ФУНКЦИИ:

 

_функции

(CAR CDR CONS ATOM EQ)

Обратите внимание, что SET вычисляет оба аргумента. Если перед первым аргументом нет апострофа, то с помощью функции SET можно присвоить значение имени, которое получается путем вычисления, Например, вызов

 

_(set (car функции) ’(взбрести в голову))

ВЗБРЕСТИ В ГОЛОВУ

Присваивает переменной CAR выражение (ВЗБРЕСТИ В ГОЛОВУ), так как вызов (CAR ФУНКЦИИ) возвращает в качестве значения символ CAR, который и используется как фактический аргумент вызова функции SET:

 

_(car функции)

CAR

_CAR

(ВЗБРЕСТИ В ГОЛОВУ)

_функции

(CAR CDR CONS ATOM EQ)

На значение символа можно сослаться, записав его без апострофа. Значение имени никак не проявится до тех пор, пока оно не примет участия в вычислениях. Значения символов определяются с помощью специальной функции SYMBOL-VALUE, которая возвращает в качестве своего значения значение символа, являющегося ее аргументом.

 

_(symbol-value (car функции))

(ВЗБРЕСТИ В ГОЛОВУ)

 







Последнее изменение этой страницы: 2016-09-05; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.206.187.81 (0.013 с.)