Учебники

LISP — Краткое руководство

LISP — Обзор

Джон Маккарти изобрел LISP в 1958 году, вскоре после разработки FORTRAN. Впервые он был реализован Стивом Расселом на компьютере IBM 704.

Он особенно подходит для программ искусственного интеллекта, поскольку он эффективно обрабатывает символическую информацию.

Common Lisp возник в 1980-х и 1990-х годах в попытке объединить работу нескольких групп реализации, которые были преемниками Maclisp, таких как ZetaLisp и NIL (Новая реализация Lisp) и т. Д.

Он служит общим языком, который может быть легко расширен для конкретной реализации.

Программы, написанные на Common LISP, не зависят от характеристик компьютера, таких как длина слова и т. Д.

Особенности Common LISP

  • Это не зависит от машины

  • Он использует методологию итеративного проектирования и простоту расширения.

  • Это позволяет динамически обновлять программы.

  • Это обеспечивает отладку высокого уровня.

  • Он обеспечивает расширенное объектно-ориентированное программирование.

  • Это обеспечивает удобную систему макросов.

  • Он предоставляет широкий спектр типов данных, таких как объекты, структуры, списки, векторы, настраиваемые массивы, хэш-таблицы и символы.

  • Это на основе выражения.

  • Это обеспечивает объектно-ориентированную систему условий.

  • Он предоставляет полную библиотеку ввода / вывода.

  • Это обеспечивает обширные структуры управления.

Это не зависит от машины

Он использует методологию итеративного проектирования и простоту расширения.

Это позволяет динамически обновлять программы.

Это обеспечивает отладку высокого уровня.

Он обеспечивает расширенное объектно-ориентированное программирование.

Это обеспечивает удобную систему макросов.

Он предоставляет широкий спектр типов данных, таких как объекты, структуры, списки, векторы, настраиваемые массивы, хэш-таблицы и символы.

Это на основе выражения.

Это обеспечивает объектно-ориентированную систему условий.

Он предоставляет полную библиотеку ввода / вывода.

Это обеспечивает обширные структуры управления.

Приложения, созданные в LISP

Большие успешные приложения, созданные в Лиспе.

  • Emacs

  • G2

  • AutoCad

  • Игорь Гравер

  • Магазин Yahoo

Emacs

G2

AutoCad

Игорь Гравер

Магазин Yahoo

LISP — Настройка среды

Настройка локальной среды

Если вы все еще хотите настроить свою среду для языка программирования Lisp, вам потребуются следующие два программного обеспечения, доступных на вашем компьютере: (а) текстовый редактор и (б) исполнитель Lisp.

Текстовый редактор

Это будет использоваться для ввода вашей программы. Примерами немногих редакторов являются Блокнот Windows, команда редактирования ОС, Brief, Epsilon, EMACS и vim или vi.

Имя и версия текстового редактора могут различаться в разных операционных системах. Например, Блокнот будет использоваться в Windows, а vim или vi могут использоваться в Windows, а также в Linux или UNIX.

Файлы, которые вы создаете в редакторе, называются исходными файлами и содержат исходный код программы. Исходные файлы для программ на Лиспе обычно называются с расширением » .lisp «.

Перед началом программирования убедитесь, что у вас есть один текстовый редактор, и у вас достаточно опыта, чтобы написать компьютерную программу, сохранить ее в файле и, наконец, выполнить.

Исполнитель Лиспа

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

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

CLISP — это многоархитектурный компилятор GNU Common LISP, используемый для настройки LISP в Windows. Версия для Windows эмулирует среду Unix, используя MingW под Windows. Инсталлятор позаботится об этом и автоматически добавит clisp в переменную PATH Windows.

Вы можете получить последнюю версию CLISP для Windows здесь — https://sourceforge.net/projects/clisp/files/latest/download

Настройка среды списка

По умолчанию он создает ярлык в меню «Пуск» для построчного переводчика.

Как использовать CLISP

Во время установки clisp автоматически добавляется в переменную PATH, если вы выберете опцию (РЕКОМЕНДУЕТСЯ). Это означает, что вы можете просто открыть новое окно командной строки и набрать «clisp», чтобы вызвать компилятор.

Чтобы запустить файл * .lisp или * .lsp, просто используйте —

clisp hello.lisp

LISP — Структура программы

Выражения LISP называются символическими выражениями или s-выражениями. S-выражения состоят из трех допустимых объектов, атомов, списков и строк.

Любое s-выражение является допустимой программой.

Программы LISP запускаются либо на интерпретаторе, либо в виде скомпилированного кода.

Интерпретатор проверяет исходный код в повторяющемся цикле, который также называется циклом чтения-оценки-печати (REPL). Он читает код программы, оценивает его и печатает значения, возвращаемые программой.

Простая программа

Напишем s-выражение, чтобы найти сумму трех чисел 7, 9 и 11. Для этого мы можем набрать в приглашении интерпретатора.

(+ 7 9 11)

LISP возвращает результат —

27

Если вы хотите запустить ту же программу, что и скомпилированный код, создайте файл исходного кода LISP с именем myprog.lisp и введите в него следующий код.

Live Demo

(write (+ 7 9 11))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

27

LISP использует префиксную нотацию

Вы могли заметить, что LISP использует префиксную нотацию.

В вышеприведенной программе символ + работает как имя функции для процесса суммирования чисел.

В префиксной записи операторы записываются перед операндами. Например, выражение,

a * ( b + c ) / d

будет написано как —

(/ (* a (+ b c) ) d)

Давайте возьмем другой пример, напишем код для преобразования температуры по Фаренгейту 60 ° F в градус Цельсия —

Математическое выражение для этого преобразования будет —

(60 * 9 / 5) + 32

Создайте файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write(+ (* (/ 9 5) 60) 32))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет ее немедленно, и возвращается результат:

140

Оценка программ LISP

Оценка программ LISP состоит из двух частей —

  • Перевод текста программы в объекты Lisp программой чтения

  • Реализация семантики языка в терминах этих объектов программой оценки

Перевод текста программы в объекты Lisp программой чтения

Реализация семантики языка в терминах этих объектов программой оценки

Процесс оценки состоит из следующих шагов:

  • Читатель переводит строки символов в объекты LISP или s-выражения.

  • Оценщик определяет синтаксис форм Lisp, которые построены из s-выражений. Этот второй уровень оценки определяет синтаксис, который определяет, какие s-выражения являются формами LISP.

  • Оценщик работает как функция, которая принимает допустимую форму LISP в качестве аргумента и возвращает значение. По этой причине мы помещаем выражение LISP в круглые скобки, потому что мы отправляем все выражение / форму в качестве аргументов в оценщик.

Читатель переводит строки символов в объекты LISP или s-выражения.

Оценщик определяет синтаксис форм Lisp, которые построены из s-выражений. Этот второй уровень оценки определяет синтаксис, который определяет, какие s-выражения являются формами LISP.

Оценщик работает как функция, которая принимает допустимую форму LISP в качестве аргумента и возвращает значение. По этой причине мы помещаем выражение LISP в круглые скобки, потому что мы отправляем все выражение / форму в качестве аргументов в оценщик.

Программа «Hello World»

Изучение нового языка программирования не будет успешным, пока вы не научитесь приветствовать весь мир на этом языке, верно!

Поэтому, пожалуйста, создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line "Hello World")

(write-line "I am at 'Tutorials Point'! Learning LISP")

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

Hello World

I am at 'Tutorials Point'! Learning LISP

LISP — основной синтаксис

Основные строительные блоки в LISP

Программы LISP состоят из трех основных строительных блоков —

  • атом
  • список
  • строка

Атом — это число или строка смежных символов. Он включает в себя цифры и специальные символы.

Ниже приведены примеры некоторых допустимых атомов:

hello-from-tutorials-point
name
123008907
*hello*
Block#221
abc123

Список — это последовательность атомов и / или других списков, заключенных в скобки.

Ниже приведены примеры некоторых действительных списков:

( i am a list)
(a ( a b c) d e fgh)
(father tom ( susan bill joe))
(sun mon tue wed thur fri sat)
( )

Строка — это группа символов, заключенная в двойные кавычки.

Ниже приведены примеры некоторых допустимых строк:

" I am a string"
"a ba c d efg #$%^&!"
"Please enter the following details :"
"Hello from 'Tutorials Point'! "

Добавление комментариев

Точка с запятой (;) используется для обозначения строки комментария.

Например,

Live Demo

(write-line "Hello World") ; greet the world

; tell them your whereabouts

(write-line "I am at 'Tutorials Point'! Learning LISP")

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

Hello World

I am at 'Tutorials Point'! Learning LISP

Некоторые заметные моменты, прежде чем перейти к следующему

Ниже приведены некоторые важные моменты, на которые следует обратить внимание.

  • Основные числовые операции в LISP: +, -, * и /

  • LISP представляет вызов функции f (x) как (fx), например, cos (45) записывается как cos 45

  • Выражения LISP нечувствительны к регистру, потому что 45 или COS 45 одинаковы.

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

    • чисел

    • Буква t, которая обозначает логическую истину.

    • Значение nil, которое обозначает логическое false, а также пустой список.

Основные числовые операции в LISP: +, -, * и /

LISP представляет вызов функции f (x) как (fx), например, cos (45) записывается как cos 45

Выражения LISP нечувствительны к регистру, потому что 45 или COS 45 одинаковы.

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

чисел

Буква t, которая обозначает логическую истину.

Значение nil, которое обозначает логическое false, а также пустой список.

Немного больше о формах LISP

В предыдущей главе мы упоминали, что процесс оценки кода LISP состоит из следующих шагов.

  • Читатель переводит строки символов в объекты LISP или s-выражения.

  • Оценщик определяет синтаксис форм Lisp, которые построены из s-выражений. Этот второй уровень оценки определяет синтаксис, который определяет, какие s-выражения являются формами LISP.

Читатель переводит строки символов в объекты LISP или s-выражения.

Оценщик определяет синтаксис форм Lisp, которые построены из s-выражений. Этот второй уровень оценки определяет синтаксис, который определяет, какие s-выражения являются формами LISP.

Теперь формы LISP могут быть.

  • Атом
  • Пустой или не список
  • Любой список, который имеет символ в качестве первого элемента

Оценщик работает как функция, которая принимает допустимую форму LISP в качестве аргумента и возвращает значение. По этой причине мы помещаем выражение LISP в круглые скобки, потому что мы отправляем все выражение / форму в качестве аргументов в оценщик.

Соглашения об именах в LISP

Имя или символы могут состоять из любого количества буквенно-цифровых символов, кроме пробелов, открытых и закрывающих скобок, двойных и одинарных кавычек, обратной косой черты, запятой, двоеточия, точки с запятой и вертикальной черты. Чтобы использовать эти символы в имени, вам нужно использовать escape-символ (\).

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

Использование одинарных кавычек

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

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

Чтобы сделать это, нам нужно поставить перед кавычкой атом или список.

Следующий пример демонстрирует это.

Создайте файл с именем main.lisp и введите в него следующий код.

Live Demo

(write-line "single quote used, it inhibits evaluation")
(write '(* 2 3))
(write-line " ")
(write-line "single quote not used, so expression evaluated")
(write (* 2 3))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

single quote used, it inhibits evaluation
(* 2 3) 
single quote not used, so expression evaluated
6

LISP — Типы данных

В LISP переменные не типизированы, а объекты данных.

Типы данных LISP могут быть классифицированы как.

  • Скалярные типы — например, числовые типы, символы, символы и т. Д.

  • Структуры данных — например, списки, векторы, битовые векторы и строки.

Скалярные типы — например, числовые типы, символы, символы и т. Д.

Структуры данных — например, списки, векторы, битовые векторы и строки.

Любая переменная может принимать любой объект LISP в качестве значения, если вы не объявили это явно.

Хотя нет необходимости указывать тип данных для переменной LISP, тем не менее, это помогает в определенных расширениях цикла, в объявлениях методов и некоторых других ситуациях, которые мы обсудим в следующих главах.

Типы данных организованы в иерархию. Тип данных — это набор объектов LISP, и многие объекты могут принадлежать одному такому набору.

Предикат typep используется для определения, принадлежит ли объект определенному типу.

Функция type-of возвращает тип данных данного объекта.

Спецификаторы типов в LISP

Спецификаторы типов — это системные символы для типов данных.

массив Fixnum пакет простая строка
атом поплавок путь к файлу простой вектор
bignum функция случайное состояние одного поплавка
немного хеш-таблица соотношение Стандарт-символ
битовый вектор целое число рациональный поток
персонаж ключевое слово readtable строка
[Общий] список последовательность [Строка-символ]
скомпилированная функция давно поплавок короткого поплавок условное обозначение
сложный Нилл зарегистрированы байты T
минусы ноль простой массив без знака байта
двойной поплавок число простой бит-вектор вектор

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

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq x 10)
(setq y 34.567)
(setq ch nil)
(setq n 123.78)
(setq bg 11.0e+4)
(setq r 124/2)

(print x)
(print y)
(print n)
(print ch)
(print bg)
(print r)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

10 
34.567 
123.78 
NIL 
110000.0 
62

Пример 2

Далее давайте проверим типы переменных, использованных в предыдущем примере. Создайте новый файл исходного кода с именем main. lisp и введите в нем следующий код.

Live Demo

(defvar x 10)
(defvar y 34.567)
(defvar ch nil)
(defvar n 123.78)
(defvar bg 11.0e+4)
(defvar r 124/2)

(print (type-of x))
(print (type-of y))
(print (type-of n))
(print (type-of ch))
(print (type-of bg))
(print (type-of r))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

(INTEGER 0 281474976710655) 
SINGLE-FLOAT 
SINGLE-FLOAT 
NULL 
SINGLE-FLOAT 
(INTEGER 0 281474976710655)

LISP — Макросы

Макросы позволяют расширять синтаксис стандартного LISP.

Технически, макрос — это функция, которая принимает s-выражение в качестве аргументов и возвращает форму LISP, которая затем оценивается.

Определение макроса

В LISP именованный макрос определяется с помощью другого макроса с именем defmacro. Синтаксис для определения макроса —

(defmacro macro-name (parameter-list))
"Optional documentation string."
body-form

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

пример

Давайте напишем простой макрос с именем setTo10, который возьмет число и установит его значение равным 10.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defmacro setTo10(num)
(setq num 10)(print num))
(setq x 25)
(print x)
(setTo10 x)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

25
10

LISP — переменные

В LISP каждая переменная представлена символом . Имя переменной — это имя символа, и оно хранится в ячейке памяти символа.

Глобальные переменные

Глобальные переменные имеют постоянные значения во всей системе LISP и действуют до тех пор, пока не будет указано новое значение.

Глобальные переменные обычно объявляются с использованием конструкции defvar .

Например

Live Demo

(defvar x 234)
(write x)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет ее немедленно, и возвращаемый результат

234

Поскольку в LISP отсутствует объявление типа для переменных, вы непосредственно указываете значение для символа с помощью конструкции setq .

Например

->(setq x 10)

Вышеприведенное выражение присваивает значение 10 переменной x. Вы можете ссылаться на переменную, используя сам символ в качестве выражения.

Функция символ-значение позволяет извлечь значение, хранящееся в месте хранения символа.

Например

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq x 10)
(setq y 20)
(format t "x = ~2d y = ~2d ~%" x y)

(setq x 100)
(setq y 200)
(format t "x = ~2d y = ~2d" x y)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат.

x = 10 y = 20 
x = 100 y = 200

Локальные переменные

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

Как и глобальные переменные, локальные переменные также могут быть созданы с помощью конструкции setq .

Есть две другие конструкции — let и prog для создания локальных переменных.

Конструкция let имеет следующий синтаксис.

(let ((var1  val1) (var2  val2).. (varn  valn))<s-expressions>)

Где var1, var2, ..varn — имена переменных, а val1, val2, .. valn — начальные значения, присвоенные соответствующим переменным.

Когда выполняется let , каждой переменной присваивается соответствующее значение и, наконец, вычисляется s-выражение . Возвращается значение последнего оцененного выражения.

Если вы не включили начальное значение для переменной, оно присваивается nil.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(let ((x 'a) (y 'b)(z 'c))
(format t "x = ~a y = ~a z = ~a" x y z))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат.

x = A y = B z = C

Конструкция prog также имеет список локальных переменных в качестве первого аргумента, за которым следует тело prog и любое количество s-выражений.

Функция prog выполняет список s-выражений в последовательности и возвращает nil, если не встречает вызов функции с именем return. Затем аргумент функции возврата оценивается и возвращается.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(prog ((x '(a b c))(y '(1 2 3))(z '(p q 10)))
(format t "x = ~a y = ~a z = ~a" x y z))

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат.

x = (A B C) y = (1 2 3) z = (P Q 10)

LISP — Константы

В LISP константы — это переменные, которые никогда не меняют своих значений во время выполнения программы. Константы объявляются с использованием конструкции defconstant .

пример

В следующем примере показано объявление глобальной константы PI, а затем использование этого значения внутри функции с именем area-circle, которая вычисляет площадь круга.

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

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defconstant PI 3.141592)
(defun area-circle(rad)
   (terpri)
   (format t "Radius: ~5f" rad)
   (format t "~%Area: ~10f" (* PI rad rad)))
(area-circle 10)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат.

Radius:  10.0
Area:   314.1592

ЛИСП — Операторы

Оператор — это символ, который указывает компилятору выполнять определенные математические или логические манипуляции. LISP допускает многочисленные операции с данными, поддерживаемые различными функциями, макросами и другими конструкциями.

Операции, разрешенные для данных, могут быть классифицированы как —

  • Арифметические операции
  • Операции сравнения
  • Логические Операции
  • Побитовые операции

Арифметические операции

В следующей таблице показаны все арифметические операторы, поддерживаемые LISP. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
+ Добавляет два операнда (+ AB) даст 30
Вычитает второй операнд из первого (- АБ) даст -10
* Умножает оба операнда (* AB) даст 200
/ Делит числитель на числитель (/ BA) даст 2
мод, рем Оператор модуля и остаток от целочисленного деления (мод БА) даст 0
INCF Оператор приращений увеличивает целочисленное значение на второй указанный аргумент (включая А 3) даст 13
DECF Оператор decrements уменьшает целочисленное значение на второй указанный аргумент (decf A 4) даст 9

Операции сравнения

Следующая таблица показывает все реляционные операторы, поддерживаемые LISP, который сравнивает числа. Однако, в отличие от реляционных операторов в других языках, операторы сравнения LISP могут принимать более двух операндов и работают только с числами.

Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать примеры

оператор Описание пример
знак равно Проверяет, равны ли все значения операндов или нет, если да, тогда условие становится истинным. (= AB) не соответствует действительности.
знак равно Проверяет, все ли значения операндов различны или нет, если значения не равны, условие становится истинным. (/ = AB) верно.
> Проверяет, монотонно ли уменьшаются значения операндов. (> AB) не соответствует действительности.
< Проверяет, монотонно ли увеличиваются значения операндов. (<AB) верно.
> = Проверяет, является ли значение любого левого операнда больше или равно значению следующего правого операнда, если да, тогда условие становится истинным. (> = AB) не соответствует действительности.
<= Проверяет, является ли значение любого левого операнда меньше или равно значению его правого операнда, если да, тогда условие становится истинным. (<= AB) верно.
Максимум Он сравнивает два или более аргумента и возвращает максимальное значение. (максимум AB) возвращает 20
мин Он сравнивает два или более аргумента и возвращает минимальное значение. (мин. АВ) возвращает 10

Логические операции над логическими значениями

Common LISP предоставляет три логических оператора: и, или, и не, который работает с логическими значениями. Предположим, что A имеет значение nil, а B имеет значение 5, тогда —

Показать примеры

оператор Описание пример
а также Требуется любое количество аргументов. Аргументы оцениваются слева направо. Если все аргументы имеют значение, отличное от nil, возвращается значение последнего аргумента. В противном случае возвращается ноль. (и AB) вернет NIL.
или же Требуется любое количество аргументов. Аргументы оцениваются слева направо до тех пор, пока один из них не станет нулевым, в этом случае возвращается значение аргумента, в противном случае возвращается ноль . (или AB) вернется 5.
не Он принимает один аргумент и возвращает t, если аргумент оценивается как ноль. (не А) вернет Т.

Побитовые операции над числами

Битовые операторы работают с битами и выполняют побитовые операции. Таблицы истинности для побитовых операций и, или, и операций xor следующие:

Показать примеры

п Q р и д р или д р х или д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
Assume if A = 60; and B = 13; now in binary format they will be as follows:
A = 0011 1100
B = 0000 1101
-----------------
A and B = 0000 1100
A or B = 0011 1101
A xor B = 0011 0001
not A  = 1100 0011

Побитовые операторы, поддерживаемые LISP, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда —

оператор Описание пример
logand Это возвращает побитовое логическое И своих аргументов. Если аргумент не указан, то результатом будет -1, который является идентификатором этой операции. (logand ab)) даст 12
logior Это возвращает побитовый логический INCLUSIVE ИЛИ его аргументов. Если аргумент не указан, то результат равен нулю, что является идентификатором для этой операции. (логиор б) даст 61
logxor Это возвращает побитовое логическое ИСКЛЮЧИТЕЛЬНОЕ ИЛИ его аргументов. Если аргумент не указан, то результат равен нулю, что является идентификатором для этой операции. (logxor ab) даст 49
lognor Это возвращает побитовое НЕ своих аргументов. Если аргумент не указан, то результатом будет -1, который является идентификатором этой операции. (lognor ab) даст -62,
logeqv Это возвращает побитовую логическую ЭКВИВАЛЕНТНОСТЬ (также известную как исключительный, ни) ее аргументов. Если аргумент не указан, то результатом будет -1, который является идентификатором этой операции. (logeqv ab) даст -50

ЛИСП — Принятие решений

Структуры принятия решений требуют, чтобы программист указал одно или несколько условий, которые должны быть оценены или протестированы программой, вместе с оператором или инструкциями, которые должны быть выполнены, если условие определено как истинное, и, необязательно, другие операторы, которые должны быть выполнены, если условие определяется как ложный.

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

Принятие решения

LISP предоставляет следующие типы конструкций для принятия решений. Нажмите на следующие ссылки, чтобы проверить их детали.

Sr.No. Конструкция и описание
1 конд

Эта конструкция используется для проверки нескольких предложений test-action. Его можно сравнить с вложенными операторами if в других языках программирования.

2 если

Конструкция if имеет различные формы. В простейшей форме за ним следуют предложение теста, тестовое действие и некоторые другие последующие действия. Если условие теста оценивается как true, то действие теста выполняется иначе, последующее предложение оценивается.

3 когда

В простейшем виде за ним следует предложение теста и действие теста. Если условие теста оценивается как true, то действие теста выполняется иначе, последующее предложение оценивается.

4 дело

Эта конструкция реализует несколько предложений test-action, таких как конструкция cond. Тем не менее, он оценивает форму ключа и допускает несколько предложений действий на основе оценки этой формы ключа.

Эта конструкция используется для проверки нескольких предложений test-action. Его можно сравнить с вложенными операторами if в других языках программирования.

Конструкция if имеет различные формы. В простейшей форме за ним следуют предложение теста, тестовое действие и некоторые другие последующие действия. Если условие теста оценивается как true, то действие теста выполняется иначе, последующее предложение оценивается.

В простейшем виде за ним следует предложение теста и действие теста. Если условие теста оценивается как true, то действие теста выполняется иначе, последующее предложение оценивается.

Эта конструкция реализует несколько предложений test-action, таких как конструкция cond. Тем не менее, он оценивает форму ключа и допускает несколько предложений действий на основе оценки этой формы ключа.

ЛИСП — Петли

Может возникнуть ситуация, когда вам нужно выполнить блок кодовых номеров раз. Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз, и в большинстве языков программирования ниже приводится общая форма оператора цикла.

Loops

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

Sr.No. Конструкция и описание
1 петля

Конструкция цикла — это самая простая форма итерации, предоставляемая LISP. В своей простейшей форме он позволяет выполнять несколько операторов несколько раз, пока не найдет оператор возврата .

2 цикл для

Цикл for construct позволяет вам реализовать итерацию, подобную циклу for, как это наиболее часто встречается в других языках.

3 делать

Конструкция do также используется для выполнения итерации с использованием LISP. Это обеспечивает структурированную форму итерации.

4 DOTIMES

Конструкция dotimes позволяет выполнять циклы для некоторого фиксированного числа итераций.

5 DOLIST

Конструкция dolist позволяет выполнять итерацию по каждому элементу списка.

Конструкция цикла — это самая простая форма итерации, предоставляемая LISP. В своей простейшей форме он позволяет выполнять несколько операторов несколько раз, пока не найдет оператор возврата .

Цикл for construct позволяет вам реализовать итерацию, подобную циклу for, как это наиболее часто встречается в других языках.

Конструкция do также используется для выполнения итерации с использованием LISP. Это обеспечивает структурированную форму итерации.

Конструкция dotimes позволяет выполнять циклы для некоторого фиксированного числа итераций.

Конструкция dolist позволяет выполнять итерацию по каждому элементу списка.

Изящно выход из блока

Блок и возврат позволяют изящно выйти из любых вложенных блоков в случае любой ошибки.

Функция block позволяет вам создать именованный блок с телом, состоящим из нуля или более операторов. Синтаксис —

(block block-name(
...
...
))

Функция return-from принимает имя блока и необязательное (по умолчанию nil) возвращаемое значение.

Следующий пример демонстрирует это —

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код —

Live Demo

(defun demo-function (flag)
   (print 'entering-outer-block)
   
   (block outer-block
      (print 'entering-inner-block)
      (print (block inner-block

         (if flag
            (return-from outer-block 3)
            (return-from inner-block 5)
         )

         (print 'This-wil--not-be-printed))
      )

      (print 'left-inner-block)
      (print 'leaving-outer-block)
   t)
)
(demo-function t)
(terpri)
(demo-function nil)

Когда вы нажимаете кнопку «Выполнить» или нажимаете Ctrl + E, LISP выполняет его немедленно, и возвращается результат —

ENTERING-OUTER-BLOCK 
ENTERING-INNER-BLOCK 

ENTERING-OUTER-BLOCK 
ENTERING-INNER-BLOCK 
5 
LEFT-INNER-BLOCK 
LEAVING-OUTER-BLOCK

ЛИСП — Функции

Функция — это группа операторов, которые вместе выполняют задачу.

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

Определение функций в LISP

Макрос с именем defun используется для определения функций. Макросу defun нужны три аргумента —

  • Наименование функции
  • Параметры функции
  • Тело функции

Синтаксис для определения функции —

(defun name (parameter-list) "Optional documentation string." body)

Давайте проиллюстрируем концепцию на простых примерах.

Пример 1

Давайте напишем функцию с именем averagenum, которая будет печатать в среднем четыре числа. Мы вышлем эти цифры в качестве параметров.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun averagenum (n1 n2 n3 n4)
   (/ ( + n1 n2 n3 n4) 4)
)
(write(averagenum 10 20 30 40))

Когда вы выполняете код, он возвращает следующий результат —

25

Пример 2

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

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun area-circle(rad)
   "Calculates area of a circle with given radius"
   (terpri)
   (format t "Radius: ~5f" rad)
   (format t "~%Area: ~10f" (* 3.141592 rad rad))
)
(area-circle 10)

Когда вы выполняете код, он возвращает следующий результат —

Radius:  10.0
Area:   314.1592

Пожалуйста, обратите внимание, что —

  • Вы можете предоставить пустой список в качестве параметров, что означает, что функция не принимает аргументов, список пуст, записывается как ().

  • LISP также допускает необязательные, множественные и ключевые аргументы.

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

  • Тело функции может состоять из любого числа выражений Lisp.

  • Значение последнего выражения в теле возвращается как значение функции.

  • Вы также можете вернуть значение из функции, используя специальный оператор return-from .

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

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

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

Тело функции может состоять из любого числа выражений Lisp.

Значение последнего выражения в теле возвращается как значение функции.

Вы также можете вернуть значение из функции, используя специальный оператор return-from .

Давайте обсудим вышеупомянутые концепции вкратце. Нажмите на следующие ссылки, чтобы найти детали —

Необязательные параметры

Остальные параметры

Параметры ключевых слов

Возвращение значений из функции

Лямбда-функции

Функции картирования

LISP — Предикаты

Предикаты — это функции, которые проверяют свои аргументы на наличие определенных условий и возвращают nil, если условие ложно, или если какое-либо значение, не равное nil, условие истинно.

В следующей таблице приведены некоторые из наиболее часто используемых предикатов —

Sr.No. Предикат и описание
1

атом

Он принимает один аргумент и возвращает t, если аргумент является атомом или ноль, если в противном случае.

2

равный

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

3

уравнение

Он принимает два аргумента и возвращает t, если они являются одинаковыми идентичными объектами, разделяющими одну и ту же ячейку памяти, или ноль в противном случае

4

EQL

Он принимает два аргумента и возвращает t, если аргументами являются eq , или они являются числами одного типа с одинаковым значением, или если они являются символьными объектами, представляющими один и тот же символ, или ноль в противном случае.

5

EVENP

Он принимает один числовой аргумент и возвращает t, если аргумент является четным числом или ноль, если в противном случае.

6

oddp

Он принимает один числовой аргумент и возвращает t, если аргумент нечетное число или ноль, если в противном случае.

7

zerop

Он принимает один числовой аргумент и возвращает t, если аргумент равен нулю, или ноль, если в противном случае.

8

ноль

Он принимает один аргумент и возвращает t, если аргумент оценивается как ноль, в противном случае он возвращает ноль .

9

listp

Он принимает один аргумент и возвращает t, если аргумент оценивается как список, в противном случае он возвращает nil .

10

greaterp

Он принимает один или несколько аргументов и возвращает t, если либо есть один аргумент, либо аргументы последовательно больше слева направо, либо nil, если в противном случае.

11

lessp

Он принимает один или несколько аргументов и возвращает t, если либо есть один аргумент, либо аргументы последовательно меньше слева направо, либо nil, если в противном случае.

12

numberp

Он принимает один аргумент и возвращает t, если аргумент является числом или ноль, если в противном случае.

13

symbolp

Он принимает один аргумент и возвращает t, если аргумент является символом, в противном случае он возвращает ноль .

14

integerp

Он принимает один аргумент и возвращает t, если аргумент является целым числом, в противном случае он возвращает nil .

15

rationalp

Он принимает один аргумент и возвращает t, если аргумент является рациональным числом, либо отношением, либо числом, в противном случае он возвращает ноль .

16

floatp

Он принимает один аргумент и возвращает t, если аргумент является числом с плавающей запятой, в противном случае он возвращает nil .

17

Реальп

Он принимает один аргумент и возвращает t, если аргумент является действительным числом, в противном случае он возвращает ноль .

18

complexp

Он принимает один аргумент и возвращает t, если аргумент является комплексным числом, в противном случае он возвращает nil.

19

characterp

Он принимает один аргумент и возвращает t, если аргумент является символом, в противном случае он возвращает ноль .

20

stringp

Он принимает один аргумент и возвращает t, если аргумент является строковым объектом, в противном случае он возвращает nil .

21

arrayp

Он принимает один аргумент и возвращает t, если аргумент является объектом массива, в противном случае он возвращает nil .

22

packagep

Он принимает один аргумент и возвращает t, если аргумент является пакетом, в противном случае он возвращает nil.

атом

Он принимает один аргумент и возвращает t, если аргумент является атомом или ноль, если в противном случае.

равный

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

уравнение

Он принимает два аргумента и возвращает t, если они являются одинаковыми идентичными объектами, разделяющими одну и ту же ячейку памяти, или ноль в противном случае

EQL

Он принимает два аргумента и возвращает t, если аргументами являются eq , или они являются числами одного типа с одинаковым значением, или если они являются символьными объектами, представляющими один и тот же символ, или ноль в противном случае.

EVENP

Он принимает один числовой аргумент и возвращает t, если аргумент является четным числом или ноль, если в противном случае.

oddp

Он принимает один числовой аргумент и возвращает t, если аргумент нечетное число или ноль, если в противном случае.

zerop

Он принимает один числовой аргумент и возвращает t, если аргумент равен нулю, или ноль, если в противном случае.

ноль

Он принимает один аргумент и возвращает t, если аргумент оценивается как ноль, в противном случае он возвращает ноль .

listp

Он принимает один аргумент и возвращает t, если аргумент оценивается как список, в противном случае он возвращает nil .

greaterp

Он принимает один или несколько аргументов и возвращает t, если либо есть один аргумент, либо аргументы последовательно больше слева направо, либо nil, если в противном случае.

lessp

Он принимает один или несколько аргументов и возвращает t, если либо есть один аргумент, либо аргументы последовательно меньше слева направо, либо nil, если в противном случае.

numberp

Он принимает один аргумент и возвращает t, если аргумент является числом или ноль, если в противном случае.

symbolp

Он принимает один аргумент и возвращает t, если аргумент является символом, в противном случае он возвращает ноль .

integerp

Он принимает один аргумент и возвращает t, если аргумент является целым числом, в противном случае он возвращает nil .

rationalp

Он принимает один аргумент и возвращает t, если аргумент является рациональным числом, либо отношением, либо числом, в противном случае он возвращает ноль .

floatp

Он принимает один аргумент и возвращает t, если аргумент является числом с плавающей запятой, в противном случае он возвращает nil .

Реальп

Он принимает один аргумент и возвращает t, если аргумент является действительным числом, в противном случае он возвращает ноль .

complexp

Он принимает один аргумент и возвращает t, если аргумент является комплексным числом, в противном случае он возвращает nil.

characterp

Он принимает один аргумент и возвращает t, если аргумент является символом, в противном случае он возвращает ноль .

stringp

Он принимает один аргумент и возвращает t, если аргумент является строковым объектом, в противном случае он возвращает nil .

arrayp

Он принимает один аргумент и возвращает t, если аргумент является объектом массива, в противном случае он возвращает nil .

packagep

Он принимает один аргумент и возвращает t, если аргумент является пакетом, в противном случае он возвращает nil.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (atom 'abcd))
(terpri)
(write (equal 'a 'b))
(terpri)
(write (evenp 10))
(terpri)
(write (evenp 7 ))
(terpri)
(write (oddp 7 ))
(terpri)
(write (zerop 0.0000000001))
(terpri)
(write (eq 3 3.0 ))
(terpri)
(write (equal 3 3.0 ))
(terpri)
(write (null nil ))

Когда вы выполняете код, он возвращает следующий результат —

T
NIL
T
NIL
T
NIL
NIL
NIL
T

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun factorial (num)
   (cond ((zerop num) 1)
      (t ( * num (factorial (- num 1))))
   )
)
(setq n 6)
(format t "~% Factorial ~d is: ~d" n (factorial n))

Когда вы выполняете код, он возвращает следующий результат —

Factorial 6 is: 720

ЛИСП — Номера

Common Lisp определяет несколько видов чисел. Тип данных номера включает в себя различные типы номеров, поддерживаемые LISP.

Типы номеров, поддерживаемые LISP:

  • Целые
  • Соотношения
  • Числа с плавающей точкой
  • Сложные числа

На следующей диаграмме показана иерархия чисел и различные числовые типы данных, доступные в LISP.

Числовые Типы

Различные числовые типы в LISP

В следующей таблице описаны данные различных типов номеров, доступные в LISP.

Sr.No. Тип данных и описание
1

Fixnum

Этот тип данных представляет целые числа, которые не слишком велики и в основном находятся в диапазоне от -215 до 215-1 (это зависит от машины)

2

bignum

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

3

соотношение

Представляет соотношение двух чисел в форме числитель / знаменатель. Функция / всегда выдает результат в соотношениях, когда ее аргументы являются целыми числами.

4

поплавок

Он представляет нецелые числа. Существует четыре типа данных с плавающей запятой с возрастающей точностью.

5

сложный

Он представляет собой комплексные числа, которые обозначены #c. Действительная и мнимая части могут быть как рациональными, так и числами с плавающей точкой.

Fixnum

Этот тип данных представляет целые числа, которые не слишком велики и в основном находятся в диапазоне от -215 до 215-1 (это зависит от машины)

bignum

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

соотношение

Представляет соотношение двух чисел в форме числитель / знаменатель. Функция / всегда выдает результат в соотношениях, когда ее аргументы являются целыми числами.

поплавок

Он представляет нецелые числа. Существует четыре типа данных с плавающей запятой с возрастающей точностью.

сложный

Он представляет собой комплексные числа, которые обозначены #c. Действительная и мнимая части могут быть как рациональными, так и числами с плавающей точкой.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (/ 1 2))
(terpri)
(write ( + (/ 1 2) (/ 3 4)))
(terpri)
(write ( + #c( 1 2) #c( 3 -4)))

Когда вы выполняете код, он возвращает следующий результат —

1/2
5/4
#C(4 -2)

Числовые функции

В следующей таблице описаны некоторые часто используемые числовые функции —

Sr.No. Описание функции
1

+, -, *, /

Соответствующие арифметические операции

2

грех, cos, загар, acos, асин, атан

Соответствующие тригонометрические функции.

3

Синх, Кош, Тан, Акош, Асин, Атанх

Соответствующие гиперболические функции.

4

ехр

Функция экспонирования. Рассчитывает е х

5

эксп

Функция возведения в степень, берет основание и власть и то и другое.

6

SQRT

Он рассчитывает квадратный корень из числа.

7

журнал

Логарифмическая функция. Если задан один параметр, то он вычисляет свой натуральный логарифм, в противном случае второй параметр используется в качестве базового.

8

сопряженный

Он рассчитывает комплексное сопряжение числа. В случае действительного числа он возвращает сам номер.

9

абс

Возвращает абсолютное значение (или величину) числа.

10

НОД

Он рассчитывает наибольший общий делитель заданных чисел.

11

LCM

Он рассчитывает наименьшее общее кратное заданных чисел.

12

isqrt

Это дает наибольшее целое число, меньшее или равное точному квадратному корню данного натурального числа.

13

пол, потолок, усеченный, круглый

Все эти функции принимают два аргумента как число и возвращают частное; floor возвращает наибольшее целое число, которое не больше, чем отношение, потолок выбирает меньшее целое число, которое больше, чем отношение, усечение выбирает целое число того же знака, что и отношение с наибольшим абсолютным значением, которое меньше абсолютного значения отношения, и округляет выбор целое число, наиболее близкое к отношению.

14

ffloor, fceiling, ftruncate, fround

Делает то же самое, что и выше, но возвращает частное как число с плавающей запятой.

15

мод, рем

Возвращает остаток в операции деления.

16

поплавок

Преобразует действительное число в число с плавающей запятой.

17

рациональный, рационализировать

Преобразует действительное число в рациональное число.

18

числитель, знаменатель

Возвращает соответствующие части рационального числа.

19

реалпарт, имагарт

Возвращает действительную и мнимую часть комплексного числа.

+, -, *, /

Соответствующие арифметические операции

грех, cos, загар, acos, асин, атан

Соответствующие тригонометрические функции.

Синх, Кош, Тан, Акош, Асин, Атанх

Соответствующие гиперболические функции.

ехр

Функция экспонирования. Рассчитывает е х

эксп

Функция возведения в степень, берет основание и власть и то и другое.

SQRT

Он рассчитывает квадратный корень из числа.

журнал

Логарифмическая функция. Если задан один параметр, то он вычисляет свой натуральный логарифм, в противном случае второй параметр используется в качестве базового.

сопряженный

Он рассчитывает комплексное сопряжение числа. В случае действительного числа он возвращает сам номер.

абс

Возвращает абсолютное значение (или величину) числа.

НОД

Он рассчитывает наибольший общий делитель заданных чисел.

LCM

Он рассчитывает наименьшее общее кратное заданных чисел.

isqrt

Это дает наибольшее целое число, меньшее или равное точному квадратному корню данного натурального числа.

пол, потолок, усеченный, круглый

Все эти функции принимают два аргумента как число и возвращают частное; floor возвращает наибольшее целое число, которое не больше, чем отношение, потолок выбирает меньшее целое число, которое больше, чем отношение, усечение выбирает целое число того же знака, что и отношение с наибольшим абсолютным значением, которое меньше абсолютного значения отношения, и округляет выбор целое число, наиболее близкое к отношению.

ffloor, fceiling, ftruncate, fround

Делает то же самое, что и выше, но возвращает частное как число с плавающей запятой.

мод, рем

Возвращает остаток в операции деления.

поплавок

Преобразует действительное число в число с плавающей запятой.

рациональный, рационализировать

Преобразует действительное число в рациональное число.

числитель, знаменатель

Возвращает соответствующие части рационального числа.

реалпарт, имагарт

Возвращает действительную и мнимую часть комплексного числа.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (/ 45 78))
(terpri)
(write (floor 45 78))
(terpri)
(write (/ 3456 75))
(terpri)
(write (floor 3456 75))
(terpri)
(write (ceiling 3456 75))
(terpri)
(write (truncate 3456 75))
(terpri)
(write (round 3456 75))
(terpri)
(write (ffloor 3456 75))
(terpri)
(write (fceiling 3456 75))
(terpri)
(write (ftruncate 3456 75))
(terpri)
(write (fround 3456 75))
(terpri)
(write (mod 3456 75))
(terpri)
(setq c (complex 6 7))
(write c)
(terpri)
(write (complex 5 -9))
(terpri)
(write (realpart c))
(terpri)
(write (imagpart c))

Когда вы выполняете код, он возвращает следующий результат —

15/26
0
1152/25
46
47
46
46
46.0
47.0
46.0
46.0
6
#C(6 7)
#C(5 -9)
6
7

ЛИСП — Персонажи

В LISP символы представлены как объекты данных типа символов.

Вы можете обозначить символьный объект, предшествующий # \ перед самим символом. Например, # \ a означает символ a.

Пробел и другие специальные символы могут быть обозначены предшествующим # \ перед именем символа. Например, # \ SPACE представляет символ пробела.

Следующий пример демонстрирует это —

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write 'a)
(terpri)
(write #\a)
(terpri)
(write-char #\a)
(terpri)
(write-char 'a)

Когда вы выполняете код, он возвращает следующий результат —

A
#\a
a
*** - WRITE-CHAR: argument A is not a character

Специальные символы

Common LISP позволяет использовать следующие специальные символы в вашем коде. Их называют полустандартными персонажами.

  • # \ Backspace
  • # \ Tab
  • # \ Linefeed
  • # \ Page
  • #\Вернуть
  • # \ Rubout

Функции сравнения символов

Функции и операторы числового сравнения, такие как <и>, не работают с символами. Common LISP предоставляет два других набора функций для сравнения символов в вашем коде.

Один набор чувствителен к регистру, а другой — без учета регистра.

В следующей таблице представлены функции —

Чувствительные к регистру функции Функции без учета регистра Описание
символ = углеродно равно Проверяет, равны ли все значения операндов или нет, если да, тогда условие становится истинным.
символ / = углеродно не равно Проверяет, все ли значения операндов различны или нет, если значения не равны, условие становится истинным.
символ < углеродно lessp Проверяет, монотонно ли уменьшаются значения операндов.
символ> углеродно greaterp Проверяет, монотонно ли увеличиваются значения операндов.
символ <= углеродно не-greaterp Проверяет, является ли значение любого левого операнда больше или равно значению следующего правого операнда, если да, тогда условие становится истинным.
символ> = углеродно не-lessp Проверяет, является ли значение любого левого операнда меньше или равно значению его правого операнда, если да, тогда условие становится истинным.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

; case-sensitive comparison
(write (char= #\a #\b))
(terpri)
(write (char= #\a #\a))
(terpri)
(write (char= #\a #\A))
(terpri)
   
;case-insensitive comparision
(write (char-equal #\a #\A))
(terpri)
(write (char-equal #\a #\b))
(terpri)
(write (char-lessp #\a #\b #\c))
(terpri)
(write (char-greaterp #\a #\b #\c))

Когда вы выполняете код, он возвращает следующий результат —

NIL
T
NIL
T
NIL
T
NIL

ЛИСП — Массивы

LISP позволяет вам определять одно- или многомерные массивы с помощью функции make-array . Массив может хранить любой объект LISP в качестве своих элементов.

Все массивы состоят из смежных областей памяти. Самый низкий адрес соответствует первому элементу, а самый высокий адрес — последнему.

Ранг

Количество измерений массива называется его рангом.

В LISP элемент массива задается последовательностью неотрицательных целочисленных индексов. Длина последовательности должна равняться рангу массива. Индексирование начинается с нуля.

Например, чтобы создать массив из 10 ячеек с именем my-array, мы можем написать:

(setf my-array (make-array '(10)))

Функция aref позволяет получить доступ к содержимому ячеек. Он принимает два аргумента: имя массива и значение индекса.

Например, чтобы получить доступ к содержимому десятой ячейки, мы пишем —

(aref my-array 9)

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (setf my-array (make-array '(10))))
(terpri)
(setf (aref my-array 0) 25)
(setf (aref my-array 1) 23)
(setf (aref my-array 2) 45)
(setf (aref my-array 3) 10)
(setf (aref my-array 4) 20)
(setf (aref my-array 5) 17)
(setf (aref my-array 6) 25)
(setf (aref my-array 7) 19)
(setf (aref my-array 8) 67)
(setf (aref my-array 9) 30)
(write my-array)

Когда вы выполняете код, он возвращает следующий результат —

#(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
#(25 23 45 10 20 17 25 19 67 30)

Пример 2

Давайте создадим массив 3 на 3.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setf x (make-array '(3 3) 
   :initial-contents '((0 1 2 ) (3 4 5) (6 7 8)))
)
(write x)

Когда вы выполняете код, он возвращает следующий результат —

#2A((0 1 2) (3 4 5) (6 7 8))

Пример 3

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq a (make-array '(4 3)))
(dotimes (i 4)
   (dotimes (j 3)
      (setf (aref a i j) (list i 'x j '= (* i j)))
   )
)
(dotimes (i 4)
   (dotimes (j 3)
      (print (aref a i j))
   )
)

Когда вы выполняете код, он возвращает следующий результат —

(0 X 0 = 0) 
(0 X 1 = 0) 
(0 X 2 = 0) 
(1 X 0 = 0) 
(1 X 1 = 1) 
(1 X 2 = 2) 
(2 X 0 = 0) 
(2 X 1 = 2) 
(2 X 2 = 4) 
(3 X 0 = 0) 
(3 X 1 = 3) 
(3 X 2 = 6)

Полный синтаксис для функции make-array

Функция make-array принимает много других аргументов. Давайте посмотрим на полный синтаксис этой функции —

make-array dimensions :element-type :initial-element :initial-contents :adjustable :fill-pointer  :displaced-to :displaced-index-offset

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

Sr.No. Аргумент и описание
1

размеры

Это дает размеры массива. Это число для одномерного массива и список для многомерного массива.

2

: элемент типа

Это спецификатор типа, значением по умолчанию является T, т.е. любой тип

3

: начально-элемент

Значение начальных элементов. Это создаст массив со всеми элементами, инициализированными к определенному значению.

4

: начально-контент

Исходный контент как объект.

5

: регулируемая

Это помогает в создании изменяемого размера (или настраиваемого) вектора, базовая память которого может быть изменена. Аргумент является логическим значением, указывающим, является ли массив регулируемым или нет, значение по умолчанию равно NIL.

6

: заполняющая указатель

Он отслеживает количество элементов, фактически сохраненных в векторе с изменяемыми размерами.

7

: смещаются к

Это помогает в создании смещенного массива или общего массива, который делится своим содержимым с указанным массивом. Оба массива должны иметь одинаковый тип элемента. Опция: displaced-to не может использоваться с опцией: initial-element или: initial-contents. Этот аргумент по умолчанию равен нулю.

8

: перемещенный-индекс-смещение

Это дает смещение индекса созданного общего массива.

размеры

Это дает размеры массива. Это число для одномерного массива и список для многомерного массива.

: элемент типа

Это спецификатор типа, значением по умолчанию является T, т.е. любой тип

: начально-элемент

Значение начальных элементов. Это создаст массив со всеми элементами, инициализированными к определенному значению.

: начально-контент

Исходный контент как объект.

: регулируемая

Это помогает в создании изменяемого размера (или настраиваемого) вектора, базовая память которого может быть изменена. Аргумент является логическим значением, указывающим, является ли массив регулируемым или нет, значение по умолчанию равно NIL.

: заполняющая указатель

Он отслеживает количество элементов, фактически сохраненных в векторе с изменяемыми размерами.

: смещаются к

Это помогает в создании смещенного массива или общего массива, который делится своим содержимым с указанным массивом. Оба массива должны иметь одинаковый тип элемента. Опция: displaced-to не может использоваться с опцией: initial-element или: initial-contents. Этот аргумент по умолчанию равен нулю.

: перемещенный-индекс-смещение

Это дает смещение индекса созданного общего массива.

Пример 4

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq myarray (make-array '(3 2 3) 
   :initial-contents 
   '(((a b c) (1 2 3)) 
      ((d e f) (4 5 6)) 
      ((g h i) (7 8 9)) 
   ))
) 
(setq array2 (make-array 4 :displaced-to myarray :displaced-index-offset 2)) 
(write myarray)
(terpri)
(write array2)

Когда вы выполняете код, он возвращает следующий результат —

#3A(((A B C) (1 2 3)) ((D E F) (4 5 6)) ((G H I) (7 8 9)))
#(C 1 2 3)

Если смещенный массив является двумерным —

Live Demo

(setq myarray (make-array '(3 2 3) 
   :initial-contents 
   '(((a b c) (1 2 3)) 
      ((d e f) (4 5 6)) 
      ((g h i) (7 8 9)) 
   ))
) 
(setq array2 (make-array '(3 2) :displaced-to myarray :displaced-index-offset 2)) 
(write myarray)
(terpri)
(write array2)

Когда вы выполняете код, он возвращает следующий результат —

#3A(((A B C) (1 2 3)) ((D E F) (4 5 6)) ((G H I) (7 8 9)))
#2A((C 1) (2 3) (D E))

Давайте изменим смещение смещенного индекса на 5 —

Live Demo

(setq myarray (make-array '(3 2 3) 
   :initial-contents 
   '(((a b c) (1 2 3)) 
      ((d e f) (4 5 6)) 
      ((g h i) (7 8 9)) 
   ))
) 
(setq array2 (make-array '(3 2) :displaced-to myarray :displaced-index-offset 5)) 
(write myarray)
(terpri)
(write array2)

Когда вы выполняете код, он возвращает следующий результат —

#3A(((A B C) (1 2 3)) ((D E F) (4 5 6)) ((G H I) (7 8 9)))
#2A((3 D) (E F) (4 5))

Пример 5

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

;a one dimensional array with 5 elements, 
;initail value 5
(write (make-array 5 :initial-element 5))
(terpri)

;two dimensional array, with initial element a
(write (make-array '(2 3) :initial-element 'a))
(terpri)

;an array of capacity 14, but fill pointer 5, is 5
(write(length (make-array 14 :fill-pointer 5)))
(terpri)

;however its length is 14
(write (array-dimensions (make-array 14 :fill-pointer 5)))
(terpri)

; a bit array with all initial elements set to 1
(write(make-array 10 :element-type 'bit :initial-element 1))
(terpri)

; a character array with all initial elements set to a
; is a string actually
(write(make-array 10 :element-type 'character :initial-element #\a)) 
(terpri)

; a two dimensional array with initial values a
(setq myarray (make-array '(2 2) :initial-element 'a :adjustable t))
(write myarray)
(terpri)

;readjusting the array
(adjust-array myarray '(1 3) :initial-element 'b) 
(write myarray)

Когда вы выполняете код, он возвращает следующий результат —

#(5 5 5 5 5)
#2A((A A A) (A A A))
5
(14)
#*1111111111
"aaaaaaaaaa"
#2A((A A) (A A))
#2A((A A B))

ЛИСП — Струны

Строки в Common Lisp являются векторами, то есть одномерным массивом символов.

Строковые литералы заключены в двойные кавычки. Любой символ, поддерживаемый набором символов, может быть заключен в двойные кавычки для создания строки, кроме символа двойной кавычки («) и escape-символа (\). Однако их можно включить, экранируя их обратной косой чертой (\).

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line "Hello World")
(write-line "Welcome to Tutorials Point")

;escaping the double quote character
(write-line "Welcome to \"Tutorials Point\"")

Когда вы выполняете код, он возвращает следующий результат —

Hello World
Welcome to Tutorials Point
Welcome to "Tutorials Point"

Функции сравнения строк

Числовые функции сравнения и операторы, такие как <и>, не работают со строками. Common LISP предоставляет два других набора функций для сравнения строк в вашем коде. Один набор чувствителен к регистру, а другой — без учета регистра.

В следующей таблице представлены функции —

Чувствительные к регистру функции Функции без учета регистра Описание
строка = строка равных Проверяет, равны ли все значения операндов или нет, если да, тогда условие становится истинным.
Строка / = Строковое не равно Проверяет, все ли значения операндов различны или нет, если значения не равны, условие становится истинным.
строка < строка-lessp Проверяет, монотонно ли уменьшаются значения операндов.
строка> строка-greaterp Проверяет, монотонно ли увеличиваются значения операндов.
строка <= строка-не-greaterp Проверяет, является ли значение любого левого операнда больше или равно значению следующего правого операнда, если да, тогда условие становится истинным.
строка> = строка-не-lessp Проверяет, является ли значение любого левого операнда меньше или равно значению его правого операнда, если да, тогда условие становится истинным.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

; case-sensitive comparison
(write (string= "this is test" "This is test"))
(terpri)
(write (string> "this is test" "This is test"))
(terpri)
(write (string< "this is test" "This is test"))
(terpri)

;case-insensitive comparision
(write (string-equal "this is test" "This is test"))
(terpri)
(write (string-greaterp "this is test" "This is test"))
(terpri)
(write (string-lessp "this is test" "This is test"))
(terpri)

;checking non-equal
(write (string/= "this is test" "this is Test"))
(terpri)
(write (string-not-equal "this is test" "This is test"))
(terpri)
(write (string/= "lisp" "lisping"))
(terpri)
(write (string/= "decent" "decency"))

Когда вы выполняете код, он возвращает следующий результат —

NIL
0
NIL
T
NIL
NIL
8
NIL
4
5

Функции управления делами

В следующей таблице описаны функции управления делами —

Sr.No. Описание функции
1

строка-Upcase

Преобразует строку в верхний регистр

2

строка-downcase

Преобразует строку в нижний регистр

3

строка-капитализировать

Прописывает каждое слово в строке

строка-Upcase

Преобразует строку в верхний регистр

строка-downcase

Преобразует строку в нижний регистр

строка-капитализировать

Прописывает каждое слово в строке

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line (string-upcase "a big hello from tutorials point"))
(write-line (string-capitalize "a big hello from tutorials point"))

Когда вы выполняете код, он возвращает следующий результат —

A BIG HELLO FROM TUTORIALS POINT
A Big Hello From Tutorials Point

Обрезка струн

В следующей таблице описаны функции обрезки строк —

Sr.No. Описание функции
1

строка-отделка

Он принимает строку символов в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы в первом аргументе удаляются из строки аргумента.

2

Строка-левая отделка

Он принимает строку символов (символов) в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы, содержащиеся в первом аргументе, удаляются из начала строки аргумента.

3

Строка-правая облицовка

Он принимает символ (ы) строки в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы, содержащиеся в первом аргументе, удаляются из конца строки аргумента.

строка-отделка

Он принимает строку символов в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы в первом аргументе удаляются из строки аргумента.

Строка-левая отделка

Он принимает строку символов (символов) в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы, содержащиеся в первом аргументе, удаляются из начала строки аргумента.

Строка-правая облицовка

Он принимает символ (ы) строки в качестве первого аргумента и строку в качестве второго аргумента и возвращает подстроку, в которой все символы, содержащиеся в первом аргументе, удаляются из конца строки аргумента.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line (string-trim " " "   a big hello from tutorials point   "))
(write-line (string-left-trim " " "   a big hello from tutorials point   "))
(write-line (string-right-trim " " "   a big hello from tutorials point   "))
(write-line (string-trim " a" "   a big hello from tutorials point   "))

Когда вы выполняете код, он возвращает следующий результат —

a big hello from tutorials point
a big hello from tutorials point   
   a big hello from tutorials point
big hello from tutorials point

Другие строковые функции

Строки в LISP являются массивами и, следовательно, также последовательностями. Мы рассмотрим эти типы данных в следующих уроках. Все функции, применимые к массивам и последовательностям, также применимы к строкам. Однако мы продемонстрируем некоторые часто используемые функции на различных примерах.

Расчет длины

Функция length вычисляет длину строки.

Извлечение подстроки

Функция subseq возвращает подстроку (поскольку строка также является последовательностью), начиная с определенного индекса и продолжаясь до определенного конечного индекса или конца строки.

Доступ к символу в строке

Функция char позволяет получить доступ к отдельным символам строки.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (length "Hello World"))
(terpri)
(write-line (subseq "Hello World" 6))
(write (char "Hello World" 6))

Когда вы выполняете код, он возвращает следующий результат —

11
World
#\W

Сортировка и объединение строк

Функция сортировки позволяет сортировать строку. Он принимает последовательность (вектор или строку) и предикат с двумя аргументами и возвращает отсортированную версию последовательности.

Функция слияния принимает две последовательности и предикат и возвращает последовательность, созданную путем слияния двух последовательностей, в соответствии с предикатом.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

;sorting the strings
(write (sort (vector "Amal" "Akbar" "Anthony") #'string<))
(terpri)

;merging the strings
(write (merge 'vector (vector "Rishi" "Zara" "Priyanka") 
   (vector "Anju" "Anuj" "Avni") #'string<))

Когда вы выполняете код, он возвращает следующий результат —

#("Akbar" "Amal" "Anthony")
#("Anju" "Anuj" "Avni" "Rishi" "Zara" "Priyanka")

Сторнирование строки

Функция reverse переворачивает строку.

Например, создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line (reverse "Are we not drawn onward, we few, drawn onward to new era"))

Когда вы выполняете код, он возвращает следующий результат —

are wen ot drawno nward ,wef ew ,drawno nward ton ew erA

Конкатенация строк

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

Например, создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write-line (concatenate 'string "Are we not drawn onward, " "we few, drawn onward to new era"))

Когда вы выполняете код, он возвращает следующий результат —

Are we not drawn onward, we few, drawn onward to new era

LISP — последовательности

Последовательность — это абстрактный тип данных в LISP. Векторы и списки являются двумя конкретными подтипами этого типа данных. Все функциональные возможности, определенные для типа данных последовательности, фактически применяются ко всем векторам и типам списков.

В этом разделе мы обсудим наиболее часто используемые функции на последовательностях.

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

Создание последовательности

Функция make-sequence позволяет создавать последовательности любого типа. Синтаксис этой функции —

make-sequence sqtype sqsize &key :initial-element

Он создает последовательность типа sqtype и длины sqsize.

При желании вы можете указать какое-либо значение с помощью аргумента : initial-element , тогда каждый из элементов будет инициализирован этим значением.

Например, создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (make-sequence '(vector float) 
   10 
   :initial-element 1.0))

Когда вы выполняете код, он возвращает следующий результат —

#(1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)

Общие функции на последовательностях

Sr.No. Описание функции
1

еи

Это позволяет получить доступ к отдельным элементам через целочисленный индекс.

2

длина

Возвращает длину последовательности.

3

после-

Он возвращает подпоследовательность путем извлечения подпоследовательности, начинающейся с определенного индекса и продолжающейся до определенного конечного индекса или конца последовательности.

4

Копия-сл

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

5

заполнить

Он используется для установки нескольких элементов последовательности на одно значение.

6

замещать

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

7

подсчитывать

Он берет элемент и последовательность и возвращает количество раз, когда элемент появляется в последовательности.

8

задний ход

Возвращает последовательность, содержащую те же элементы аргумента, но в обратном порядке.

9

nreverse

Возвращает ту же последовательность, содержащую те же элементы, что и последовательность, но в обратном порядке.

10

сцеплять

Он создает новую последовательность, содержащую конкатенацию любого количества последовательностей.

11

позиция

Он принимает элемент и последовательность и возвращает индекс элемента в последовательности или ноль.

12

находить

Требуется предмет и последовательность. Он находит элемент в последовательности и возвращает его, если не найден, то возвращает ноль.

13

Сортировать

Он принимает последовательность и предикат с двумя аргументами и возвращает отсортированную версию последовательности.

14

сливаться

Он принимает две последовательности и предикат и возвращает последовательность, созданную путем слияния двух последовательностей в соответствии с предикатом.

15

карта

Он принимает функцию с n аргументами и n последовательностей и возвращает новую последовательность, содержащую результат применения функции к последующим элементам последовательностей.

16

немного

Он принимает предикат в качестве аргумента и выполняет итерацию по последовательности аргументов и возвращает первое не-NIL-значение, возвращаемое предикатом, или возвращает false, если предикат никогда не выполняется.

17

каждый

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

18

notany

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

19

не каждый

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

20

уменьшить

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

21

поиск

Он ищет последовательность, чтобы найти один или несколько элементов, удовлетворяющих некоторому критерию.

22

Удалить

Он принимает элемент и последовательность и возвращает последовательность с удаленными экземплярами элемента.

23

удалять

Это также берет элемент и последовательность и возвращает последовательность того же вида, что и последовательность аргументов, которая имеет те же элементы, кроме элемента.

24

замена

Он принимает новый элемент, существующий элемент и последовательность и возвращает последовательность с экземплярами существующего элемента, замененными новым элементом.

25

nsubstitute

Он принимает новый элемент, существующий элемент и последовательность и возвращает ту же последовательность с экземплярами существующего элемента, замененными новым элементом.

26

несоответствие

Он принимает две последовательности и возвращает индекс первой пары несовпадающих элементов.

еи

Это позволяет получить доступ к отдельным элементам через целочисленный индекс.

длина

Возвращает длину последовательности.

после-

Он возвращает подпоследовательность путем извлечения подпоследовательности, начинающейся с определенного индекса и продолжающейся до определенного конечного индекса или конца последовательности.

Копия-сл

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

заполнить

Он используется для установки нескольких элементов последовательности на одно значение.

замещать

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

подсчитывать

Он берет элемент и последовательность и возвращает количество раз, когда элемент появляется в последовательности.

задний ход

Возвращает последовательность, содержащую те же элементы аргумента, но в обратном порядке.

nreverse

Возвращает ту же последовательность, содержащую те же элементы, что и последовательность, но в обратном порядке.

сцеплять

Он создает новую последовательность, содержащую конкатенацию любого количества последовательностей.

позиция

Он принимает элемент и последовательность и возвращает индекс элемента в последовательности или ноль.

находить

Требуется предмет и последовательность. Он находит элемент в последовательности и возвращает его, если не найден, то возвращает ноль.

Сортировать

Он принимает последовательность и предикат с двумя аргументами и возвращает отсортированную версию последовательности.

сливаться

Он принимает две последовательности и предикат и возвращает последовательность, созданную путем слияния двух последовательностей в соответствии с предикатом.

карта

Он принимает функцию с n аргументами и n последовательностей и возвращает новую последовательность, содержащую результат применения функции к последующим элементам последовательностей.

немного

Он принимает предикат в качестве аргумента и выполняет итерацию по последовательности аргументов и возвращает первое не-NIL-значение, возвращаемое предикатом, или возвращает false, если предикат никогда не выполняется.

каждый

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

notany

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

не каждый

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

уменьшить

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

поиск

Он ищет последовательность, чтобы найти один или несколько элементов, удовлетворяющих некоторому критерию.

Удалить

Он принимает элемент и последовательность и возвращает последовательность с удаленными экземплярами элемента.

удалять

Это также берет элемент и последовательность и возвращает последовательность того же вида, что и последовательность аргументов, которая имеет те же элементы, кроме элемента.

замена

Он принимает новый элемент, существующий элемент и последовательность и возвращает последовательность с экземплярами существующего элемента, замененными новым элементом.

nsubstitute

Он принимает новый элемент, существующий элемент и последовательность и возвращает ту же последовательность с экземплярами существующего элемента, замененными новым элементом.

несоответствие

Он принимает две последовательности и возвращает индекс первой пары несовпадающих элементов.

Аргументы ключевых слов стандартной последовательности функций

аргументация Имея в виду Значение по умолчанию
:тестовое задание Это функция с двумя аргументами, используемая для сравнения элемента (или значения, извлеченного функцией key) с элементом. EQL
: ключ Функция с одним аргументом для извлечения значения ключа из фактического элемента последовательности. NIL означает использовать элемент как есть. NIL
:Начните Начальный индекс (включительно) подпоследовательности. 0
:конец Конечный индекс (исключающий) подпоследовательности. NIL указывает на конец последовательности. NIL
: От конца Если true, последовательность будет проходить в обратном порядке, от конца к началу. NIL
: граф Число, указывающее количество элементов, которые необходимо удалить или заменить, или NIL, чтобы указать все (только УДАЛИТЬ и ЗАМЕНИТЬ). NIL

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

Найти длину и элемент

Функция length возвращает длину последовательности, а функция elt позволяет получить доступ к отдельным элементам с помощью целочисленного индекса.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq x (vector 'a 'b 'c 'd 'e))
(write (length x))
(terpri)
(write (elt x 3))

Когда вы выполняете код, он возвращает следующий результат —

5
D

Изменение последовательности

Некоторые функции последовательности позволяют выполнять итерацию по последовательности и выполнять некоторые операции, такие как поиск, удаление, подсчет или фильтрация определенных элементов без написания явных циклов.

Следующий пример демонстрирует это —

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (count 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (remove 5 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (delete 5 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (substitute 10 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (find 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (position 5 '(1 5 6 7 8 9 2 7 3 4 5)))

Когда вы выполняете код, он возвращает следующий результат —

2
(1 6 7 8 9 2 7 3 4)
(1 6 7 8 9 2 7 3 4)
(1 5 6 10 8 9 2 10 3 4 5)
7
1

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (delete-if #'oddp '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (delete-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (remove-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5) :count 1 :from-end t))
(terpri)
(setq x (vector 'a 'b 'c 'd 'e 'f 'g))
(fill x 'p :start 1 :end 4)
(write x)

Когда вы выполняете код, он возвращает следующий результат —

(6 8 2 4)
(1 5 7 9 7 3 5)
(1 5 6 7 8 9 2 7 3 5)
#(A P P P E F G)

Сортировка и объединение последовательностей

Функции сортировки принимают последовательность и предикат с двумя аргументами и возвращают отсортированную версию последовательности.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'<))
(terpri)
(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'>))
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

(1 2 3 3 4 4 5 6 7 8 9)
(9 8 7 6 5 4 4 3 3 2 1)

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (merge 'vector #(1 3 5) #(2 4 6) #'<))
(terpri)
(write (merge 'list #(1 3 5) #(2 4 6) #'<))
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

#(1 2 3 4 5 6)
(1 2 3 4 5 6)

Предикаты последовательности

Функции every, some, notany и notevery называются предикатами последовательности.

Эти функции перебирают последовательности и проверяют логический предикат.

Все эти функции принимают предикат в качестве первого аргумента, а остальные аргументы являются последовательностями.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (every #'evenp #(2 4 6 8 10)))
(terpri)
(write (some #'evenp #(2 4 6 8 10 13 14)))
(terpri)
(write (every #'evenp #(2 4 6 8 10 13 14)))
(terpri)
(write (notany #'evenp #(2 4 6 8 10)))
(terpri)
(write (notevery #'evenp #(2 4 6 8 10 13 14)))
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

T
T
NIL
NIL
T

Последовательности картирования

Мы уже обсуждали функции отображения. Точно так же функция map позволяет применять функцию к последующим элементам одной или нескольких последовательностей.

Функция map принимает функцию с n аргументами и n последовательностей и возвращает новую последовательность после применения функции к последующим элементам последовательностей.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (map 'vector #'* #(2 3 4 5) #(3 5 4 8)))

Когда вы выполняете код, он возвращает следующий результат —

#(6 15 16 40)

LISP — Списки

Списки были самой важной и основной составной структурой данных в традиционном LISP. На сегодняшний день Common LISP предоставляет другие структуры данных, такие как вектор, хеш-таблица, классы или структуры.

Списки — это отдельные связанные списки. В LISP списки строятся в виде цепочки простой структуры записей с именем cons, связанной вместе.

Минусы Запись Структура

Минусы — это структура записи, содержащая два компонента, которые называются car и cdr.

Минусы ячейки или минусы — это объекты значений пар, которые создаются с помощью функции cons.

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

Если второе значение не равно nil или другой cons-ячейке, то значения печатаются в виде пунктирной пары, заключенной в скобки.

Два значения в ячейке cons называются car и cdr. Функция car используется для доступа к первому значению, а функция cdr — для доступа ко второму значению.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (cons 1 2))
(terpri)
(write (cons 'a 'b))
(terpri)
(write (cons 1 nil))
(terpri)
(write (cons 1 (cons 2 nil)))
(terpri)
(write (cons 1 (cons 2 (cons 3 nil))))
(terpri)
(write (cons 'a (cons 'b (cons 'c nil))))
(terpri)
(write ( car (cons 'a (cons 'b (cons 'c nil)))))
(terpri)
(write ( cdr (cons 'a (cons 'b (cons 'c nil)))))

Когда вы выполняете код, он возвращает следующий результат —

(1 . 2)
(A . B)
(1)
(1 2)
(1 2 3)
(A B C)
A
(B C)

Вышеприведенный пример показывает, как структуры cons могут использоваться для создания единого связанного списка, например, список (ABC) состоит из трех cons-ячеек, связанных друг с другом их cdrs .

Схематически это можно выразить как —

Списки в LISP

Хотя cons-ячейки могут использоваться для создания списков, построение списка из вложенных вызовов функции cons не может быть лучшим решением. Функция списка скорее используется для создания списков в LISP.

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

Первая и остальные функции дают первый элемент и остальную часть списка. Следующие примеры демонстрируют концепции.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (list 1 2))
(terpri)
(write (list 'a 'b))
(terpri)
(write (list 1 nil))
(terpri)
(write (list 1 2 3))
(terpri)
(write (list 'a 'b 'c))
(terpri)
(write (list 3 4 'a (car '(b . c)) (* 4 -2)))
(terpri)
(write (list (list 'a 'b) (list 'c 'd 'e)))

Когда вы выполняете код, он возвращает следующий результат —

(1 2)
(A B)
(1 NIL)
(1 2 3)
(A B C)
(3 4 A B -8)
((A B) (C D E))

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun my-library (title author rating availability)
   (list :title title :author author :rating rating :availabilty availability)
)

(write (getf (my-library "Hunger Game" "Collins" 9 t) :title))

Когда вы выполняете код, он возвращает следующий результат —

"Hunger Game"

Функции управления списком

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

Sr.No. Описание функции
1

автомобиль

Он принимает список в качестве аргумента и возвращает свой первый элемент.

2

корд

Он принимает список в качестве аргумента и возвращает список без первого элемента

3

минусы

Он принимает два аргумента, элемент и список, и возвращает список с элементом, вставленным на первое место.

4

список

Он принимает любое количество аргументов и возвращает список с аргументами в качестве элементов-членов списка.

5

присоединять

Он объединяет два или более списка в один.

6

прошлой

Он берет список и возвращает список, содержащий последний элемент.

7

член

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

8

задний ход

Он берет список и возвращает список с верхними элементами в обратном порядке.

автомобиль

Он принимает список в качестве аргумента и возвращает свой первый элемент.

корд

Он принимает список в качестве аргумента и возвращает список без первого элемента

минусы

Он принимает два аргумента, элемент и список, и возвращает список с элементом, вставленным на первое место.

список

Он принимает любое количество аргументов и возвращает список с аргументами в качестве элементов-членов списка.

присоединять

Он объединяет два или более списка в один.

прошлой

Он берет список и возвращает список, содержащий последний элемент.

член

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

задний ход

Он берет список и возвращает список с верхними элементами в обратном порядке.

Обратите внимание, что все функции последовательности применимы к спискам.

Пример 3

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (car '(a b c d e f)))
(terpri)
(write (cdr '(a b c d e f)))
(terpri)
(write (cons 'a '(b c)))
(terpri)
(write (list 'a '(b c) '(e f)))
(terpri)
(write (append '(b c) '(e f) '(p q) '() '(g)))
(terpri)
(write (last '(a b c d (e f))))
(terpri)
(write (reverse '(a b c d (e f))))

Когда вы выполняете код, он возвращает следующий результат —

A
(B C D E F)
(A B C)
(A (B C) (E F))
(B C E F P Q G)
((E F))
((E F) D C B A)

Конкатенация автомобилей и CDR Функции

Функции car и cdr и их комбинация позволяют извлечь любой конкретный элемент / элемент списка.

Однако последовательности функций car и cdr можно сократить, объединив букву a для car и d для cdr внутри букв c и r.

Например, мы можем написать cadadr для сокращения последовательности вызовов функций — car cdr car cdr.

Таким образом, (cadadr ‘(a (cd) (efg))) вернет d

Пример 4

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (cadadr '(a (c d) (e f g))))
(terpri)
(write (caar (list (list 'a 'b) 'c)))   
(terpri)
(write (cadr (list (list 1 2) (list 3 4))))
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

D
A
(3 4)

ЛИСП — Символы

В LISP символ — это имя, которое представляет объекты данных и, что интересно, это также объект данных.

Что делает символы особенными, так это то, что они имеют компонент, называемый списком свойств или списком свойств.

Списки недвижимости

LISP позволяет назначать свойства символам. Например, пусть у нас есть объект person. Нам бы хотелось, чтобы этот объект «человек» имел такие свойства, как имя, пол, рост, вес, адрес, профессия и т. Д. Свойство похоже на имя атрибута.

Список свойств реализован как список с четным числом (возможно, нулем) элементов. Каждая пара элементов в списке представляет собой запись; первый элемент — индикатор, а второй — значение.

Когда символ создан, его список свойств изначально пуст. Свойства создаются с помощью get в форме setf .

Например, следующие операторы позволяют нам назначать свойства title, author и издатель и соответствующие значения для объекта с именем (symbol) ‘book’.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (setf (get 'books'title) '(Gone with the Wind)))
(terpri)
(write (setf (get 'books 'author) '(Margaret Michel)))
(terpri)
(write (setf (get 'books 'publisher) '(Warner Books)))

Когда вы выполняете код, он возвращает следующий результат —

(GONE WITH THE WIND)
(MARGARET MICHEL)
(WARNER BOOKS)

Различные функции списка свойств позволяют назначать свойства, а также извлекать, заменять или удалять свойства символа.

Функция get возвращает список свойств символа для данного индикатора. Он имеет следующий синтаксис —

get symbol indicator &optional default

Функция get ищет список свойств данного символа для указанного индикатора, если найден, то возвращает соответствующее значение; в противном случае возвращается значение по умолчанию (или ноль, если значение по умолчанию не указано).

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setf (get 'books 'title) '(Gone with the Wind))
(setf (get 'books 'author) '(Margaret Micheal))
(setf (get 'books 'publisher) '(Warner Books))

(write (get 'books 'title))
(terpri)
(write (get 'books 'author))
(terpri)
(write (get 'books 'publisher))

Когда вы выполняете код, он возвращает следующий результат —

(GONE WITH THE WIND)
(MARGARET MICHEAL)
(WARNER BOOKS)

Функция symbol-plist позволяет увидеть все свойства символа.

Пример 3

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setf (get 'annie 'age) 43)
(setf (get 'annie 'job) 'accountant)
(setf (get 'annie 'sex) 'female)
(setf (get 'annie 'children) 3)

(terpri)
(write (symbol-plist 'annie))

Когда вы выполняете код, он возвращает следующий результат —

(CHILDREN 3 SEX FEMALE JOB ACCOUNTANT AGE 43)

Функция remprop удаляет указанное свойство из символа.

Пример 4

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setf (get 'annie 'age) 43)
(setf (get 'annie 'job) 'accountant)
(setf (get 'annie 'sex) 'female)
(setf (get 'annie 'children) 3)

(terpri)
(write (symbol-plist 'annie))
(remprop 'annie 'age)
(terpri)
(write (symbol-plist 'annie))

Когда вы выполняете код, он возвращает следующий результат —

(CHILDREN 3 SEX FEMALE JOB ACCOUNTANT AGE 43)
(CHILDREN 3 SEX FEMALE JOB ACCOUNTANT)

ЛИСП — Векторы

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

Создание векторов

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

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setf v1 (vector 1 2 3 4 5))
(setf v2 #(a b c d e))
(setf v3 (vector 'p 'q 'r 's 't))

(write v1)
(terpri)
(write v2)
(terpri)
(write v3)

Когда вы выполняете код, он возвращает следующий результат —

#(1 2 3 4 5)
#(A B C D E)
#(P Q R S T)

Обратите внимание, что LISP использует синтаксис # (…) в качестве литеральной записи для векторов. Вы можете использовать этот синтаксис # (…) для создания и включения литеральных векторов в ваш код.

Однако это буквальные векторы, поэтому их изменение не определено в LISP. Поэтому для программирования вы всегда должны использовать векторную функцию или более общую функцию make-array для создания векторов, которые вы планируете изменить.

Функция make-array является более общим способом создания вектора. Вы можете получить доступ к векторным элементам, используя функцию aref .

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq a (make-array 5 :initial-element 0))
(setq b (make-array 5 :initial-element 2))

(dotimes (i 5)
   (setf (aref a i) i))
   
(write a)
(terpri)
(write b)
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

#(0 1 2 3 4)
#(2 2 2 2 2)

Заполнить указатель

Функция make-array позволяет вам создавать изменяемый размер вектора.

Аргумент fill-pointer функции отслеживает количество элементов, фактически сохраненных в векторе. Это индекс следующей позиции, которая будет заполнена при добавлении элемента в вектор.

Функция векторного нажатия позволяет добавить элемент в конец изменяемого размера вектора. Увеличивает указатель заполнения на 1.

Функция vector-pop возвращает последний добавленный элемент и уменьшает указатель заполнения на 1.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq a (make-array 5 :fill-pointer 0))
(write a)

(vector-push 'a a)
(vector-push 'b a)
(vector-push 'c a)

(terpri)
(write a)
(terpri)

(vector-push 'd a)
(vector-push 'e a)

;this will not be entered as the vector limit is 5
(vector-push 'f a)

(write a)
(terpri)

(vector-pop a)
(vector-pop a)
(vector-pop a)

(write a)

Когда вы выполняете код, он возвращает следующий результат —

#()
#(A B C)
#(A B C D E)
#(A B)

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

LISP — Набор

Common Lisp не предоставляет установленный тип данных. Однако он предоставляет ряд функций, позволяющих выполнять операции над списком.

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

Реализация наборов в LISP

Наборы, подобные спискам, обычно реализуются в терминах cons-ячеек. Однако именно по этой причине операции с множествами становятся все менее эффективными, чем больше сеты.

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

Примыкающая функция сначала ищет элемент в данном списке, если он найден, затем возвращает исходный список; в противном случае он создает новую ячейку cons со своим автомобилем в качестве элемента и cdr, указывающим на исходный список, и возвращает этот новый список.

Примыкающая функция также принимает аргументы : key и : test key . Эти аргументы используются для проверки наличия элемента в исходном списке.

Поскольку функция примыкания не изменяет исходный список, чтобы внести изменения в сам список, необходимо либо присвоить значение, возвращаемое примыканием, к исходному списку, либо использовать макрос pushnew для добавления элемента в набор.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

; creating myset as an empty list
(defparameter *myset* ())
(adjoin 1 *myset*)
(adjoin 2 *myset*)

; adjoin did not change the original set
;so it remains same
(write *myset*)
(terpri)
(setf *myset* (adjoin 1 *myset*))
(setf *myset* (adjoin 2 *myset*))

;now the original set is changed
(write *myset*)
(terpri)

;adding an existing value
(pushnew 2 *myset*)

;no duplicate allowed
(write *myset*)
(terpri)

;pushing a new value
(pushnew 3 *myset*)
(write *myset*)
(terpri)

Когда вы выполняете код, он возвращает следующий результат —

NIL
(2 1)
(2 1)
(3 2 1)

Проверка членства

Группа функций-членов позволяет вам проверить, является ли элемент членом набора или нет.

Ниже приведены синтаксисы этих функций —

member item list &key :test :test-not :key 
member-if predicate list &key :key 
member-if-not predicate list &key :key

Эти функции выполняют поиск в указанном списке для данного элемента, который удовлетворяет критерию. Если такой элемент не найден, функции возвращают ноль. В противном случае возвращается хвост списка с элементом в качестве первого элемента.

Поиск ведется только на верхнем уровне.

Эти функции могут быть использованы в качестве предикатов.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(write (member 'zara '(ayan abdul zara riyan nuha)))
(terpri)
(write (member-if #'evenp '(3 7 2 5/3 'a)))
(terpri)
(write (member-if-not #'numberp '(3 7 2 5/3 'a 'b 'c)))

Когда вы выполняете код, он возвращает следующий результат —

(ZARA RIYAN NUHA)
(2 5/3 'A)
('A 'B 'C)

Установить Союз

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

Ниже приведены синтаксисы этих функций —

union list1 list2 &key :test :test-not :key 
nunion list1 list2 &key :test :test-not :key

Функция union принимает два списка и возвращает новый список, содержащий все элементы, присутствующие в любом из списков. Если есть дубликаты, то в возвращенном списке сохраняется только одна копия члена.

Функция nunion выполняет ту же операцию, но может уничтожить списки аргументов.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq set1 (union '(a b c) '(c d e)))
(setq set2 (union '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
       
(setq set3 (union '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

Когда вы выполняете код, он возвращает следующий результат —

(A B C D E)
(#(F H) #(5 6 7) #(A B) #(G H))
(#(A B) #(5 6 7) #(F H) #(5 6 7) #(A B) #(G H))

Пожалуйста, обратите внимание

Функция объединения не работает должным образом без : test-not # ‘несоответствующие аргументы для списка из трех векторов. Это потому, что списки состоят из cons-ячеек, и, хотя значения выглядят одинаково для нас, очевидно, cdr- часть ячеек не совпадает, поэтому они не совсем совпадают с интерпретатором / компилятором LISP. Это причина; реализация больших наборов не рекомендуется при использовании списков. Это работает хорошо для небольших наборов, хотя.

Установить пересечение

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

Ниже приведены синтаксисы этих функций —

intersection list1 list2 &key :test :test-not :key 
nintersection list1 list2 &key :test :test-not :key

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

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq set1 (intersection '(a b c) '(c d e)))
(setq set2 (intersection '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
       
(setq set3 (intersection '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

Когда вы выполняете код, он возвращает следующий результат —

(C)
(#(A B) #(5 6 7))
NIL

Функция пересечения является деструктивной версией пересечения, то есть она может уничтожить исходные списки.

Установить разницу

Группа функций разности множеств позволяет выполнять разности множеств в двух списках, представленных в качестве аргументов этих функций на основе теста.

Ниже приведены синтаксисы этих функций —

set-difference list1 list2 &key :test :test-not :key 
nset-difference list1 list2 &key :test :test-not :key

Функция set-Difference возвращает список элементов первого списка, которые не отображаются во втором списке.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq set1 (set-difference '(a b c) '(c d e)))
(setq set2 (set-difference '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
(setq set3 (set-difference '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

Когда вы выполняете код, он возвращает следующий результат —

(A B)
(#(F H))
(#(A B) #(5 6 7) #(F H))

ЛИСП — Дерево

Вы можете строить древовидные структуры данных из cons-ячеек, как списки списков.

Чтобы реализовать древовидные структуры, вам нужно спроектировать функциональные возможности, которые будут проходить через cons-ячейки в определенном порядке, например, предварительный порядок, порядок и порядок для двоичных деревьев.

Дерево как список списков

Давайте рассмотрим древовидную структуру, состоящую из клеток cons, которые образуют следующий список списков:

((1 2) (3 4) (5 6)).

Схематически это можно выразить как —

Древовидная структура

Функции дерева в LISP

Хотя в основном вам нужно будет написать свои собственные древовидные функции в соответствии с вашими конкретными потребностями, LISP предоставляет некоторые древовидные функции, которые вы можете использовать.

Помимо всех функций списка, следующие функции работают особенно на древовидных структурах —

Sr.No. Описание функции
1

дерево копий x & необязательный vecp

Возвращает копию дерева cons клеток x. Он рекурсивно копирует как автомобиль, так и CDR. Если x не является cons-ячейкой, функция просто возвращает x без изменений. Если необязательный аргумент vecp равен true, эта функция копирует векторы (рекурсивно), а также cons-ячейки.

2

равный дереву xy & key: test: test-not: key

Он сравнивает два дерева минусов. Если x и y оба являются cons-ячейками, их машины и cdrs сравниваются рекурсивно. Если ни x, ни y не являются cons-ячейками, они сравниваются по eql или согласно указанному тесту. Функция: key, если указана, применяется к элементам обоих деревьев.

3

sub новое старое дерево и ключ: test: test-not: key

Он заменяет вхождения данного старого элемента новым элементом в дереве , которое является деревом клеток-противников.

4

nsubst новое старое дерево и ключ: test: test-not: key

Он работает так же, как и Sub, но уничтожает исходное дерево.

5

Sublis Alist Tree & Key: тест: тест-не: ключ

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

6

nsublis alist tree & key: test: test-not: key

Он работает так же, как Sublis, но деструктивная версия.

дерево копий x & необязательный vecp

Возвращает копию дерева cons клеток x. Он рекурсивно копирует как автомобиль, так и CDR. Если x не является cons-ячейкой, функция просто возвращает x без изменений. Если необязательный аргумент vecp равен true, эта функция копирует векторы (рекурсивно), а также cons-ячейки.

равный дереву xy & key: test: test-not: key

Он сравнивает два дерева минусов. Если x и y оба являются cons-ячейками, их машины и cdrs сравниваются рекурсивно. Если ни x, ни y не являются cons-ячейками, они сравниваются по eql или согласно указанному тесту. Функция: key, если указана, применяется к элементам обоих деревьев.

sub новое старое дерево и ключ: test: test-not: key

Он заменяет вхождения данного старого элемента новым элементом в дереве , которое является деревом клеток-противников.

nsubst новое старое дерево и ключ: test: test-not: key

Он работает так же, как и Sub, но уничтожает исходное дерево.

Sublis Alist Tree & Key: тест: тест-не: ключ

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

nsublis alist tree & key: test: test-not: key

Он работает так же, как Sublis, но деструктивная версия.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq lst (list '(1 2) '(3 4) '(5 6)))
(setq mylst (copy-list lst))
(setq tr (copy-tree lst))

(write lst)
(terpri)
(write mylst)
(terpri)
(write tr)

Когда вы выполняете код, он возвращает следующий результат —

((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))
((1 2) (3 4) (5 6))

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq tr '((1 2 (3 4 5) ((7 8) (7 8 9)))))
(write tr)
(setq trs (subst 7 1 tr))
(terpri)
(write trs)

Когда вы выполняете код, он возвращает следующий результат —

((1 2 (3 4 5) ((7 8) (7 8 9))))
((7 2 (3 4 5) ((7 8) (7 8 9))))

Строим свое дерево

Давайте попробуем построить наше собственное дерево, используя функции списка, доступные в LISP.

Сначала давайте создадим новый узел, который содержит некоторые данные

(defun make-tree (item)
   "it creates a new node with item."
   (cons (cons item nil) nil)
)

Далее давайте добавим дочерний узел в дерево — он возьмет два узла дерева и добавит второе дерево в качестве дочернего для первого.

(defun add-child (tree child)
   (setf (car tree) (append (car tree) child))
   tree)

Эта функция вернет первому дочернему элементу данное дерево — она ​​возьмет узел дерева и вернет первого дочернего элемента этого узла, или nil, если у этого узла нет дочерних узлов.

(defun first-child (tree)
   (if (null tree)
      nil
      (cdr (car tree))
   )
)

Эта функция будет возвращать следующего брата данного узла — она ​​принимает узел дерева в качестве аргумента и возвращает ссылку на следующий узел брата, или nil, если у узла его нет.

(defun next-sibling (tree)
   (cdr tree)
)

Наконец, нам нужна функция для возврата информации в узле —

(defun data (tree)
   (car (car tree))
)

пример

Этот пример использует вышеуказанные функции —

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun make-tree (item)
   "it creates a new node with item."
   (cons (cons item nil) nil)
)
(defun first-child (tree)
   (if (null tree)
      nil
      (cdr (car tree))
   )
)

(defun next-sibling (tree)
   (cdr tree)
)
(defun data (tree)
   (car (car tree))
)
(defun add-child (tree child)
   (setf (car tree) (append (car tree) child))
   tree
)

(setq tr '((1 2 (3 4 5) ((7 8) (7 8 9)))))
(setq mytree (make-tree 10))

(write (data mytree))
(terpri)
(write (first-child tr))
(terpri)
(setq newtree (add-child tr mytree))
(terpri)
(write newtree)

Когда вы выполняете код, он возвращает следующий результат —

10
(2 (3 4 5) ((7 8) (7 8 9)))

((1 2 (3 4 5) ((7 8) (7 8 9)) (10)))

LISP — Хеш-таблица

Структура данных хеш-таблицы представляет собой набор пар ключ-значение , которые организованы на основе хеш-кода ключа. Он использует ключ для доступа к элементам в коллекции.

Хеш-таблица используется, когда вам нужно получить доступ к элементам с помощью ключа, и вы можете определить полезное значение ключа. Каждый элемент в хеш-таблице имеет пару ключ / значение. Ключ используется для доступа к элементам в коллекции.

Создание хеш-таблицы в LISP

В Common LISP хеш-таблица является коллекцией общего назначения. Вы можете использовать произвольные объекты в качестве ключа или индексов.

Когда вы сохраняете значение в хеш-таблице, вы создаете пару ключ-значение и сохраняете ее под этим ключом. Позже вы можете получить значение из хеш-таблицы, используя тот же ключ. Каждый ключ отображается на одно значение, хотя вы можете сохранить новое значение в ключе.

Хэш-таблицы в LISP можно разделить на три типа в зависимости от способа сравнения ключей — eq, eql или равных. Если хеш-таблица хешируется на объектах LISP, то ключи сравниваются с eq или eql. Если хеш-таблица хеш-структуры на древовидной структуре, то она будет сравниваться с использованием равных.

Функция make-hash-table используется для создания хэш-таблицы. Синтаксис этой функции —

make-hash-table &key :test :size :rehash-size :rehash-threshold

Где —

  • Ключевой аргумент предоставляет ключ.

  • Аргумент : test определяет, как сравниваются ключи — он должен иметь одно из трех значений # ‘eq, #’ eql или # ‘равно или один из трех символов eq, eql или равно. Если не указано, предполагается, что eql.

  • Аргумент : size устанавливает начальный размер хеш-таблицы. Это должно быть целое число больше нуля.

  • Аргумент : rehash-size указывает, насколько увеличить размер хеш-таблицы, когда она заполняется. Это может быть целое число больше нуля, которое является количеством добавляемых записей, или это может быть число с плавающей запятой, большее 1, которое является отношением нового размера к старому размеру. Значение по умолчанию для этого аргумента зависит от реализации.

  • Аргумент : rehash-threshold указывает, насколько полной может быть хеш-таблица, прежде чем она должна вырасти. Это может быть целое число больше нуля и меньше: rehash-size (в этом случае оно будет масштабироваться при увеличении таблицы), или это может быть число с плавающей запятой от нуля до 1. Значение по умолчанию для этого Аргумент зависит от реализации.

Ключевой аргумент предоставляет ключ.

Аргумент : test определяет, как сравниваются ключи — он должен иметь одно из трех значений # ‘eq, #’ eql или # ‘равно или один из трех символов eq, eql или равно. Если не указано, предполагается, что eql.

Аргумент : size устанавливает начальный размер хеш-таблицы. Это должно быть целое число больше нуля.

Аргумент : rehash-size указывает, насколько увеличить размер хеш-таблицы, когда она заполняется. Это может быть целое число больше нуля, которое является количеством добавляемых записей, или это может быть число с плавающей запятой, большее 1, которое является отношением нового размера к старому размеру. Значение по умолчанию для этого аргумента зависит от реализации.

Аргумент : rehash-threshold указывает, насколько полной может быть хеш-таблица, прежде чем она должна вырасти. Это может быть целое число больше нуля и меньше: rehash-size (в этом случае оно будет масштабироваться при увеличении таблицы), или это может быть число с плавающей запятой от нуля до 1. Значение по умолчанию для этого Аргумент зависит от реализации.

Вы также можете вызвать функцию make-hash-table без аргументов.

Извлечение элементов из и добавление элементов в хэш-таблицу

Функция gethash извлекает элемент из хеш-таблицы путем поиска его ключа. Если он не находит ключ, он возвращает ноль.

Он имеет следующий синтаксис —

gethash key hash-table &optional default

где —

  • ключ: это связанный ключ

  • хеш-таблица: хеш-таблица для поиска

  • default: возвращаемое значение, если запись не найдена, которая равна nil, если не указана.

ключ: это связанный ключ

хеш-таблица: хеш-таблица для поиска

default: возвращаемое значение, если запись не найдена, которая равна nil, если не указана.

Функция gethash на самом деле возвращает два значения, второе — это значение предиката, которое имеет значение true, если запись была найдена, и false, если запись не была найдена.

Для добавления элемента в хеш-таблицу вы можете использовать функцию setf вместе с функцией gethash .

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq empList (make-hash-table)) 
(setf (gethash '001 empList) '(Charlie Brown))
(setf (gethash '002 empList) '(Freddie Seal)) 
(write (gethash '001 empList)) 
(terpri)
(write (gethash '002 empList))  

Когда вы выполняете код, он возвращает следующий результат —

(CHARLIE BROWN)
(FREDDIE SEAL)

Удаление записи

Функция remhash удаляет любую запись для определенного ключа в хэш-таблице. Это предикат, который имеет значение true, если была запись, или false, если ее не было.

Синтаксис этой функции —

remhash key hash-table

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq empList (make-hash-table)) 
(setf (gethash '001 empList) '(Charlie Brown))
(setf (gethash '002 empList) '(Freddie Seal)) 
(setf (gethash '003 empList) '(Mark Mongoose)) 

(write (gethash '001 empList)) 
(terpri)
(write (gethash '002 empList)) 
(terpri)
(write (gethash '003 empList))  
(remhash '003 empList)
(terpri)
(write (gethash '003 empList))  

Когда вы выполняете код, он возвращает следующий результат —

(CHARLIE BROWN)
(FREDDIE SEAL)
(MARK MONGOOSE)
NIL

Функция maphash

Функция maphash позволяет применять указанную функцию к каждой паре ключ-значение в хеш-таблице.

Он принимает два аргумента — функцию и хеш-таблицу и вызывает функцию один раз для каждой пары ключ / значение в хеш-таблице.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(setq empList (make-hash-table)) 
(setf (gethash '001 empList) '(Charlie Brown))
(setf (gethash '002 empList) '(Freddie Seal)) 
(setf (gethash '003 empList) '(Mark Mongoose)) 

(maphash #'(lambda (k v) (format t "~a => ~a~%" k v)) empList)

Когда вы выполняете код, он возвращает следующий результат —

3 => (MARK MONGOOSE)
2 => (FREDDIE SEAL)
1 => (CHARLIE BROWN)

LISP — вход и выход

Common LISP предоставляет множество функций ввода-вывода. Мы уже использовали функцию форматирования и функцию печати для вывода. В этом разделе мы рассмотрим некоторые из наиболее часто используемых функций ввода-вывода, представленных в LISP.

Функции ввода

В следующей таблице приведены наиболее часто используемые функции ввода LISP —

Sr.No. Описание функции
1

чтение и необязательный входной поток eof-error-p eof-value recursive-p

Он считывает напечатанное представление объекта Lisp из input-stream, создает соответствующий объект Lisp и возвращает объект.

2

чтение-сохранение-пробелы и необязательный in-stream eof-error-p eof-value recursive-p

Он используется в некоторых специализированных ситуациях, когда желательно точно определить, каким символом завершен расширенный токен.

3

read-line & необязательный входной поток eof-error-p eof-value recursive-p

Он читает строку текста, оканчивающуюся новой строкой.

4

read-char & необязательный входной поток eof-error-p eof-value recursive-p

Он берет один символ из входного потока и возвращает его как символьный объект.

5

непрочитанный символ и необязательный поток ввода

Он помещает символ, последний прочитанный из потока ввода, в начало потока ввода.

6

peek-char & необязательный входной поток peek-типа eof-error-p eof-value recursive-p

Он возвращает следующий символ, который будет считан из потока ввода, без фактического удаления его из потока ввода.

7

прослушивание и дополнительный поток ввода

Предикат прослушивания имеет значение true, если есть символ, немедленно доступный из потока ввода, и значение false, если нет.

8

read-char-no-hang & необязательный input-stream eof-error-p eof-value recursive-p

Он похож на read-char , но если он не получает символ, он не ждет символа, но немедленно возвращает ноль.

9

чистый ввод и дополнительный поток ввода

Он очищает любой буферизованный ввод, связанный с input-stream.

10

строка чтения из строки и необязательный eof-error-p eof-value & key: start: end: preserve-whitespace

Он последовательно принимает символы строки, создает объект LISP и возвращает объект. Он также возвращает индекс первого символа в строке, который не был прочитан, или длину строки (или длину +1), в зависимости от обстоятельств.

11

строка целочисленного анализа и ключ: начало: конец: основание: нежелательная почта

Он проверяет подстроку строки, разделенную: start и: end (по умолчанию начало и конец строки). Он пропускает пробельные символы, а затем пытается проанализировать целое число.

12

бинарный входной поток чтения и необязательное значение eof-error-p-eof-value

Он читает один байт из потока двоичного ввода и возвращает его в виде целого числа.

чтение и необязательный входной поток eof-error-p eof-value recursive-p

Он считывает напечатанное представление объекта Lisp из input-stream, создает соответствующий объект Lisp и возвращает объект.

чтение-сохранение-пробелы и необязательный in-stream eof-error-p eof-value recursive-p

Он используется в некоторых специализированных ситуациях, когда желательно точно определить, каким символом завершен расширенный токен.

read-line & необязательный входной поток eof-error-p eof-value recursive-p

Он читает строку текста, оканчивающуюся новой строкой.

read-char & необязательный входной поток eof-error-p eof-value recursive-p

Он берет один символ из входного потока и возвращает его как символьный объект.

непрочитанный символ и необязательный поток ввода

Он помещает символ, последний прочитанный из потока ввода, в начало потока ввода.

peek-char & необязательный входной поток peek-типа eof-error-p eof-value recursive-p

Он возвращает следующий символ, который будет считан из потока ввода, без фактического удаления его из потока ввода.

прослушивание и дополнительный поток ввода

Предикат прослушивания имеет значение true, если есть символ, немедленно доступный из потока ввода, и значение false, если нет.

read-char-no-hang & необязательный input-stream eof-error-p eof-value recursive-p

Он похож на read-char , но если он не получает символ, он не ждет символа, но немедленно возвращает ноль.

чистый ввод и дополнительный поток ввода

Он очищает любой буферизованный ввод, связанный с input-stream.

строка чтения из строки и необязательный eof-error-p eof-value & key: start: end: preserve-whitespace

Он последовательно принимает символы строки, создает объект LISP и возвращает объект. Он также возвращает индекс первого символа в строке, который не был прочитан, или длину строки (или длину +1), в зависимости от обстоятельств.

строка целочисленного анализа и ключ: начало: конец: основание: нежелательная почта

Он проверяет подстроку строки, разделенную: start и: end (по умолчанию начало и конец строки). Он пропускает пробельные символы, а затем пытается проанализировать целое число.

бинарный входной поток чтения и необязательное значение eof-error-p-eof-value

Он читает один байт из потока двоичного ввода и возвращает его в виде целого числа.

Чтение ввода с клавиатуры

Функция чтения используется для ввода данных с клавиатуры. Это может не принимать никаких аргументов.

Например, рассмотрим фрагмент кода —

(write ( + 15.0 (read)))

Предположим, что пользователь вводит 10.2 из ввода STDIN, он возвращает,

25.2

Функция read читает символы из входного потока и интерпретирует их, анализируя как представления объектов Lisp.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код —

; the function AreaOfCircle
; calculates area of a circle
; when the radius is input from keyboard

(defun AreaOfCircle()
(terpri)
(princ "Enter Radius: ")
(setq radius (read))
(setq area (* 3.1416 radius radius))
(princ "Area: ")
(write area))
(AreaOfCircle)

Когда вы выполняете код, он возвращает следующий результат —

Enter Radius: 5 (STDIN Input)
Area: 78.53999

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(with-input-from-string (stream "Welcome to Tutorials Point!")
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (read-char stream))
   (print (peek-char nil stream nil 'the-end))
   (values)
)

Когда вы выполняете код, он возвращает следующий результат —

#\W 
#\e 
#\l 
#\c 
#\o 
#\m 
#\e 
#\Space 
#\t 
#\o 
#\Space 

Функции вывода

Все функции вывода в LISP принимают необязательный аргумент, называемый output-stream, куда отправляется вывод. Если не указано или равно nil, по умолчанию для output-stream используется значение переменной * standard-output *.

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

Sr.No. Функция и описание
1

запись объекта и ключа: поток: escape: основание: круг: довольно: уровень: длина: регистр: gensym: массив

запись объекта и ключа: поток: escape: основание: основание: круг: довольно: уровень: длина: регистр: gensym: массив: читабельно: правое поле: ширина склейки: строки: pprint-dispatch

Оба записывают объект в выходной поток, заданный параметром: stream, значение по умолчанию которого равно * standard-output *. Другие значения по умолчанию соответствуют глобальным переменным, установленным для печати.

2

объект prin1 и дополнительный поток вывода

объект печати и дополнительный поток вывода

объект pprint и дополнительный поток вывода

объект princ и необязательный выходной поток

Все эти функции выводят печатное представление объекта в output-stream . Тем не менее, существуют следующие различия:

  • prin1 возвращает объект как его значение.

  • print печатает объект с предыдущей новой строкой, за которой следует пробел. Возвращает объект.

  • pprint похож на print, за исключением того, что завершающий пробел пропущен.

  • princ похож на prin1 за исключением того, что в выводе нет экранирующего символа

3

Объект записи в строку и ключ : escape: основание: основание: окружность: довольно: уровень: длина: регистр: gensym: массив

Объект записи в строку и ключ: escape: основание: основание: окружность: довольно: уровень: длина: регистр: gensym: массив: читабельно: правое поле: ширина скриншота: линии: pprint-dispatch

объект prin1-to-string

объект типа « строка-строка»

Объект эффективно печатается, а выходные символы превращаются в строку, которая возвращается.

4

символ записи и дополнительный поток вывода

Он выводит символ в output-stream и возвращает символ.

5

строка записи и необязательный выходной поток и ключ: начало: конец

Он записывает символы указанной подстроки строки в поток вывода.

6

строка записи и необязательный выходной поток и ключ: начало: конец

Он работает так же, как write-string, но впоследствии выводит новую строку.

7

terpri & необязательный выходной поток

Он выводит новую строку в output-stream.

8

свежая линия и дополнительный выходной поток

он выводит новую строку, только если поток еще не находится в начале строки.

9

окончательный вывод и дополнительный выходной поток

принудительный вывод и дополнительный выходной поток

чистый вывод и дополнительный выходной поток

  • Функция finish-output пытается убедиться, что весь вывод, отправленный в output-stream, достиг своего места назначения, и только после этого возвращает nil.

  • Функция force-output инициирует очистку любых внутренних буферов, но возвращает nil, не ожидая завершения или подтверждения.

  • Функция clear-output пытается прервать любую незавершенную операцию вывода, чтобы как можно меньше выходных данных продолжалось до места назначения.

10

запись байтового целого двоичного потока вывода

Записывает один байт, значение целого числа.

запись объекта и ключа: поток: escape: основание: круг: довольно: уровень: длина: регистр: gensym: массив

запись объекта и ключа: поток: escape: основание: основание: круг: довольно: уровень: длина: регистр: gensym: массив: читабельно: правое поле: ширина склейки: строки: pprint-dispatch

Оба записывают объект в выходной поток, заданный параметром: stream, значение по умолчанию которого равно * standard-output *. Другие значения по умолчанию соответствуют глобальным переменным, установленным для печати.

объект prin1 и дополнительный поток вывода

объект печати и дополнительный поток вывода

объект pprint и дополнительный поток вывода

объект princ и необязательный выходной поток

Все эти функции выводят печатное представление объекта в output-stream . Тем не менее, существуют следующие различия:

prin1 возвращает объект как его значение.

print печатает объект с предыдущей новой строкой, за которой следует пробел. Возвращает объект.

pprint похож на print, за исключением того, что завершающий пробел пропущен.

princ похож на prin1 за исключением того, что в выводе нет экранирующего символа

Объект записи в строку и ключ : escape: основание: основание: окружность: довольно: уровень: длина: регистр: gensym: массив

Объект записи в строку и ключ: escape: основание: основание: окружность: довольно: уровень: длина: регистр: gensym: массив: читабельно: правое поле: ширина скриншота: линии: pprint-dispatch

объект prin1-to-string

объект типа « строка-строка»

Объект эффективно печатается, а выходные символы превращаются в строку, которая возвращается.

символ записи и дополнительный поток вывода

Он выводит символ в output-stream и возвращает символ.

строка записи и необязательный выходной поток и ключ: начало: конец

Он записывает символы указанной подстроки строки в поток вывода.

строка записи и необязательный выходной поток и ключ: начало: конец

Он работает так же, как write-string, но впоследствии выводит новую строку.

terpri & необязательный выходной поток

Он выводит новую строку в output-stream.

свежая линия и дополнительный выходной поток

он выводит новую строку, только если поток еще не находится в начале строки.

окончательный вывод и дополнительный выходной поток

принудительный вывод и дополнительный выходной поток

чистый вывод и дополнительный выходной поток

Функция finish-output пытается убедиться, что весь вывод, отправленный в output-stream, достиг своего места назначения, и только после этого возвращает nil.

Функция force-output инициирует очистку любых внутренних буферов, но возвращает nil, не ожидая завершения или подтверждения.

Функция clear-output пытается прервать любую незавершенную операцию вывода, чтобы как можно меньше выходных данных продолжалось до места назначения.

запись байтового целого двоичного потока вывода

Записывает один байт, значение целого числа.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

; this program inputs a numbers and doubles it
(defun DoubleNumber()
   (terpri)
   (princ "Enter Number : ")
   (setq n1 (read))
   (setq doubled (* 2.0 n1))
   (princ "The Number: ")
   (write n1)
   (terpri)
   (princ "The Number Doubled: ")
   (write doubled)
)
(DoubleNumber)

Когда вы выполняете код, он возвращает следующий результат —

Enter Number : 3456.78 (STDIN Input)
The Number: 3456.78
The Number Doubled: 6913.56

Форматированный вывод

Формат функции используется для создания красиво отформатированного текста. Он имеет следующий синтаксис —

format destination control-string &rest arguments

где,

  • назначение — стандартный вывод
  • control-string содержит символы для вывода и директиву печати.

Директива формата состоит из тильды (~), необязательных параметров префикса, разделенных запятыми, необязательных модификаторов двоеточия (:) и at-sign (@) и одного символа, указывающего, что это за директива.

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

В следующей таблице приведено краткое описание часто используемых директив —

Sr.No. Директива и описание
1

~ A

За ним следуют аргументы ASCII.

2

~ S

Сопровождается S-выражениями.

3

~ D

Для десятичных аргументов.

4

~ B

Для двоичных аргументов.

5

~ O

Для восьмеричных аргументов.

6

~ X

Для шестнадцатеричных аргументов.

7

~ C

Для аргументов персонажа.

8

~ F

Для аргументов с плавающей точкой фиксированного формата.

9

~ E

Экспоненциальные аргументы с плавающей точкой.

10

~ $

Доллар и аргументы с плавающей запятой.

11

~%

Новая строка печатается.

12

~ *

Следующий аргумент игнорируется.

13

~?

Косвенность. Следующий аргумент должен быть строкой, а следующий после нее — списком.

~ A

За ним следуют аргументы ASCII.

~ S

Сопровождается S-выражениями.

~ D

Для десятичных аргументов.

~ B

Для двоичных аргументов.

~ O

Для восьмеричных аргументов.

~ X

Для шестнадцатеричных аргументов.

~ C

Для аргументов персонажа.

~ F

Для аргументов с плавающей точкой фиксированного формата.

~ E

Экспоненциальные аргументы с плавающей точкой.

~ $

Доллар и аргументы с плавающей запятой.

~%

Новая строка печатается.

~ *

Следующий аргумент игнорируется.

~?

Косвенность. Следующий аргумент должен быть строкой, а следующий после нее — списком.

пример

Перепишем программу расчета площади круга —

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

(defun AreaOfCircle()
   (terpri)
   (princ "Enter Radius: ")
   (setq radius (read))
   (setq area (* 3.1416 radius radius))
   (format t "Radius: = ~F~% Area = ~F" radius area)
)
(AreaOfCircle)

Когда вы выполняете код, он возвращает следующий результат —

Enter Radius: 10.234 (STDIN Input)
Radius: = 10.234
Area = 329.03473

LISP — File I / O

Мы обсудили, как стандартный ввод и вывод обрабатывается обычным LISP. Все эти функции также работают для чтения и записи в текстовые и двоичные файлы. Единственное отличие состоит в том, что в этом случае используемый нами поток — это не стандартный ввод или вывод, а поток, созданный для конкретной цели записи или чтения из файлов.

В этой главе мы увидим, как LISP может создавать, открывать, закрывать текстовые или двоичные файлы для их хранения данных.

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

Открытие файлов

Вы можете использовать функцию открытия, чтобы создать новый файл или открыть существующий файл. Это самая основная функция для открытия файла. Однако with-open-file обычно более удобен и более широко используется, как мы увидим позже в этом разделе.

Когда файл открывается, объект потока создается для его представления в среде LISP. Все операции с потоком в основном эквивалентны операциям с файлом.

Синтаксис для открытой функции —

open filename &key :direction :element-type :if-exists :if-does-not-exist :external-format

где,

  • Аргумент имени файла — это имя файла, который нужно открыть или создать.

  • Ключевое слово arguments указывает тип потока и способы обработки ошибок.

  • Ключевое слово : direction указывает, должен ли поток обрабатывать ввод, вывод или оба, он принимает следующие значения —

    • : input — для входных потоков (значение по умолчанию)

    • : output — для выходных потоков

    • : io — для двунаправленных потоков

    • : probe — для проверки наличия файлов; поток открывается, а затем закрывается.

  • Элемент : element-type указывает тип единицы транзакции для потока.

  • Аргумент : if-существующие указывает действие, которое необходимо предпринять, если: direction:: output или: io и файл с указанным именем уже существует. Если направление: input или: probe, этот аргумент игнорируется. Он принимает следующие значения —

    • : ошибка — сигнализирует об ошибке.

    • : new-version — создает новый файл с тем же именем, но большим номером версии.

    • : переименовать — переименовывает существующий файл.

    • : переименовать-и-удалить — переименовывает существующий файл и затем удаляет его.

    • : append — добавляет к существующему файлу.

    • : supersede — заменяет существующий файл

    • ноль — он не создает файл или даже поток просто возвращает ноль, чтобы указать сбой.

  • Аргумент : if-does-not- there указывает действие, которое необходимо предпринять, если файл с указанным именем еще не существует. Он принимает следующие значения —

    • : ошибка — сигнализирует об ошибке.

    • : create — создает пустой файл с указанным именем и затем использует его.

    • ноль — он не создает файл или даже поток, но вместо этого просто возвращает ноль, чтобы указать сбой.

  • Аргумент : external-format указывает распознаваемую реализацией схему для представления символов в файлах.

Аргумент имени файла — это имя файла, который нужно открыть или создать.

Ключевое слово arguments указывает тип потока и способы обработки ошибок.

Ключевое слово : direction указывает, должен ли поток обрабатывать ввод, вывод или оба, он принимает следующие значения —

: input — для входных потоков (значение по умолчанию)

: output — для выходных потоков

: io — для двунаправленных потоков

: probe — для проверки наличия файлов; поток открывается, а затем закрывается.

Элемент : element-type указывает тип единицы транзакции для потока.

Аргумент : if-существующие указывает действие, которое необходимо предпринять, если: direction:: output или: io и файл с указанным именем уже существует. Если направление: input или: probe, этот аргумент игнорируется. Он принимает следующие значения —

: ошибка — сигнализирует об ошибке.

: new-version — создает новый файл с тем же именем, но большим номером версии.

: переименовать — переименовывает существующий файл.

: переименовать-и-удалить — переименовывает существующий файл и затем удаляет его.

: append — добавляет к существующему файлу.

: supersede — заменяет существующий файл

ноль — он не создает файл или даже поток просто возвращает ноль, чтобы указать сбой.

Аргумент : if-does-not- there указывает действие, которое необходимо предпринять, если файл с указанным именем еще не существует. Он принимает следующие значения —

: ошибка — сигнализирует об ошибке.

: create — создает пустой файл с указанным именем и затем использует его.

ноль — он не создает файл или даже поток, но вместо этого просто возвращает ноль, чтобы указать сбой.

Аргумент : external-format указывает распознаваемую реализацией схему для представления символов в файлах.

Например, вы можете открыть файл с именем myfile.txt, хранящийся в папке / tmp, как —

(open "/tmp/myfile.txt")

Запись в и чтение из файлов

With -open-file позволяет читать или записывать в файл, используя переменную потока, связанную с транзакцией чтения / записи. Как только работа завершена, она автоматически закрывает файл. Это чрезвычайно удобно для использования.

Он имеет следующий синтаксис —

with-open-file (stream filename {options}*)
   {declaration}* {form}*
  • filename — имя файла, который нужно открыть; это может быть строка, путь или поток.

  • Параметры совпадают с ключевыми словами аргументов открытой функции.

filename — имя файла, который нужно открыть; это может быть строка, путь или поток.

Параметры совпадают с ключевыми словами аргументов открытой функции.

Пример 1

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

(with-open-file (stream "/tmp/myfile.txt" :direction :output)
   (format stream "Welcome to Tutorials Point!")
   (terpri stream)
   (format stream "This is a tutorials database")
   (terpri stream)
   (format stream "Submit your Tutorials, White Papers and Articles into our Tutorials   Directory.")
)

Обратите внимание, что все функции ввода-вывода, обсуждавшиеся в предыдущей главе, такие как terpri и format, работают для записи в файл, который мы здесь создали.

Когда вы выполняете код, он ничего не возвращает; однако наши данные записываются в файл. Ключевые слова : direction: output позволяют нам сделать это.

Тем не менее, мы можем читать из этого файла, используя функцию чтения строки .

Пример 2

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

(let ((in (open "/tmp/myfile.txt" :if-does-not-exist nil)))
   (when in
      (loop for line = (read-line in nil)
      
      while line do (format t "~a~%" line))
      (close in)
   )
)

Когда вы выполняете код, он возвращает следующий результат —

Welcome to Tutorials Point!
This is a tutorials database
Submit your Tutorials, White Papers and Articles into our Tutorials Directory.

Закрытие файла

Функция close закрывает поток.

ЛИСП — Структуры

Структуры являются одним из определяемых пользователем типов данных, который позволяет комбинировать элементы данных разных видов.

Структуры используются для представления записи. Предположим, вы хотите отслеживать свои книги в библиотеке. Вы можете отслеживать следующие атрибуты о каждой книге —

  • заглавие
  • автор
  • Предмет
  • ID книги

Определение структуры

Макрос defstruct в LISP позволяет вам определять абстрактную структуру записи. Оператор defstruct определяет новый тип данных с более чем одним членом для вашей программы.

Чтобы обсудить формат макроса defstruct , давайте напишем определение структуры Book. Мы могли бы определить структуру книги как —

(defstruct book 
   title 
   author 
   subject 
   book-id 
)

пожалуйста, обратите внимание

  • Приведенное выше объявление создает структуру книги с четырьмя именованными компонентами. Таким образом, каждая созданная книга будет объектом этой структуры.

  • Он определяет четыре функции с именами book-title, book-author, book-subject и book-book-id, которые будут принимать один аргумент, структуру книги и будут возвращать название поля, автора, тему и идентификатор книги книги объект. Эти функции называются функциями доступа.

  • Книга символов становится типом данных, и вы можете проверить это с помощью предиката typep .

  • Также будет неявная функция с именем book-p, которая является предикатом и будет истинной, если ее аргумент является книгой и в противном случае будет ложным.

  • Будет создана другая неявная функция с именем make-book , которая является конструктором, который при вызове создает структуру данных с четырьмя компонентами, подходящими для использования с функциями доступа.

  • Синтаксис #S относится к структуре, и вы можете использовать ее для чтения или печати экземпляров книги.

  • Также определяется неявная функция с именем copy-book одного аргумента. Он берет объект книги и создает другой объект книги, который является копией первого. Эта функция называется функцией копира.

  • Вы можете использовать setf, чтобы изменить компоненты книги, например

Приведенное выше объявление создает структуру книги с четырьмя именованными компонентами. Таким образом, каждая созданная книга будет объектом этой структуры.

Он определяет четыре функции с именами book-title, book-author, book-subject и book-book-id, которые будут принимать один аргумент, структуру книги и будут возвращать название поля, автора, тему и идентификатор книги книги объект. Эти функции называются функциями доступа.

Книга символов становится типом данных, и вы можете проверить это с помощью предиката typep .

Также будет неявная функция с именем book-p, которая является предикатом и будет истинной, если ее аргумент является книгой и в противном случае будет ложным.

Будет создана другая неявная функция с именем make-book , которая является конструктором, который при вызове создает структуру данных с четырьмя компонентами, подходящими для использования с функциями доступа.

Синтаксис #S относится к структуре, и вы можете использовать ее для чтения или печати экземпляров книги.

Также определяется неявная функция с именем copy-book одного аргумента. Он берет объект книги и создает другой объект книги, который является копией первого. Эта функция называется функцией копира.

Вы можете использовать setf, чтобы изменить компоненты книги, например

(setf (book-book-id book3) 100)

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defstruct book 
   title 
   author 
   subject 
   book-id 
)

( setq book1 (make-book :title "C Programming"
   :author "Nuha Ali" 
   :subject "C-Programming Tutorial"
   :book-id "478")
)

( setq book2 (make-book :title "Telecom Billing"
   :author "Zara Ali" 
   :subject "C-Programming Tutorial"
   :book-id "501")
) 

(write book1)
(terpri)
(write book2)
(setq book3( copy-book book1))
(setf (book-book-id book3) 100) 
(terpri)
(write book3)

Когда вы выполняете код, он возвращает следующий результат —

#S(BOOK :TITLE "C Programming" :AUTHOR "Nuha Ali" :SUBJECT "C-Programming Tutorial" :BOOK-ID "478")
#S(BOOK :TITLE "Telecom Billing" :AUTHOR "Zara Ali" :SUBJECT "C-Programming Tutorial" :BOOK-ID "501")
#S(BOOK :TITLE "C Programming" :AUTHOR "Nuha Ali" :SUBJECT "C-Programming Tutorial" :BOOK-ID 100)

ЛИСП — Пакеты

В общем смысле языки программирования, пакет предназначен для обеспечения способа отделить один набор имен от другого. Символы, объявленные в одном пакете, не будут конфликтовать с теми же символами, объявленными в другом. Таким образом, пакеты уменьшают конфликты именования между независимыми модулями кода.

Читатель LISP ведет таблицу всех найденных символов. Когда он находит новую последовательность символов, он создает новый символ и сохраняет его в таблице символов. Эта таблица называется пакетом.

Текущий пакет указывается специальной переменной * package *.

В LISP есть два предопределенных пакета:

  • common-lisp — содержит символы для всех определенных функций и переменных.

  • common-lisp-user — использует пакет common-lisp и все остальные пакеты с инструментами редактирования и отладки; это называется cl-user вкратце

common-lisp — содержит символы для всех определенных функций и переменных.

common-lisp-user — использует пакет common-lisp и все остальные пакеты с инструментами редактирования и отладки; это называется cl-user вкратце

Пакетные функции в LISP

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

Sr.No. Функция и описание
1

make-package имя пакета и ключ: псевдонимы: использовать

Он создает и возвращает новый пакет с указанным именем пакета.

2

имя пакета и ключ в пакете : псевдонимы: использовать

Делает пакет актуальным.

3

имя в упаковке

Этот макрос заставляет * package * быть установленным на имя пакета, которое должно быть символом или строкой.

4

название пакета поиска

Он ищет пакет. Пакет с таким именем или псевдонимом возвращается; если такого пакета не существует, find-package возвращает nil.

5

переименовать пакет пакет новое имя и дополнительные новые псевдонимы

это переименовывает пакет.

6

список-все-пакеты

Эта функция возвращает список всех пакетов, которые в настоящее время существуют в системе Lisp.

7

пакет удаления пакета

Удаляет пакет.

make-package имя пакета и ключ: псевдонимы: использовать

Он создает и возвращает новый пакет с указанным именем пакета.

имя пакета и ключ в пакете : псевдонимы: использовать

Делает пакет актуальным.

имя в упаковке

Этот макрос заставляет * package * быть установленным на имя пакета, которое должно быть символом или строкой.

название пакета поиска

Он ищет пакет. Пакет с таким именем или псевдонимом возвращается; если такого пакета не существует, find-package возвращает nil.

переименовать пакет пакет новое имя и дополнительные новые псевдонимы

это переименовывает пакет.

список-все-пакеты

Эта функция возвращает список всех пакетов, которые в настоящее время существуют в системе Lisp.

пакет удаления пакета

Удаляет пакет.

Создание пакета LISP

Функция defpackage используется для создания пользовательского пакета. Он имеет следующий синтаксис —

(defpackage :package-name
   (:use :common-lisp ...)
   (:export :symbol1 :symbol2 ...)
)

Куда,

  • имя-пакета — это имя пакета.

  • Ключевое слово: use указывает пакеты, в которых нуждается этот пакет, то есть пакеты, которые определяют функции, используемые кодом в этом пакете.

  • Ключевое слово: export указывает внешние символы в этом пакете.

имя-пакета — это имя пакета.

Ключевое слово: use указывает пакеты, в которых нуждается этот пакет, то есть пакеты, которые определяют функции, используемые кодом в этом пакете.

Ключевое слово: export указывает внешние символы в этом пакете.

Функция make-package также используется для создания пакета. Синтаксис этой функции —

make-package package-name &key :nicknames :use

Аргументы и ключевые слова имеют то же значение, что и раньше.

Использование пакета

Создав пакет, вы можете использовать код в этом пакете, сделав его текущим пакетом. Макрос в пакете делает пакет текущим в среде.

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(make-package :tom)
(make-package :dick)
(make-package :harry)
(in-package tom)
(defun hello () 
   (write-line "Hello! This is Tom's Tutorials Point")
)

(hello)
(in-package dick)
(defun hello () 
   (write-line "Hello! This is Dick's Tutorials Point")
)

(hello)
(in-package harry)
(defun hello () 
   (write-line "Hello! This is Harry's Tutorials Point")
)

(hello)
(in-package tom)
(hello)
(in-package dick)
(hello)
(in-package harry)
(hello)

Когда вы выполняете код, он возвращает следующий результат —

Hello! This is Tom's Tutorials Point
Hello! This is Dick's Tutorials Point
Hello! This is Harry's Tutorials Point

Удаление пакета

Макрос delete-package позволяет вам удалить пакет. Следующий пример демонстрирует это —

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(make-package :tom)
(make-package :dick)
(make-package :harry)
(in-package tom)
(defun hello () 
   (write-line "Hello! This is Tom's Tutorials Point")
)

(in-package dick)
(defun hello () 
   (write-line "Hello! This is Dick's Tutorials Point")
)

(in-package harry)
(defun hello () 
   (write-line "Hello! This is Harry's Tutorials Point")
)

(in-package tom)
(hello)
(in-package dick)
(hello)
(in-package harry)
(hello)
(delete-package tom)
(in-package tom)
(hello)

Когда вы выполняете код, он возвращает следующий результат —

Hello! This is Tom's Tutorials Point
Hello! This is Dick's Tutorials Point
Hello! This is Harry's Tutorials Point
*** - EVAL: variable TOM has no value

LISP — Обработка ошибок

В общей терминологии LISP исключения называются условиями.

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

Механизм обработки условий в LISP обрабатывает такие ситуации таким образом, что условия используются для сигнализации о предупреждении (скажем, путем печати предупреждения), в то время как код верхнего уровня в стеке вызовов может продолжать свою работу.

Система обработки условий в LISP состоит из трех частей:

  • Сигнализация условия
  • Обработка условия
  • Перезапустите процесс

Обработка условия

Давайте рассмотрим пример обработки условия, возникающего из деления на нулевое условие, чтобы объяснить концепции здесь.

Вам нужно предпринять следующие шаги для обработки условия —

  • Определите условие — «Условие — это объект, чей класс указывает на общий характер условия, а данные экземпляра содержат информацию о деталях конкретных обстоятельств, которые приводят к сигналу условия».

    Макрос define-condition используется для определения условия, которое имеет следующий синтаксис:

    (define-condition condition-name (error)
       ((text :initarg :text :reader text))
    )
    

    Новые объекты условий создаются с помощью макроса MAKE-CONDITION, который инициализирует слоты нового условия на основе аргумента : initargs .

    В нашем примере следующий код определяет условие —

    (define-condition on-division-by-zero (error)
       ((message :initarg :message :reader message))
    )
  • Написание обработчиков — обработчик условия — это код, который используется для обработки указанного в нем условия. Обычно оно написано в одной из функций более высокого уровня, которые вызывают функцию ошибки. Когда условие сигнализируется, механизм сигнализации ищет подходящий обработчик на основе класса условия.

    Каждый обработчик состоит из —

    • Спецификатор типа, который указывает тип условия, которое он может обработать
    • Функция, которая принимает один аргумент, условие

    Когда условие сигнализируется, механизм сигнализации находит последний установленный обработчик, который совместим с типом условия, и вызывает его функцию.

    Случай обработчика макроса устанавливает обработчик условия. Основная форма обработчика-кейса —

    (handler-case expression error-clause*)
    

    Где каждое предложение об ошибке имеет вид —

    condition-type ([var]) code)
    
  • Фаза перезапуска

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

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

    Основная форма привязки обработчика выглядит следующим образом:

    (handler-bind (binding*) form*)
    

    Где каждая привязка представляет собой список следующего —

    • тип условия
    • функция-обработчик одного аргумента

    Макрос invoke-restart находит и вызывает последнюю связанную функцию restart с указанным именем в качестве аргумента.

    Вы можете иметь несколько перезапусков.

Определите условие — «Условие — это объект, чей класс указывает на общий характер условия, а данные экземпляра содержат информацию о деталях конкретных обстоятельств, которые приводят к сигналу условия».

Макрос define-condition используется для определения условия, которое имеет следующий синтаксис:

Новые объекты условий создаются с помощью макроса MAKE-CONDITION, который инициализирует слоты нового условия на основе аргумента : initargs .

В нашем примере следующий код определяет условие —

Написание обработчиков — обработчик условия — это код, который используется для обработки указанного в нем условия. Обычно оно написано в одной из функций более высокого уровня, которые вызывают функцию ошибки. Когда условие сигнализируется, механизм сигнализации ищет подходящий обработчик на основе класса условия.

Каждый обработчик состоит из —

Когда условие сигнализируется, механизм сигнализации находит последний установленный обработчик, который совместим с типом условия, и вызывает его функцию.

Случай обработчика макроса устанавливает обработчик условия. Основная форма обработчика-кейса —

Где каждое предложение об ошибке имеет вид —

Фаза перезапуска

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

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

Основная форма привязки обработчика выглядит следующим образом:

Где каждая привязка представляет собой список следующего —

Макрос invoke-restart находит и вызывает последнюю связанную функцию restart с указанным именем в качестве аргумента.

Вы можете иметь несколько перезапусков.

пример

В этом примере мы демонстрируем вышеприведенные концепции, написав функцию с именем Division-function, которая создаст условие ошибки, если аргумент делителя равен нулю. У нас есть три анонимные функции, которые обеспечивают три способа выхода из него — путем возврата значения 1, отправки делителя 2 и пересчета или возврата 1.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(define-condition on-division-by-zero (error)
   ((message :initarg :message :reader message))
)
   
(defun handle-infinity ()
   (restart-case
      (let ((result 0))
         (setf result (division-function 10 0))
         (format t "Value: ~a~%" result)
      )
      (just-continue () nil)
   )
)
     
(defun division-function (value1 value2)
   (restart-case
      (if (/= value2 0)
         (/ value1 value2)
         (error 'on-division-by-zero :message "denominator is zero")
      )

      (return-zero () 0)
      (return-value (r) r)
      (recalc-using (d) (division-function value1 d))
   )
)

(defun high-level-code ()
   (handler-bind
      (
         (on-division-by-zero
            #'(lambda (c)
               (format t "error signaled: ~a~%" (message c))
               (invoke-restart 'return-zero)
            )
         )
         (handle-infinity)
      )
   )
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'return-value 1)
         )
      )
   )
   (handle-infinity)
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'recalc-using 2)
         )
      )
   )
   (handle-infinity)
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'just-continue)
         )
      )
   )
   (handle-infinity)
)

(format t "Done."))

Когда вы выполняете код, он возвращает следующий результат —

error signaled: denominator is zero
Value: 1
error signaled: denominator is zero
Value: 5
error signaled: denominator is zero
Done.

Помимо «Системы условий», как обсуждалось выше, Common LISP также предоставляет различные функции, которые могут быть вызваны для сигнализации об ошибке. Обработка ошибки, когда сообщается, однако, зависит от реализации.

Функции сигнализации об ошибках в LISP

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

Пользовательская программа указывает сообщение об ошибке (строка). Функции обрабатывают это сообщение и могут / не могут отображать его пользователю.

Сообщения об ошибках должны создаваться с применением функции форматирования , не должны содержать символ новой строки в начале или конце и не должны указывать на ошибку, поскольку система LISP позаботится об этом в соответствии со своим предпочтительным стилем.

Sr.No. Функция и описание
1

строка формата ошибки и остальные аргументы

Это сигнализирует о фатальной ошибке. Невозможно продолжать с такой ошибки; таким образом, ошибка никогда не вернется к своему вызывающему.

2

cerror continue-format-string error-format-string & rest args

Он сигнализирует об ошибке и входит в отладчик. Однако это позволяет продолжить программу из отладчика после устранения ошибки.

3

предупредить строку формата и остальные аргументы

он печатает сообщение об ошибке, но обычно не входит в отладчик

4

разрыв и необязательный формат-строки и остальные аргументы

Он печатает сообщение и попадает прямо в отладчик, не допуская возможности перехвата запрограммированными средствами обработки ошибок

строка формата ошибки и остальные аргументы

Это сигнализирует о фатальной ошибке. Невозможно продолжать с такой ошибки; таким образом, ошибка никогда не вернется к своему вызывающему.

cerror continue-format-string error-format-string & rest args

Он сигнализирует об ошибке и входит в отладчик. Однако это позволяет продолжить программу из отладчика после устранения ошибки.

предупредить строку формата и остальные аргументы

он печатает сообщение об ошибке, но обычно не входит в отладчик

разрыв и необязательный формат-строки и остальные аргументы

Он печатает сообщение и попадает прямо в отладчик, не допуская возможности перехвата запрограммированными средствами обработки ошибок

пример

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

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defun factorial (x)
   (cond ((or (not (typep x 'integer)) (minusp x))
      (error "~S is a negative number." x))
      ((zerop x) 1)
      (t (* x (factorial (- x 1))))
   )
)

(write(factorial 5))
(terpri)
(write(factorial -1))

Когда вы выполняете код, он возвращает следующий результат —

120
*** - -1 is a negative number.

ЛИСП — ЗАКРЫТЬ

Общий LISP предшествовал продвижению объектно-ориентированного программирования на пару десятилетий. Однако объектная ориентация была включена в него на более позднем этапе.

Определение классов

Макрос defclass позволяет создавать пользовательские классы. Он устанавливает класс как тип данных. Он имеет следующий синтаксис —

(defclass class-name (superclass-name*)
   (slot-description*)
   class-option*))

Слоты — это переменные, в которых хранятся данные или поля.

Описание слота имеет форму (slot-name slot-option *), где каждая опция является ключевым словом, за которым следует имя, выражение и другие опции. Наиболее часто используемые варианты слотов —

  • : имя функции доступа

  • : выражение initform

  • : символ initarg

: имя функции доступа

: выражение initform

: символ initarg

Например, давайте определим класс Box с длиной, шириной и высотой трех слотов.

(defclass Box () 
   (length 
   breadth 
   height)
)

Предоставление доступа и контроля чтения / записи в слот

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

Вы можете указать аксессоры для каждого слота при определении класса. Например, возьмем наш класс Box —

(defclass Box ()
   ((length :accessor length)
      (breadth :accessor breadth)
      (height :accessor height)
   )
)

Вы также можете указать отдельные имена доступа для чтения и записи слота.

(defclass Box ()
   ((length :reader get-length :writer set-length)
      (breadth :reader get-breadth :writer set-breadth)
      (height :reader get-height :writer set-height)
   )
)

Создание экземпляра класса

Общая функция make-instance создает и возвращает новый экземпляр класса.

Он имеет следующий синтаксис —

(make-instance class {initarg value}*)

пример

Давайте создадим класс Box с тремя слотами: длина, ширина и высота. Мы будем использовать три слота для доступа к значениям в этих полях.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
   )
)
(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(format t "Length of the Box is ~d~%" (box-length item))
(format t "Breadth of the Box is ~d~%" (box-breadth item))
(format t "Height of the Box is ~d~%" (box-height item))

Когда вы выполняете код, он возвращает следующий результат —

Length of the Box is 10
Breadth of the Box is 10
Height of the Box is 5

Определение метода класса

Макрос defmethod позволяет вам определять метод внутри класса. В следующем примере наш класс Box расширяется, чтобы включить метод с именем volume.

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   

(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)

 ;setting the values 

(setf item (make-instance 'box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)

; displaying values

(format t "Length of the Box is ~d~%" (box-length item))
(format t "Breadth of the Box is ~d~%" (box-breadth item))
(format t "Height of the Box is ~d~%" (box-height item))
(format t "Volume of the Box is ~d~%" (volume item))

Когда вы выполняете код, он возвращает следующий результат —

Length of the Box is 10
Breadth of the Box is 10
Height of the Box is 5
Volume of the Box is 500

наследование

LISP позволяет вам определять объект в терминах другого объекта. Это называется наследством. Вы можете создать производный класс, добавив новые или новые функции. Производный класс наследует функции родительского класса.

Следующий пример объясняет это —

пример

Создайте новый файл исходного кода с именем main.lisp и введите в него следующий код.

Live Demo

(defclass box ()
   ((length :accessor box-length)
      (breadth :accessor box-breadth)
      (height :accessor box-height)
      (volume :reader volume)
   )
)

; method calculating volume   
(defmethod volume ((object box))
   (* (box-length object) (box-breadth object)(box-height object))
)
  
;wooden-box class inherits the box class  
(defclass wooden-box (box)
((price :accessor box-price)))

;setting the values 
(setf item (make-instance 'wooden-box))
(setf (box-length item) 10)
(setf (box-breadth item) 10)
(setf (box-height item) 5)
(setf (box-price item) 1000)

; displaying values
(format t "Length of the Wooden Box is ~d~%" (box-length item))
(format t "Breadth of the Wooden Box is ~d~%" (box-breadth item))
(format t "Height of the Wooden Box is ~d~%" (box-height item))
(format t "Volume of the Wooden Box is ~d~%" (volume item))
(format t "Price of the Wooden Box is ~d~%" (box-price item))

Когда вы выполняете код, он возвращает следующий результат —