- •Введение
- •Понятие функционального программирования
- •Языки функционального программирования
- •Лямбда-исчисление Введение в лямбда-исчисление
- •Алонсо Черч
- •Иллюстрация ромбического свойства на примере
- •Прикладные лямбда-исчисления
- •Данные и выражения языка Lisp. Понятия списков и атомов, вычисление функций.
- •Организация памяти Lisp-машины
- •Функции проверки типов и логические функции
- •Манипуляция элементами списков
- •Основные конструкции Лямбда - выражения и пользовательские функции
- •Последовательности вычислений
- •Условные операторы и циклы
- •Рекурсия
- •Проверка на вхождения атома в список
- •Удаление из списка n-ного элемента
- •Добавление в список элемента в позицию n
- •Функционалы
- •Макросы
- •Ввод и вывод
- •Типы данных Иерархия типов
- •Символы
- •Последовательности
- •Массивы
- •Структуры
- •Лабораторные работы Лабораторная работа 1
- •Лабораторная работа 2
- •Лабораторная работа 3
- •Дана схема метрополитена, найти кратчайший путь между станциями.
- •Игра в 15.
- •Задача о 8-ми ферзях.
- •Задача о 8-ми ферзях 2.
- •Задача о Ханойской башне.
- •Задача о составлении расписания
- •Раскрасить плоскую карту четырьмя цветами, так что бы любые две смежные области не были окрашены в один цвет
- •Задача о коммивояжере.
- •Лабораторная работа 4
Ввод и вывод
Одной из основных задач для каждого языка программирования является организация взаимодействия с пользователем. В Lisp для этой цели предусмотрены функции ввода-вывода для стандартного устройства, а также функции работы с файлами.
read |
(read [поток]) Функция читает выражение из консоли и возвращает его в качестве результата. Функция никак не показывает пользователю, что ожидается ввод. В этой функции и далее: если поток не указан, чтение (или для других функций запись) производится со стандартного устройства ввода - консоли. |
>(read) >>a+b A+B |
Здесь при вызове функции READ пользователь ввёл выражение A+B (символ >> символизирует приглашение к вводу и не должен переноситься в текст при попытке выполнить пример). Результатом вычисления явилось собственно введённое выражение.
В качестве примера рассмотрим вычисление суммы от двух введённых чисел:
>(* (read) (read)) >>3 >>8 24
>(* (read) (read)) >>3 8 24 |
Иными словами, Lisp, как и большинство языков высокого уровня, выполняет синтаксический разбор ввода с консоли и выделяет параметры, идущие через пробел. При этом READ вводит именно выражения, т.е. если бы в примере мы ввели, например, (+ 5 7) (- 6 4) то этот ввод также был бы распознан как два параметра, другое дело что подобное выражение недопустимо в рамках примера. Модифицируем пример следующим образом:
>(* (eval (read)) (eval (read))) >>(+ 5 7) (- 6 4) 24 |
Некоторые символы в Lisp при вводе указывают интерпретатору на выполнение определённых действий (например, скобки, пробел, точка). Lisp хранит информацию о таких символах в специальной таблице, называемой таблице чтения. Эти символы называются макрознаками, и их набор может быть изменён (вследствие чего, естественно, может измениться и синтаксис языка Lisp).
set-macro-character |
(set-macro-character символ функция) Функция сопоставляет символу некоторую функцию, обрабатывающую этот символ при синтаксическом разборе выражений. Функция разбора должна иметь два аргумента - поток чтения и собственно символ, который мы обрабатываем. |
Следующий пример заставляет Lisp интерпретировать символ % так же, как апостроф (т.е. как функцию QUOTE)
>(SET-MACRO-CHARACTER #\% (lambda (stream char) (list 'quote (read)))) T > %(A) (A) |
prin1 princ |
(print выражение [поток]) (prin1 выражение [поток]) (princ выражение [поток]) Функция выводит данные на консоль. PRINT выводит данные, печатает пробел и переводит строку. В различных диалектах указанные действия производятся в различной последовательности. Кроме того, иногда функция не печатает пробел. PRIN1 работает точно также, но не переводит строку. PRINC работает также, как и PRIN1, но преобразует при выводе некоторые типы данных (например, строковые) к более приятному для восприятия виду. |
>(progn (setq data "a b c d") (print data) (prin1 data) (princ data))
"a b c d" "a b c d"a b c d "a b c d" |
Как видно из примера, в Allegro Common Lisp функция PRINT сперва перевела строку, а затем вывела данные и пробел. Затем функция PRIN1 вывела те же самые данные, но строку не перевела и пробел не напечатала. Наконец, PRINC вывела всё ту же самую строку, но при выводе исключила кавычки. Однако, результатом этой функции, как мы видим, является всё та же строка.
terpri |
(terpri [поток]) Функция переводит строку в стандартном устройстве вывода. |
format |
(format поток образец [аргументы]) Функция выводит строку в соответствии с образцом. Если вы качестве потока задаётся Т, то вывод производится на экран, в противном случае необходимо указать ассоциированный с файлом и открытый поток вывода. В качестве образца в функцию подаётся строка, определяющая формат вывода (в чём-то сходная со строкой форматирования функции printf языка С). Значения управляющих символов в строке даны в таблице 1. Текст в образце, не являющийся управляющими символами, также печатается. Функция возвращает в качестве своего значения nil. |
Таблица 1
Символы управления выводом функции format
Символ |
Смысл |
~% |
Перевод строки |
~S |
Вывод очередного аргумента функцией PRIN1 |
~A |
Вывод очередного аргумента функцией PRINС |
~nT |
Начинает вывод с колонки n. Если она уже была достигнута, выводится пробел. |
~~ |
(Два знака тильды подряд) Вывод самого знака тильды |
>(format t "~~Первый параметр ~A и второй параметр ~S" 5 7) ~ 5 7 NIL |
Данная функция весьма удобна при выводе таблиц:
>(format t "~10T~%~A~10T~A~%~A~10T~A~%~A~10T~A~%" 1 2 3 4 5 6) 1 2 3 4 5 6 |
Файловый ввод и вывод несколько отличается от работы с консолью. Во-первых, для работы с файлом его надо ассоциировать с потоком и открыть. Во-вторых, по окончании работы с файлом его надо закрыть. Также различаются файлы последовательного доступа, где записи могут быть получены последовательным чтением с начала файла, и файлы прямого доступа, в которых в любой момент можно обратиться к каждой записи.
Для работы с файлами в Lisp предусмотрены следующие средства. Во-первых, определены специальные символы, указывающие на стандартное устройство ввода и стандартное устройство вывода. Эти символы, например, могут применяться в функциях PRIN1, PRINC и READ, а также FORMAT.
*STANDARD-INPUT* *STANDARD-OUTPUT*
|
Символы указывают на стандартные устройства ввода и вывода соответственно (т.е. клавиатуру и экран). |
Можно также связать какой-либо поток с файлом, используя специальные функции.
open |
(open файл направление_обмена) Функция открывает файл для чтения или записи. Если файл необходимо открыть для чтения, в качестве направления обмена указывается :INPUT, если для записи -:OUTPUT. Для одновременного чтения и записи указывают направление обмена :IO. В качестве возвращаемого значения передаётся открытый поток, который может быть использован в других функциях. |
close |
(close поток) Функция закрывает поток, открытый ранее с помощью OPEN |
with-open-file |
(with-open-file (имя_потока имя_файла направление_обмена) формы) Функция открывает поток, выполняет все формы и закрывает поток, не требуя от пользователя никаких дополнительных действий. |
Отдельно следует отметить функцию, существенно облегчающую написание Lisp-программ и позволяющую создавать их во внешних редакторах и дробить на части:
load |
(load имя_файла) Функция загружает и исполняет код на языке Lisp, хранящийся в указанном файле. |
