Курсовая работа (т): Исследование форм структурированных данных на Lisp

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

(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).

Источник: https://www.bibliofond.ru/detail.aspx?id=863977