Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pol_Grem_-_ANSI_Common_Lisp_High_tech_-_2012.pdf
Скачиваний:
28
Добавлен:
12.03.2016
Размер:
4.85 Mб
Скачать

7.5. Макрознаки

141

Чтобы­ макси­маль­но­ упро­стить­ пример,­ код на рис. 7.2. просто­ заме­ня­­ ет одну­ строку­ на другую­. Одна­ко­ его неслож­но­ обобщить­ и соору­дить­ поиск­ по полно­цен­ным­ шабло­нам­ вместо­ после­до­ва­тель­но­стей­ букв. Все, что вам потре­бу­ет­ся, ­– заме­нить­ вызов­ char= на функцию­ провер­ки­ на соот­вет­ст­вие­ шабло­ну­.

7.5. Макрознаки

Макро­зна­ки­ (macro character) – это знаки,­ имеющие­ особое­ значе­ние­ для функции­ read. Знаки­ a и b обычно­ обра­ба­ты­ва­ют­ся­ как есть, одна­ко­ знак откры­ваю­щей­ круглой­ скобки­ распо­зна­ет­ся­ как нача­ло­ считы­ва­­ ния списка­.

Макро­зна­ки­ или их комби­на­ция­ извест­ны­ также­ как макро­сы­ чтения­ (read-macro). Многие­ макро­сы­ чтения­ в Common Lisp на деле­ явля­ют­ся­ сокра­ще­ния­ми­. Напри­мер,­ кавыч­ка­. Цити­руе­мое­ выра­же­ние,­ напри­­ мер ’a, при обра­бот­ке­ с помо­щью­ read раскры­ва­ет­ся­ в список­ (quote a). При набо­ре­ подоб­но­го­ выра­же­ния­ в toplevel оно вычис­ля­ет­ся­ сразу­ же после­ прочте­ния,­ и вы нико­гда­ не увиди­те­ этого­ преоб­ра­зо­ва­ния­. Его можно­ обна­ру­жить,­ вызы­­вая read явно:­

> (car (read-from-string "’a")) QUOTE

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

Такие­ макро­сы­ чтения­ назы­­вают­ся­ диспет­че­ри­зуе­мы­ми­ (dispatching), а их первый­ знак назы­­вает­ся­ диспет­че­ром­. У всех стандарт­ных­ макро­­ сов чтения­ знаком­-диспет­че­ром­ явля­ет­ся­ решет­ка­ #. С неко­то­ры­­ми из них мы уже знако­мы­. Напри­мер,­ #’ соот­вет­ст­ву­ет­ (function ...), а ’ яв­ ляет­ся­ сокра­ще­ни­ем­ для (quote ...).

Следую­щие­ диспет­че­ри­зуе­мые­ макро­сы­ чтения­ мы также­ уже виде­ли:­ #(...) явля­ет­ся­ сокра­ще­ни­ем­ для векто­ров,­ #nА(...) – для масси­вов,­ #\ – для знаков,­ #S(n ...) – для структур­. При вы­воде­ на печать­ через­ prin1 (или format с ~S) такие­ объек­ты­ отобра­зят­ся­ в виде­ соот­вет­ст­вую­щих­ макро­сов­ чтения­.1 Это озна­ча­ет,­ что объек­ты,­ запи­сан­ные­ бук­валь­но,­ могут­ быть счита­ны­ обрат­но­ в таком­ же виде:­

> (let ((*print-array* t))

(vectorp (read-from-string (format nil "~S" (vector 1 2)))))

T

1Чтобы­ векто­ры­ и масси­вы­ печа­та­лись­ таким­ обра­зом,­ необ­хо­ди­мо­ уста­но­­ вить значе­ние­ *print-array*, равное­ t.

142

Глава 7. Ввод и вывод

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

Не все объек­ты­ отобра­жа­ют­ся­ в соот­вет­ст­вии­ с табли­цей­ чтения­ read­ table. Функции­ и хеш-табли­цы,­ к приме­ру,­ отобра­жа­ют­ся­ через­ #<...>. Факти­че­ски­ #< – тоже­ макрос­ чтения,­ одна­ко­ при пере­да­че­ в read он все­ гда вызы­­вает­ ошибку­. Функции­ и хеш-табли­цы­ не могут­ быть напе­ча­­ таны,­ а затем­ прочи­та­ны­ обрат­но,­ и этот макрос­ чтения­ гаран­ти­ру­ет,­ что пользо­ва­те­ли­ не будут­ питать­ иллю­зий­ на этот счет1.

При опре­де­ле­нии­ собст­вен­­ного­ представ­ле­ния­ для како­го­-либо­ объек­та­ (напри­мер,­ для отобра­же­ния­ структур)­ важно­ пом­нить этот прин­цип. Либо­ объект­ в вашем­ представ­ле­нии­ может­ быть прочи­тан­ обрат­но,­ ли­ бо вы исполь­зуе­те­ #<...>.

Итоги главы

1.Пото­ки ­– источ­ни­ки­ ввода­ и полу­ча­те­ли­ выво­да­. В пото­ках­ знаков­ ввод и вывод­ состо­ят­ из знаков­.

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

3.Ввод может­ обра­ба­ты­вать­ся­ как набор­ объек­тов,­ строка­ знаков­ или же как отдель­ные­ знаки­.

4.Функция­ format предос­тав­ля­ет­ полное­ управле­ние­ выво­дом­.

5.Чтобы­ осуще­ст­вить­ заме­ну­ строк в тексто­вом­ файле,­ вам придет­ся­ считы­вать­ знаки­ в буфер­.

6.Когда­ read встреча­ет­ макро­знак­ типа­ ’, она вызы­­вает­ связан­ную­ с ним функцию­.

Упражнения

1.Опре­де­ли­те­ функцию,­ возвра­щаю­щую­ список­ из строк, прочи­тан­­ ных из задан­но­го­ файла­.

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

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

1В Лиспе­ решет­ка­ с кавыч­кой­ не могут­ исполь­зо­вать­ся­ для описа­ния­ функ­ ций, так как этот макро­знак­ не в состоя­нии­ представ­лять­ замы­ка­ние­.

Упражнения

143

4. Опре­де­ли­те­ функцию,­ прини­маю­щую­ двумер­ный­ массив­ чисел­

сплаваю­щей­ запя­той­ и отобра­жаю­щую­ его в виде­ акку­рат­ных­ коло­­ нок. Каждый­ элемент­ должен­ печа­тать­ся­ с двумя­ знака­ми­ после­ за­ пятой­ на простран­ст­ве­ 10 знаков­. (Исхо­ди­те­ из предпо­ло­же­ния,­ что все они уместят­ся­ в отве­ден­ном­ простран­ст­ве­.) Вам потре­бу­ет­ся­ функция­ array-dimensions (стр. 374).

5.Изме­ни­те­ функцию­ stream-subst так, чтобы­ она пони­ма­ла­ шабло­ны­

смета­зна­ком­ +. Если­ знак + появ­ля­ет­ся­ в строке­ old, он может­ соот­­ ветст­во­вать­ любо­му­ знаку­.

6.Изме­ни­те­ функцию­ stream-subst так, чтобы­ шаблон­ мог содер­жать­ элемент,­ соот­вет­ст­вую­щий:­ любой­ цифре,­ любой­ цифре­ и бук­ве,­ лю­ бому­ знаку­. Шаблон­ должен­ уметь распо­зна­вать­ любые­ читае­мые­ знаки­. (Подсказ­ка:­ old теперь­ не обяза­тель­но­ должен­ быть строкой­.)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]