- •2. Описание лабораторных работ по функциональному программированию на языке лисп
- •2.1. Краткие теоретические сведения по программированию на языке Лисп
- •Основные функции обработки списков
- •Присваивание значений
- •Предикаты
- •Определение функций
- •Ввод-вывод
- •2.2. Лабораторная работа по теме «Знакомство с основными понятиями в системе программирования Лисп»
- •2.3. Лабораторная работа по теме «Решение задач с ветвлением в системе программирования Лисп»
- •2.4. Лабораторная работа по теме «Реализация рекурсии на языке Лисп»
- •2.5. Лабораторная работа по теме «Обработка списков на языке программирования Лисп»
Ввод-вывод
При работе с интерпретатором Лиспа ввод-вывод выполняется автоматически. Интерпретатор читает вводимое пользователем s-выражение (READ), вычисляет его (EVAL) и выводит результаты (PRINT). В простейшем случае функция READ не требует аргументов. После вызова этой функции происходит обращение к стандартному входному потоку и считывание введенного пользователем s-выражения. Введенное выражение возвращается в точку вызова READ.
Определим функцию, которая находит сумму четырех введенных с клавиатуры чисел:
(defun sum4 ()
(+ (read) (read) (read) (read))
Для вызова этой функции необходимо напечатать (sum4), а затем ввести четыре числа:
> (sum4)
1 234
─ > 10
>
Если требуется вводить данные из файлов, то сначала необходимо открыть с помощью функции OPEN соответствующий входной поток:
(setf vvod (open "extern.dat" direction :input))
Для чтения выражений из открытого потока WOD необходимо сообщить его имя функции READ, т.е.
(read vvod)
В этом случае произойдет обращение к файлу "extern.dat", и из него будет считано одно s-выражение. Результатом вызова функции READ будет s-выражение, введенное из файла.
Для вывода значений в Лиспе используется функция PRINT. Эта функция имеет один аргумент, значение которого выводится в выходной поток. Функция PRINT перед выводом значения осуществляет переход на новую строку, а после печати значения выводит пробел
(print '(abc))
(a b с)
─ > (А В С)
Здесь список (А В С) дважды отображается на экране. Дополнительный автоматический вызов функции PRINT происходит в цикле READ-EVAL-PRINT интерпретатора.
Для вывода значений могут также использоваться функции PRIN1 и PRINC. Функция PRIN1 аналогична PRINT, но не выполняет переход на новую строку и не выводит пробел. Функция PRINC дает возможность напечатать строку без ограничивающих кавычек:
(princ "lisp") ─ > lisp
Для перехода при выводе значений на новую строку можно использовать функцию TERPRI. У функции TERPRI нет аргументов. Если требуется вывести на печать имя символа, содержащее пробелы, скобки или строчные и заглавные буквы, то применяют знак отмены "\" или ограничивающие вертикальные линии "|". Все рассмотренные функции вывода позволяют осуществлять вывод в выходной поток открытый, с помощью функции OPEN:
(serf stran (open "extern.dat" direction :output :if-exists :append))
(print '|a b с d| stran) ─> |a b с d|
(print '\a\C \ \d stran) ─> |aC d|
(princ '|a b с d| stran) ─ > |a b с d|
Здесь вторым аргументом функции является выходной поток STRAN, связанный с файлом EXTERN.DAT.
При работе с файлами удобно использовать макроформу WITH-OPEN-FILE. Она позволяет открыть поток, задать режим работы с ним, выполнить необходимую его обработку и закрыть его:
(with-open-file (поток имя-файла {опция}*) {декларация}* {форма}*)
Вызов WITH-OPEN-FILE базируется на использовании функции OPEN. Режимы открытия потока задаются с помощью аргумента опция. Они полностью соответствуют ключевым параметрам, указываемым при вызове функции OPEN. Формы вызова WITH-OPEN-FILE вычисляются последовательно. В качестве результата возвращается значение последней формы. В приведенном ниже примере открывается поток с именем STORE, который связывается с файлом TEST1.LSP. В файл циклически записываются s-выражения, вводимые с клавиатуры. Формирование файла завершается, если с клавиатуры вводится атом EOF:
(defun writer ()
(with-open-file (store "testl .lsp" : direction :output
: if-exists : append
: if-does-not-exist :create)
(princ "Введите s-выражение")
(terpri)
(princ "Для завершения ввода напечатайте EOF")
(terpri)
(do ((item (read) (read))) ; чтение s-выражения
((eq item 'eof) 'end-of-session)
(print item store ) )))
Для управления формой вывода в Коммон Лиспе применяется функция FORMAT:
(format поток шаблон &REST аргументы )
Если поток задан символом Т, то функция осуществляет вывод на экран. Шаблон представляет собой строку, которая может содержать коды для управления печатью. Перед управляющими кодами записывается знак "~" (тильда). Если в шаблоне нет управляющих кодов, то функция FORMAT выводит строку шаблона так же, как и функция PRINC.