(STRING= "LISP" "LISP")
(STRING= "C-LISP" "H-LISP")
NIL
(EQUAL "!" "!")
После того как интерпретатор LISP встречает атом, происходит его сравнение с ранее известными атомами. При этом если атом новый, то происходит резервирование памяти под структуру атома. При чтении строкового типа такого не происходит, поэтому к нему прибегают, когда к данным, представленными последовательностью знаков алфавита не нужно присваивать значения.
На языке математики комплексным числом называется выражение вида a + ib, где a и b - любые действительные числа, i - специальное число, которое называется мнимой единицей. Я Common Lisp возможно использование комплексных чисел, они представляются парой вещественных числе в форме: #C(REAL IMAGINARY).
В соответствии с правилами комплексного анализа, Lisp выполняет все арифметические операции с комплексными числами, вычисляет корни, тригонометрические и логарифмические значения, возводит в степень и т.п.
В приведенном примере результатами алгебраических выражений являются
комплексные числа, это одна из важных особенностей языка LISP.
(* 2 (+ #c(10 5) 4))
#C(28 10)
(log -10)
#C(2.302585d0 3.141593d0)
(* 2 (+ (log -10) 5))
#C(14.60517d0 6.283185d0)
(sin(log (expt #c(10 5) 2)))
#C(-1.451832 0.123302)
Иерархия классов состоит из двух основных семейств классов: встроенных и определенных пользователем. Классы, которые представляют типы данных, такие как INTEGER, STRING и LIST, являются встроенными. Они находятся в отдельном разделе иерархии классов, организованные соответствующими связями дочерних и родительских классов, и для работы с ними используются функции, о которых говорилось ранее. Нельзя унаследовать от этих классов, однако можно определить специализированные методы для них, эффективно расширяя поведения этих классов. Lisp дает возможность создать сложный объект - классы и задает поведение для своих экземпляров.
Класс, как тип данных, состоит из трех частей: имени, отношения к другим
классам и имен слотов. Базовая форма DEFCLASS выглядит достаточно просто:
(DEFCLASS (КЛАСС-ПРЕДОК) (СЛОТЫ)...)
В поле наследуемого класса можно ничего не вписывать, если этого не требуется. Большая часть DEFCLASS состоит из списка спецификаторов слотов. Каждый спецификатор определяет слот, который будет частью экземпляра класса. Каждый слот в экземпляре является местом, которое может хранить значение, к которому можно получить доступ через функцию SLOT-VALUE. SLOT-VALUE в качестве аргументов принимает объект и имя слота и возвращает значение нужного слота в данном объекте. Эта функция может использоваться вместе с SETF для установки значений слота в объекте.
Класс также наследует спецификаторы слотов от своих суперклассов, так что набор слотов, присутствующих в любом объекте, является объединением всех слотов, указанных в форме DEFCLASS для класса, а также указанных для всех его суперклассов.
Создаются новые объекты типа класс с помощью функции MAKE-INSTANCE, возвращаемым значением её является новый объект.
Используя данное определение нового класса, новые объекты будут
создаваться со слотами, которые не связаны со значениями. Любая попытка
получить значение для несвязанного значения приведет к выдаче ошибки, так что
нужно задать значение до того, как его считывать.
(defclass MAI ()
(Faculty))
#<Standard-Class MAI #x367FCB8>
(defclass student (MAI)
(progress))
#<Standard-Class STUDENT #x38ED2E0>
(defparameter *Isaev (make-instance 'student))
*ISAEV
(setf (slot-value *ISAEV 'PROGRESS) "GOOD")
"GOOD"
"GOOD"
(SETF (SLOT-VALUE *ISAEV 'FACULTY) '7)
7
(SLOT-VALUE *ISAEV 'FACULTY)
Lisp предоставляет три способа управления начальными значениями слотов.
Первые два требуют добавления опций в спецификаторы слотов в DEFCLASS: с
помощью опции :initarg указывается имя, которое потом будет использоваться как
именованный параметр при вызове MAKE-INSTANCE и переданное значение будет
сохранено в слоте. Вторая опция - :initform, указывает выражение на Lisp,
которое будет использоваться для вычисления значения, если при вызове
MAKE-INSTANCE не был передан аргумент :initarg . В заключение, для полного
контроля за инициализацией объекта, можно определить метод для обобщенной
функции INITIALIZE-INSTANCE, которую вызывает MAKE-INSTANCE.
(defclass boxer ()
((name
:initarg :name)
(weight
:initarg :weight
:initform 0)
(height
:initarg :height
:initform 0)))
#<Standard-Class BOXER #x36D2450>
(defparameter *Ali
(make-instance 'boxer :name "Mohammed Ali" :weight 91 :height 191))
*ALI
(slot-value *Ali 'weight)
91
В большинстве случаев, комбинации опций :initarg и :initform будет достаточно для нормальной инициализации объекта. Однако, хотя начальное выражение может быть любым выражением Lisp, оно не имеет доступа к инициализируемому объекту, так что оно не может инициализировать один слот, основываясь на значении другого. Для выполнения такой задачи необходимо определить метод для обобщенной функции INITIALIZE-INSTANCE.
Основной метод INITIALIZE-INSTANCE, специализированный для STANDARD-OBJECT берет на себя заботу об инициализации слотов, основываясь на данных, заданных опциями :initarg и :initform.
Методы представляют собой входящие в состав класс фрагменты кода, которые выполняются с набором аргументов, который удовлетворяет определенному шаблону. Методы не являются, как это можно было бы ожидать, функциями, они не могут вызываться непосредственно с набором аргументов, а лишь встраиваются в обобщенные функции.
В примере, приведенном ниже, с помощью определенного метода
INITIALIZE-INSTANCE слот account-type устанавливается в значение :gold, :silver или :bronze
в зависимости от установленного значения в слоте balance.
(defclass bank-account ()
((customer-name
:initarg :customer-name
:initform (error "Must supply a customer name."))
(balance
:initarg :balance
:initform 0)
(account-number
:initform (incf *account-numbers*))
account-type))
#<Standard-Class BANK-ACCOUNT #x36AF0F8>
(defvar *account-numbers* 0)
*ACCOUNT-NUMBERS*
(defmethod initialize-instance :after ((account bank-account) &key)
(let ((balance (slot-value account 'balance)))
(setf (slot-value account 'account-type)
(cond
((>= balance 100000) :gold)
((>= balance 50000) :silver)
(t :bronze)))))
#<Standard-Method INITIALIZE-INSTANCE :AFTER (BANK-ACCOUNT) #x3879138>
(defparameter *acc* (make-instance 'bank-account :customer-name "FS14"
:balance 1000))
*ACC*
(slot-value *acc* 'account-type)
:BRONZE
всегда присваивает начальное значение названной переменной[4].
DEFVAR
присваивает начальное значение переменной, которая еще не определена [4].
В курсовой работе были рассмотрены основные типы данных и особенности языка программирования LISP.
Мы увидели, что LISP представляет собой объекты, которые принадлежат к одному, или к нескольким типам одновременно. В этом отношении Лисп также опередил свое время на многие десятилетия и в нем объектно-ориентированный подход, как мы убедились, реализован исключительно ярко и удобно.
Конечно, за 50 лет эволюции языка LISP в нем появилось немало производных типов данных,
которые предназначены для решения тех или иных специфичных задач. Сегодня
Common Lisp поддерживает работу с разнообразными типами объектов. Это важная
оговорка - в LISP тип имеют не переменные, а именно
объекты, в которых размещены те или иные данные. При этом любая переменная
может иметь в качестве значения объект произвольного типа.
1. Большакова Е.И., Груздева Н.В. «Основы программирования на языке ЛИСП» - М.: МГУ, 2010
. Семенов М. «Язык Лисп для персональных ЭВМ» - М.: МГУ, 1989.
. Хювянен Э., Сеппянен Й. «Мир Лиспа» - М.: Наука, т. 1, 2, 1984.
. Интернет-источник: http://www.lisper.ru/ (06.11.2015).