Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Предикаты (функции) сравнения



(eq e1 e2)

Функция сравнивает значения своих аргументов, которые должны быть атомами-идентификаторами. В случае их совпадения (идентичности) значение функции равно T, иначе – ().

(eql e1 e2)

В отличие от предыдущей функции eql сравнивает значения своих аргументов, которыми могут быть не только атомы-идентификаторы, но и атомы-числа. Если они равны, то значение функции равно T, иначе - ().

(equal e1 e2)

Функция производит сравнение двух произвольных S-выражений - значений своих аргументов. Если они равны (имеют одинаковую структуру и состоят из одинаковых атомов), то значение функции равно T, иначе - ().

(neq e1 e2)

Аналог, но значения аргументов сравниваются на "не равно".

(member a l)

Функция производит поиск атома, являющегося значением первого ее аргумента, в списке (на верхнем его уровне), являющемся вторым аргументом. В случае успеха поиска значение функции равно T, иначе - ().

(gt n1 n2) или (> n1 n2)

Значениями аргументов этой функции должны быть числа. Если первое из них больше второго, то значение функции равно T, иначе – ().

(lt n1 n2) или (< n1 n2)

Аналог, но числа сравниваются на "меньше".

Логические функции

Так называются три функции, реализующие основные логические операции.

(not e)

Эта функция, реализующая "отрицание", является дубликатом функции null: если значение аргумента равно () ("ложь"), то функция выдает результат T ("истина"), а при любом другом значении аргумента выдает результат ().

(and e1 e2 ... ek) (k ≥ 1)

Это "конъюнкция". Функция по очереди вычисляет свои аргументы. Если значение очередного из них равно () ("ложь"), то функция, не вычисляя оставшиеся аргументы, заканчивает свою работу со значением (), а иначе переходит к вычислению следующего аргумента. Если функция дошла до вычисления последнего аргумента, то с его значением она и заканчивает свою работу.

(or e1 e2 ... ek) (k ≥ 1)

Это "дизъюнкция". Функция по очереди вычисляет свои аргументы. Если значение очередного из них не равно () ("ложь"), то функция, не вычисляя оставшиеся аргументы, заканчивает свою работу со значением этого аргумента, в противном случае она переходит к вычислению следующего аргумента. Если функция дошла до вычисления последнего аргумента, то с его значением она и заканчивает свою работу.

К числу логических функций можно отнести и лисповское условное выражение:

[cond (p1 e1,1 e1,2 ... e1,k1) ...

(pn en,1 en,2 ... en,kn)]

где (n≥1, ki≥1)

Функция cond последовательно вычисляет первые элементы своих аргументов – обращения к предикатам pi. Если все они имеют значение () ("ложь"), тогда функция заканчивает свою работу с этим же значением. Но если был обнаружен предикат pi, значение которого отлично от (), т.е. он имеет значение "истина", тогда функция cond уже не будет рассматривать остальные предикаты, а последовательно вычислит формы ei,j из этого i-го аргумента и со значением последнего из них закончит свою работу. Заметим, что поскольку значения предыдущих форм из этого аргумента нигде не запоминаются, то в качестве этих форм имеет смысл использовать только такие, которые имеют побочный эффект, например, обращение к функции присвоения значения.

 

2.9. Определения функций. Формализм их задания

Механизм объявления функций заимствован из лямбда-исчисления Черча, то есть основан на методе представления «безымянных функций» с помощью вычислимых выражений. «Безымянная» функция (или лямбда-выражение) представляет собой совокупность набора формальных переменных и действия с ними. Пример лямбда-выражения:

(lambda (х у) (+ х у))

Само по себе лямбда-выражение не воспринимается интерпретатором, а вот лямбда-выражение, примененное к фактическим аргументам, уже вычислимо:

((lambda (х у) (+ х у)) 1 2) => 3

При вызове лямбда-выражения фактические параметры по определенным правилам связываются с формальными и над ними выполняется заданное действие.

Таким образом, каждый раз, когда нам нужна функция, мы можем записать необходимое лямбда-выражение, примененное к фактическим параметрам. Ясно, что это весьма неудобно (хотя и правильно с «идейной» точки зрения), поэтому Lisp предоставляет возможность именования конкретных лямбда-выражений для их последующего повторного использования.

Для этого служит встроенная функция defun, к которой возможны следующие (равноценные) обращения:

(defun f (lambda (v1 v2 ... vn) e))

или

(defun f (v1 v2 ... vn) e).

Вычисление функции defun в качестве побочного эффекта приводит к появлению в программе новой функции с именем f ; vi – формальные параметры новой функции (n≥0), а e - форма, зависящая от vi. Заметим, что таким образом определяется обычная лисп-функция, т.е. функция с фиксированным количеством аргументов, которые всегда вычисляются при обращении к ней.

При последующем обращении к этой уже определенной функции

(f a1 a2 ... an)

сначала вычисляются аргументы (фактические параметры) ai, затем вводятся локальные переменные vi, которым присваиваются значения соответствующих аргументов ai, и далее вычисляется форма e при этих значениях переменных vi, после чего эти переменные уничтожаются. Значением данной формы становится значение функции f при аргументах ai.

Лексические переменные (формальные параметры функций) связаны лишь в пределах той формы, в которой они определены, то есть изменение их значений не влияет на значения одноименных внешних переменных.

В силу рекурсивной природы списков как таковых для определения функций можно использовать рекурсию, хотя возможности Лиспа не исключают и обычные, императивные определения. В качестве примера можно привести следующее рекурсивное определение функции вычисления факториала:

(defun myfactor (х)

(cond((equal х 1) 1)

(t (* x (myfactor (- x 1))))))

Фундаментальное значение рекурсии состоит в ее применении всюду, где требуются циклические вычисления, поскольку «чистая» функциональная программа не содержит операторов цикла.

 

Функционалы

Кроме обычных функций в Lisp существует также возможность объявления функций более высокого порядка, или функционалов. Функционал – это функция, одним из аргументов которой, в свою очередь, является функция. В различных случаях функциональный аргумент может использоваться и как данные (в том случае, если он не влияет на вычисления), и как обычная функция (в том случае, если он используется как средство, определяющее вычисления):

(car ’(lambda (x) (list x))) => lambda

;; CAR - функция,

;; лямбда-выражение - данные;

((lambda (x) (list x)) ’car) => (car)

;; CAR - данные,

;; лямбда-выражение – функция

Функционал – это функция, в которой функциональный аргумент используется в позиции и в роли функции.

Пример пояснит ситуацию. Часто используются так называемые отображающие функционалы МАРx (где x—CAR или CDR), применяющие функциональные аргументы последовательно к CAR или CDR списка и составляющие список результатов:

(mapcar ’(lambda (x) (print x))

’(1 2 3))

=> 1\n2\n3\n

(mapcdr ’(lambda (x) (print

(car x))) ’(1 2 3))

=> 2\n3\n nil\n

 

Свойства символов

В Lisp каждый символ имеет так называемые свойства. Удобно представлять символы в виде структуры из нескольких значений: непосредственно самого значения символа, а также некоторых присвоенных ему именованных значений, называемых свойствами. На самом деле свойства представляются списком, хранящимся вместе с символом (список свойств, property list, proplist), следующего вида: (имя1 значение1 имя2 значение2. . . ), например, у символа «кошка» может быть такой список свойств:

(шерсть густая цвет-шерсти белый

цвет-глаз голубой)

В Common Lisp (одна из стандартизованных реализаций языка Лисп) получение определенного свойства символа выполняется с помощью

функции get:

(get ’кошка ’цвет-шерсти) => белый

Присваивание же выполняется с помощью объединения обобщенного присваивания setf и get. Причем подобным образом может быть и заведено новое свойство:

(setf (get ’кошка ’природная-еда) ’мыши)

=> мыши

(get ’кошка ’природная-еда) => мыши

Полный список пользовательских свойств может быть получен с помощьюфункции symbolplist:

(symbol-plist ’кошка)

=> (природная-еда мыши)

Каждый символ в Lisp помимо определенных пользователем свойств содержит также список системных свойств, таких, как, например, лямбда-выражение (если с данным символом связано определение функции), тип символа и т. д. Эти свойства изменяются с помощью описанных выше функций set, defun и пр.

Таким образом, является ли данный символ функцией или нет, принадлежит ли он тому или иному типу и т. п., является свойством самого символа, что позволяет легко манипулировать этими свойствами (попробуйте в С убрать у main() свойство быть функцией).

Эта возможность Lisp позволяет заметно облегчить написание программ, управляемых данными, семантических сетей, а также объектно-ориентированных программ.


Поделиться:



Последнее изменение этой страницы: 2019-06-20; Просмотров: 180; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.018 с.)
Главная | Случайная страница | Обратная связь