Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие Функциональное и логическое программирование.docx
Скачиваний:
4
Добавлен:
01.07.2025
Размер:
309.57 Кб
Скачать

Функция get - возвращает значение свойства, связанного с символом:

(GET символ свойство )

При отсутствии свойства функция GET возвращает NIL в качестве ответа.

Пусть имя студент имеет следующий список свойств (имя Иван отчество Иванович фамилия Иванов):

(GET ‘студент ‘имя) => Иван

(GET ‘студент ‘группа) => NIL

Присваивание свойства или изменение значения существующего свойства осуществляется уже известными нам функциями:

(SETF (GET символ свойство) значение)

Например:

(SETF (GET ‘студент ’группа) ’КИО8-15) => КИО8-15

(GET ‘студент ’группа) => КИО8-15

Псевдофункция remprop удаляет свойство и его значение:

(REMPROP символ свойство)

Эта функция возвращает в качестве значения имя удаляемого свойства. Если удаляемого свойства нет, то возвращается NIL:

(REMPROP ‘студент ’группа) => группа

(GET ‘студент ’группа) => NIL

(REMPROP ‘студент ’ср_бал) => NIL

Для просмотра всего списка свойств используют функцию SYMBOL-PLIST. Значением функции является весь список свойств.

(SYMBOL-PLIST символ)

Пример:

(SYMBOL-PLIST ‘студент) => (имя Иван отчество Иванович фамилия Иванов)

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

(SETF (get 'st 'sv1) '1) => 1

(GET 'st 'sv1) => 1

(SETQ st1 'st) => st

(GET st1 'sv1) => 1

Вызов интерпретатора eval вычисляет значение выражения.

Интерпретатор ЛИСПа называется EVAL. Его можно так же, как и другие функции вызывать из программы.

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

QUOTE и EVAL действуют в противоположных направлениях и аннулируют друг друга. EVAL – универсальная функция ЛИСПа, вычисляющая любое правильно составленное s-выражение.

Эта функция определяет семантику лисповских форм, т.е. определяет, какие символы и формы совместно с чем и что означают и какие выражения имеют значения. Семантика ЛИСПа легко определяется на самом ЛИСПе. Большая часть системных программ в ЛИСП-системах написана на ЛИСПе, и пользователь легко может изменить систему в зависимости от своих потребностей. Транслятор также целиком написан на ЛИСПе.

Примеры:

(EVAL (QUOTE (+ 2 3))) => 5

(SETQ x '(a b c)) => (a b c)

'x => x

x => (a b c)

(EVAL 'x) => (a b c)

(EVAL x) => error: unbound function – a

(SETQ x '(+ 2 3)) => (+ 2 3)

x => (+ 2 3)

(EVAL 'x) => (+ 2 3)

(EVAL x) => 5

Ввод и вывод.

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

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

Для выполнения ввода существует функция:

(READ)

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

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

Если прочитанное значение необходимо сохранить для дальнейшего использования, то вызов (READ) должен быть аргументом какой-нибудь формы, например, присваивания, которая свяжет полученное выражение:

(setq a (read))

Форма, вызывающая интерпретатор (EVAL), и функция (READ) совместно с другими функциями позволяют читать выражения, внешние по отношению к программе. Из них можно строить новые Лисповские выражения или целые программы. Построенные структуры можно вычислить, передав их непосредственно интерпретатору:

Пример 1.

(eval (list (read) (read) (read)))

cons 23 '(1 2 3) => (23 1 2 3)

Пример 2.

(setq a 34)

(eval (list (read) (read) (read)))

/ a 2 => 17

Для выполнения вывода в Лиспе существует функция:

(PRINT арг. )

Это функция с одним аргументом, которая сначала вычисляет значение аргумента, а затем выводит это значение.

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

Значением функции является значение ее аргумента, побочным эффектом – печать этого значения.

Операторы ввода-вывода могут быть аргументами других функций:

(+ (print 2) 3)

=> 2

=> 5

Функции

(PRIN1 арг.)

(PRINC арг.)

позволяют выводить данные без перехода на новую строку. PRINC осуществляет символьный вывод. Различие: PRIN1 выводит строку в кавычках, а PRINC без кавычек.

(progn (princ "(((") (prin1 123) (princ ")))"))

=> (((123)))

=> ")))"

Функция (TERPRI) осуществляет перевод строки.

Для форматированного вывода предназначена функция:

(FORMAT поток образец &REST аргументы).

Поток – задает файл или устройство, куда осуществляется вывод;

- Т – вывод на экран.

- при выводе в файл потоком является поток вывода, представляющий этот файл.

NIL – у такой формы есть лишь значение (строка, построенная по образцу с помощью управляющих кодов и аргументов) и нет побочного эффекта, связанного с выводом.

Образец – управляющая строка, которая содержит управляющие коды. Перед управляющим кодом ставится знак ~ (тильда).

~% - переводит строку

~S – выводит функцией PRIN1 значение очередного аргумента

~А – выводит функцией PRINС значение очередного аргумента

~nТ – начинает вывод с колонки n. Если ее уже достигли, то выводится пробел.

~~ - выводит сам знак тильды.

Аргументы ставятся в соответствие управляющим кодам строки:

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

Примеры форматированного вывода.

Пример 1.

(format t "111~%222~%333")

111 печать

222 печать

333 печать

NIL результат

Пример 2.

(format nil "otvet - ~S" (+ 2 3)) печати нет

= > "otvet - 5" значением является строка

Пример 3.

(setq x 2) => 2

(setq y 3) => 3

(format t "~S + ~S = ~S~%" x y (+ x y))

2 + 3 = 5 печать

NIL результат

Пример 4.

(defun tabl (sp)

(format t "~%FIO~10Ttelefon")

(do ((x sp (rest x)))

((null x) (terpri))

(format t "~%~A~10T~A" (caar x) (cadar x))))

(tabl '((IVANOV 12-34-12)(PETROV 43-23-65)(SIDOROV 32-12-65)))

FIO telefon

IVANOV 12-34-12

PETROV 43-23-65

SIDOROV 32-12-65