Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Изучение системных свойств символа в диалекте языка ЛИСП(1).doc
Скачиваний:
8
Добавлен:
01.05.2014
Размер:
172.03 Кб
Скачать

2.3.1. Числа

Числа, которые можно использовать в программе, написанной на mulisp, подразделяются на целые и дробные, а целые, в свою очередь, – на малые (с абсолютной величиной менее 65536) и большие.

Любое число является простым объектом и задается с помощью четырех полей:

Табл. 2.2

IDENTITY

SIGN

LENGTH

VECTOR

Само число «знак» длина вектор

Поле IDENTITY содержит указатель самого числа, доступен как CAR, но не может быть изменен.

Содержимое поля SIGN можно выяснить, рассматривая следующую таблицу:

Табл. 2.3

SIGN

+

-

Малое целое

NIL

T

Большое целое

LAMBDA

NLAMBDA

Дробное

MACRO

SPECIAL

SIGN доступен как CDR, но не может быть изменен.

LENGTH определена следующим образом: это величина числа, если число малое; длина слова вектора, если число большое целое; указатель на числитель, если число дробное

2.3.2 Внутреннее представление символа

Символ – распознаваемый объект, состоящий из четырех элементов-указателей

Табл. 2.4

Value

Property

Function

p-name

где Value - значение

Property - список свойств

Function - определение функции

p-name - печатное имя.

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

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

Список свойств первоначально равен пустому списку NIL.

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

Задание для самостоятельной работы: Выяснить, как задаются и изменяются значения системных свойств в mulisp’е. Составить таблицу, аналогичную таблицу 2.1.

2.4. Организация ввода/вывода

Все программы (в том числе, и ЛИСП -программы) общаются с окружающей средой при помощи средств ввода/вывода. Многие реализации ЛИСПа предоставляют достаточно широкие возможности для организации ввода/вывода, вследствие чего это разнообразие привело к несовместимости отдельных функций. Мы рассмотрим стандартные функции ЛИСПа, существующие как в COMMON LISPе, так и в mulispе.

Ввод/вывод осуществляется в LISPе в процессе сеанса общения с интерпретатором, которое производится в цикле READ-EVAL-PRINT. Кроме того, ввод и вывод осуществляются при выполнении специальных функций. Ввод и вывод в ЛИСПе осуществляется через потоки. Стандартные потоки ввода/вывода в COMMON LISPе задаются глобальными переменными *STANDARD-INPUT* и *STANDARD-OUTPUT*. Эти переменные отсутствуют в mulispе, зато в нем есть функции (RDS) и (WRS), которые назначают входной и выходной потоки, соответственно, например,

(RDS 'D:RDB)

открывает файл "D:RDB.LSP" и назначает поток ввода на него.

После того, как файл был открыт и назначен функцией (RDS) или (WRS), поток ввода или вывода можно вновь назначить на консоль путем присвоения переменной RDS или WRS, соответственно, значения NIL. В дальнейшем, при присвоении переменной ненулевого значения, поток вновь будет связан с текущим открытым файлом (чтение или запись будут возобновляться с текущей позиции).

(RDS) и (WRS) без аргумента назначают поток ввода (вывода) на консоль и закрывают файлы открытые для ввода (вывода).

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

Функции вывода, например, PRINT, воспринимают объект и посылают его печатное представление в поток вывода. Набор программ, выполняющих это действие в ЛИСПе называется процедурой печати, LISP-printer.

Аналогично, при вводе, функция ввода, например, READ, берет символы из потока, интерпретирует их как печатное представление ЛИСП-объекта и строит этот объект. Таким образом, при чтении печатного представления получается объект, равный (в смысле EQUAL) исходному объекту.

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

Пример

Число 27 можно представить как

27

27.

#о33

#х113

81/3

(* 3 3 3)

Список (а в) можно представить как

(а в)

( а в )

|в|

)

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

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

2.4.1. Функции ввода в mulisp

Функция READ

Функция (READ) считывает одно целое выражение из стандартного потока ввода

и возвращает эквивалентный связанный список. Правильно составленные

выражения с использованием либо списковых, либо точечных изображений,

либо их комбинаций, являются допустимыми входными данными для функции

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

Пример

В результате выполнения обращения к

(SETQ SYMB (READ))

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

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

Макро-символы при вводе обрабатываются специальным образом. Когда

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

ассоциированную с данным символом.

В стандартно определенный набор входят следующие символы:

<Tab>, <Space>, <NewLine> – разделители;

\ – "Escape" -- игнорируется обычное синтаксическое значение

следующего символа;

| – начало и конец объекта (эквивалентно '\' перед каждой буквой

определения);

( – начало ввода списка или точечной пары;

) – конец ввода списка или точечной пары;

' – возвращает следующее за ним выражение с QUOTE;

; – начало комментария (до конца строки);

" – начало или конец строки;

Макро-символы в составе имен можно употреблять, только выделив их с помощью '\' или '|', которые блокируют макро-обработку.

Существуют также функции, получающие текущее определение для макро-символа:

В COMMON LISP это

GET-MACRO-CHARACTER аргумент

а в mulisp

GET-MACRO-CHAR аргумент

где аргумент – символ, определение которого необходимо получить.

Функция READ-CHAR

(READ-CHAR [peek-flag]) считывает очередной элемент из потока

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

peek-flag не равен NIL, элемент не извлекается из входного потока (особенность MULISP'а)

Функция UNREAD-CHAR

(UNREAD-CHAR) восстанавливает последний элемент, считанный из

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

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

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

Функция PEEK-CHAR

(PEEK-CHAR [флаг]) считывает следующий элемент из входного потока, не

извлекая его оттуда, т.е.,

(PEEK-CHAR) <==> (PROG1 (READ-CHAR) (UNREAD-CHAR))

(PEEK-CHAR T) считывает элементы из входного потока до тех пор,

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

Обращение (PEEK-CHAR <элемент>), где <элемент> – символ, вызывает считывание элементов из входного потока до тех пор, пока не встретится элемент, равный первому

символу в печатном имени <элемента>.

Во всех случаях, PEEK-CHAR восстанавливает последний считанный из входного потока элемент во входном потоке.

Пример

$ (PEEK-CHAR 'M) COMPUTER

производит именно те действия, которые Вы можете видеть на предыдущей

строке.

Функция CLEAR-INPUT

При обращении (CLEAR-INPUT) очищается текущий буфер ввода.

Функция READ-LINE

(READ-LINE) считывает элементы из стандартного потока ввода до тех

пор, пока не встретится <Return>, и возвращает символ , у которого печатное имя

состоит из всех считанных элементов, кроме <Return>.

READ-LINE возвращает строку такой, как она есть, не отбрасывая пустые места или комментарии.

2.4.2 Функции вывода в mulisp

Функции вывода, как отмечалось ранее, выводят печатное представление символа ЛИСПа в стандартный поток вывода.

Функция PRIN1

(PRIN1 <обьект>) передает символьное представление <обьекта> в

стандартный поток вывода и возвращает <обьект> в качестве значения.

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

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

*PRINT-ESCAPE* – при значении T выводятся ESCAPE-символы ('\', '|' и т.п.),

при значении NIL не выводятся

*PRINT-BASE* – основание системы счисления, используемое при выводе

чисел.

*PRINT-POINT* – количество знаков после запятой при выводе чисел с

плавающей точкой.

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

значение контрольной переменной *PRINT-ESCAPE* не играет роли.

Функция PRINT

При выполнении обращения (PRINT обьект) символьное представление <обьекта> передает в стандартный поток вывода, с использованием PRIN1, осуществляется переход на следующую строку и возвращение <объекта> в качестве результата. Эквивалентное определение PRINT:

(DEFUN PRINT (OBJ) (PRIN1 OBJ) (TERPRI) OBJ )

Функция TERPRI

(TERPRI [<n>]) передает в стандартный поток вывода <n> символов

новой строки. При отсутствии <n> выводится 1 символ. В качестве

результата возвращается NIL.

Функция WRITE-BYTE

Это функция, специфичная для MULISPа.

Если <n> - целое число в пределах от 0 до 255 включительно,

(WRITE-BYTE <n>) записывает байт с ASCII кодом <n> в стандартный поток

вывода и возвращает <n>.

Замечание. Примерно эквивалентная функция в COMMON LISPе

называется WRITE-CHAR и выводит знак,

т.е. (WRITE-BYTE <n>) <==> (WRITE-CHAR (ASCII <n>))

Функция SPACES

(SPACES [<n>]) передает в стандартный поток вывода <n> символов

пробела. При отсутствии <n> выводится 1 символ. В качестве результата

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

Функции WRITE-STRING и WRITE-LINE

Если <символ> – символ, то

(WRITE-STRING <символ>) и (WRITE-LINE <символ>)

записывают элементы печатного имени <символа> в поток вывода и возвращает <сим-

вол>. WRITE-LINE записывает элемент новой строки после пересылки Р-имени.

Если <символ> - не символ, то обе функции возвращают NIL. Следует заме-

тить, что функции COMMON LISP'а с такими же названиями выводят подстроку

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

Функция LINELENGTH

Если <n> - положительное целое, (LINELENGTH <n>) определяет длину

строки для вывода ее системным принтером в файле так, что строки

автоматически ограничиваются по длине <n> символами. В качестве

результата возвращается предыдущая длина строки. Если <n> неположительное

целое или не задано, функция выдает текущую длину строки. На вывод строк

на консоль данная функция не оказывает влияния.