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

8

Символы

С Лисп-симво­ла­ми­ вы уже доволь­но­ хоро­шо­ знако­мы,­ но есть еще неко­­ торые­ вещи,­ на кото­рые­ стоит­ обра­тить­ внима­ние­. Пона­ча­лу­ не стоило­ углуб­лять­ся­ в меха­низм­ их реали­за­ции­. Вы може­те­ исполь­­зовать­ их как в каче­ст­ве­ объ­ектов,­ так и в каче­ст­ве­ имен для объ­ектов,­ не заду­мы­­ ваясь­ о том, каким­ обра­зом­ связа­ны­ эти две роли­. Но в какой­-то момент­ полез­но­ оста­но­вить­ся­ и разо­брать­ся­ с тем, что же проис­хо­дит­ внутри­. В этой главе­ подроб­но­ обсу­ж­да­ют­ся­ все дета­ли,­ связан­ные­ с симво­ла­ми­.

8.1. Имена символов

В главе­ 2 симво­лы­ описы­ва­лись­ как имена­ пере­мен­ных,­ суще­ст­вую­щие­ сами­ по себе­. Одна­ко­ область­ приме­не­ния­ симво­лов­ в Лиспе­ шире,­ чем область­ приме­не­ния­ пере­мен­ных­ в большин­ст­ве­ других­ язы­ков. На са­ мом деле,­ имя симво­ла ­– это обычная­ строка­. Имя симво­ла­ можно­ по­ лучить­ с помо­щью­ symbol-name:

> (symbol-name ’abc) "ABC"

Обра­ти­те­ внима­ние,­ что имена­ симво­лов­ запи­сы­ва­ют­ся­ в верхнем­ реги­­ стре­. По умолча­нию­ Common Lisp не чувст­ви­те­лен­ к реги­ст­ру,­ поэто­му­ при чтении­ он преоб­ра­зу­ет­ все бук­вы­ в именах­ к заглав­ным:­

>(eql ’aBc ’Abc)

T

>(CaR ’(a b c))

A

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

8.2. Списки свойств

145

черточ­ка­ми,­ счита­ет­ся­ симво­лом­. Таким­ обра­зом­ вы може­те­ помес­тить­ любые­ знаки­ в имя симво­ла:­

> (list ’|Lisp 1.5| ’|| ’|abc| ’|ABC|) (|Lisp 1.5| || |abc| ABC)

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

Так на какие­ же симво­лы­ мож­но ссылать­ся,­ не прибе­гая­ к исполь­зо­ва­­ нию верти­каль­ной­ черты?­ По сути,­ на все сим­волы,­ имена­ кото­рых­ не явля­ют­ся­ числом­ и не содер­жат­ знаков,­ имеющих­ для read специ­аль­но­­ го значе­ния­. Чтобы­ узнать,­ может­ ли символ­ суще­ст­во­вать­ без тако­го­ оформле­ния,­ доста­точ­но­ просто­ посмот­реть,­ как Лисп его напе­ча­та­ет­. Если­ при печа­ти­ символ­ не будет­ обрам­лен­ верти­каль­ны­ми­ черточ­ка­­ ми, как послед­ний­ символ­ в преды­ду­щем­ при­мере,­ значит­ и вам не нужно­ их исполь­зо­вать­.

Следу­ет­ помнить,­ что верти­каль­ные­ черточ­ки ­– специ­аль­ный­ синтак­­ сис, а не часть имени­ симво­ла:­

> (symbol-name ’|a b c|) "a b c"

(Если­ вы желае­те­ включить­ черточ­ку­ в имя симво­ла,­ распо­ло­жи­те­ пе­ ред ней знак «\».)

8.2.Списки свойств

ВCommon Lisp каждый­ символ­ имеет­ собст­вен­­ный список­ свойств (property­-list, plist). Функция­ get прини­ма­ет­ символ­ и ключ, возвра­щая­ значе­ние,­ связан­ное­ с этим ключом,­ из списка­ свойств:

> (get ’alizarin ’color) NIL

Для сопос­тав­ле­ния­ ключей­ исполь­зу­ет­ся­ eql. Если­ указан­ное­ свойст­во­ не зада­но,­ get возвра­ща­ет­ nil.

Чтобы­ ассо­ции­ро­вать­ значе­ние­ с ключом,­ можно­ исполь­зо­вать­ setf вме­ сте с get:

>(setf (get ’alizarin ’color) ’red) RED

>(get ’alizarin ’color)

RED

Теперь­ свойст­во­ color (цвет) сим­вола­ alizarin имеет­ значе­ние­ red (крас­ ный).

Функция­ symbol-plist возвра­ща­ет­ список­ свойств симво­ла:­

>(setf (get ’alizarin ’transparency) ’high) HIGH

>(symbol-plist ’alizarin)

(TRANSPARENCY HIGH COLOR RED)

146

Глава 8. Символы

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

В Common Lisp списки­ свойств исполь­зу­ют­ся­ доволь­но­ редко­. Они в зна­ читель­ной­ мере­ вытес­не­ны­ хеш-табли­ца­ми­.

8.3. А символы-то не маленькие

Симво­лы­ созда­ют­ся­ неяв­ным­ обра­зом,­ когда­ мы печа­та­ем­ их имена,­

ипри отобра­же­нии­ самих­ симво­лов­ их имена ­– это все что мы видим­. При таких­ обстоя­тель­ст­вах­ легко­ поду­мать,­ что символ ­– это лишь имя

иниче­го­ более­. Одна­ко­ многое­ скрыто­ от наших­ глаз.

Из того,­ как мы видим­ и исполь­зу­ем­ симво­лы,­ может­ пока­зать­ся,­ что это малень­кие­ объек­ты,­ такие­ же как, скажем,­ целые­ числа­. На самом­ деле,­ симво­лы­ обла­да­ют­ внуши­тель­ны­ми­ разме­ра­ми­ и более­ похо­дят­ на структу­ры,­ опре­де­ляе­мые­ через­ defstruct. Символ­ может­ иметь имя, пакет,­ значе­ние­ связан­ной­ с ним пере­мен­ной,­ значе­ние­ связан­ной­ функ­ ции и список­ свойств. Устрой­ст­во­ симво­ла­ и взаимо­связь­ между­ его компо­нен­та­ми­ пока­за­ны­ на рис. 8.1.

Мало­ кто исполь­зу­ет­ настоль­ко­ большое­ коли­че­ст­во­ симво­лов,­ чтобы­ вставал­ вопрос­ об эконо­мии­ памя­ти­. Одна­ко­ стоит­ держать­ в уме, что симво­лы ­– полно­цен­ные­ объек­ты,­ а не просто­ имена­. Две пере­мен­ные­ могут­ ссылать­ся­ на один символ,­ так же как и на один список:­ в таком­ случае­ они имеют­ указа­тель­ на общий­ объект­.

 

name

"FOO"

 

package

 

 

value

27

 

function

#<function>

package

plist

(color red)

 

 

Рис. 8.1. Структу­ра­ симво­ла­

8.4.Создание символов

Вразделе 8.1 было­ пока­за­но,­ как полу­чать­ имена­ симво­лов­. Также­ воз­ можно­ и обрат­ное­ дейст­вие ­– преоб­ра­зо­ва­ние­ строки­ в символ­. Это бо­ лее сложная­ зада­ча,­ пото­му­ что для ее вы­полне­ния­ необ­хо­ди­мо­ иметь представ­ле­ние­ о паке­тах­.

8.5. Использование нескольких пакетов

147

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

Большин­ст­во­ симво­лов­ интер­ни­ру­ют­ся­ во время­ считы­ва­ния­. Когда­ вы впервые­ вводи­те­ символ,­ Лисп созда­ет­ новый­ символь­ный­ объект­ и ин­ терни­ру­ет­ его в теку­щий­ пакет­ (по умолча­нию­ это common-lisp-user). Од­ нако­ вы може­те­ сделать­ то же самое­ вручную­ с помо­щью­ intern:

> (intern "RANDOM-SYMBOL") RANDOM-SYMBOL

NIL

Функция­ intern прини­ма­ет­ также­ допол­ни­тель­ный­ аргу­мент ­– пакет­ (по умолча­нию­ исполь­зу­ет­ся­ теку­щий)­ . Приве­ден­ный­ выше­ вызов­ соз­ дает­ в теку­щем­ паке­те­ символ­ с именем­ "RANDOM-SYMBOL", если­ тако­го­ симво­ла­ пока­ еще нет в данном­ паке­те­. Второй­ аргу­мент­ возвра­ща­ет­ ис­ тину,­ когда­ такой­ символ­ уже суще­ст­ву­ет­.

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

вглаве 10.

8.5.Использование нескольких пакетов

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

При исполь­зо­ва­нии­ язы­ков, не поддер­жи­ваю­щих­ разде­ле­ние­ простран­­ ства­ имен, програм­ми­стам,­ рабо­таю­щим­ над серьез­ны­ми­ проек­та­ми,­ прихо­дит­ся­ вводить­ дого­во­рен­но­сти,­ чтобы­ избе­жать­ конфлик­тов­ при исполь­зо­ва­ния­ одних­ и тех же имен. Напри­мер,­ разра­бот­чик­ подсис­те­­ мы отобра­же­ния,­ веро­ят­но,­ будет­ исполь­зо­вать­ имена,­ начи­наю­щие­ся­ с disp_, в то время­ как програм­мист,­ разра­ба­ты­ваю­щий­ мате­ма­ти­че­­ ские проце­ду­ры,­ будет­ приме­нять­ имена,­ начи­наю­щие­ся­ с math_. Так, напри­мер,­ функция,­ вы­полняю­щая­ быстрое­ преоб­ра­зо­ва­ние­ Фурье,­ вполне­ может­ носить­ имя math_fft.

Паке­ты­ выпол­ня­ют­ эту рабо­ту­ само­стоя­тель­но­. Внутри­ отдель­но­го­ па­ кета­ мож­но исполь­зо­вать­ любые­ имена­. Только­ те симво­лы,­ кото­рые­ бу­ дут явным­ обра­зом­ экспор­ти­ро­ва­ны­, будут­ види­мы­ в других­ паке­тах,­ где будут­ доступ­ны­ с помо­щью­ префик­са­ (или квали­фи­ци­ро­ва­ны­), соот­­ ветст­вую­ще­го­ имени­ содер­жа­ще­го­ их паке­та­.

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