Глава 10 сопоставление с образцом


Содержание

Глава 10 сопоставление с образцом

Хотя Лисп сам по себе не имеет встроенного сопоставления с образцом, легко написать на этом языке функции, осуществляющие сопоставление образцов. Можно поэтому сказать, что Лисп является хорошим языком для реализации сопоставления образцов.

Многие реализованные подмножества языка с возможностями сопоставления имеют те свойства, которые будут продемонстрированы нами ниже.

В сопоставлении участвуют подобные s-выражения

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

Ниже мы построим функцию, называемую MATCH (СОПОСТАВЛЕНИЕ), которая будет сопоставлять один образец и один факт. Эта функция будет интенсивно применяться для иллюстраций того, как реализуются и используются функции сопоставления. Сначала, однако, посмотрим, что, собственно, ищет функция MATCH.

Когда с некоторым фактом сравнивается образец, не содержащий специальных атомов, то сопоставление считается успешным только тогда, когда они в точности одинаковы, так что каждая позиция занята у них одинаковыми атомами. Если мы сопоставляем (ЦВЕТ ЯБЛОКО КРАСНЫЙ), как образец, с идентичным фактом (ЦВЕТ ЯБЛОКО КРАСНЫЙ), то сопоставление будет, разумеется, успешным:

Но сопоставление (ЦВЕТ ЯБЛОКО КРАСНЫЙ) с (ЦВЕТ ЯБЛОКО ЗЕЛЕНЫЙ) не проходит:

Выделенный атом? обладает тем свойством, что он сопоставим с любым атомом. Это сильно расширяет полезные возможности функции MATCH:

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

Теперь посмотрим, как можно было бы реализовать функцию MATCH. Мы будем придерживаться стратегии движения вдоль образца и вдоль факта атом за атомом, проверяя, совпадают ли атом образца и атом факта в каждой позиции. Переводя на терминологию системы Лисп, мы строим функцию, которая проверяет первые элементы обоих списков и, если сравнение успешно, движется дальше, вызывая себя рекурсивно для работы над CDR от этих списков:

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

Мы также должны проверить, не короче ли один из списков другого — иначе функция MATCH собьется, если более короткий список сопоставляется с началом более длинного.

Рис. 14.1. В MATCH совершается рекурсия, пока текущий первый атом в образце является либо ? либо совпадает с текущим первым атомом в факте. При одновременном достижении конца образца и факта на нижнем уровне возвращается Т и передается наверх

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

В качестве окончательного результата мы получим Т, как показано на рис. 14.1. Но если мы обратимся к

то мы получим в результате NIL, как показано на риc. 14.2.

Теперь, чтобы сильно расширить возможности нашей функции сопоставления, мы включим в нее свойство, благодаря которому * будет сопоставимо с одним или более атомами. Вот пробная версия:

Переключаемое звездочкой предложение COND в этой версии обеспечивает рекурсивное обращение к MATCH. Срабатывает одна из грех возможностей: * ни с чем не сопоставима, в этом случае она выбрасывается и сопоставлению подвергается остальная часть образца; * сопоставима с одним атомом, в этом случае отбрасывается и ?*, и этот атом; ?* сопоставима с двумя или более атомами, в этом случае мы продолжаем действовать в рекурсивной манере, сохраняя * в образце, отбрасывая первые атомы, с которыми она сопоставима успешно.

Второй член в указанном предложении COND на самом деле излишен, если может сопоставляться с любым числом атомов, включая нулевое их число. От него можно избавиться, и функция MATCH будет все равно работать. В этом случае MATCH отделяет и сопоставляет оставшуюся часть Р с нетронутым списком D или же сохраняет * и передвигается на один атом в данных в предположении, что это один из атомов, сопоставимых со *. Вероятно, моделирование поможет прояснить работу рекурсии при этих обстоятельствах. См. рис. 14.3.

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

Рис. 14.3. Когда в образце встречается атом, он замещает произвольное число элементов. Функция MATCH отбрасывает либо *,либо первый элемент в факте на каждом уровне рекурсии. Попытка отбросить * делается перед приемом следующего элемента факта, который имеет место при сохранении *

Одновременные присваивания придают дополнительные возможности операциям сопоставления

Следующее направление усовершенствования лежит в обобщении функции MATCH таким образом, чтобы она присваивала определенные значения, когда сопоставление проходит успешно. Атомы, которые начинаются со знаков > или действуют как ? и * в процессе сопоставления, но в случае успеха их значениями становится то, с чем они сопоставимы. Переменные с > должны иметь в качестве значений атомы, тогда как переменные с * должны иметь в качестве значений списки сопоставляемых атомов. Обозначение >, использованное здесь, должно наводить на мысль о «заталкивании» значений в переменные с предлогом >. Разработчики языков сопоставления очень искусны в выборе синтаксиса.

Сопоставление с > и присваивание могут быть реализованы путем использования двух новых функций, ATOMCAR и ATOMCDR, и добавления предложения в COND, в котором АТОМСАР выделяет первый символ в атоме для его изучения. Обратите внимание на использование SET для присваивания значения переменной образца тому элементу в данных, с которым оно сопоставимо.

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

На самом деле, в большинстве систем Лиспа отсутствуют функции ATOMCAR и ATOMCDR, но часто имеется что-то вроде функций EXPLODE и IMPLODE * . Функция EXPLODE появляется в программе, чтобы разбить атом на список из составляющих его символов, каждый из которых появляется как отдельный атом:

Функция IMPLODE выполняет дополнительную к EXPLODE операцию, превращая список атомов в один атом:

Используя EXPLODE и IMPLODE, легко определить ATOMCAR и ATOMCDR:

* ( В реализации Лиспа на Фортране, например, эти функции называются соответственно UNPACK и PACKLIST (т. е. РАСПАКОВАТЬ и ЗАПАКО- ВАТЬ-СПИСОК).- Прим. перев.)


    Такой способ реализации одновременного присваивания неэффективен, потому что операции EXPLODE и IMPLODE выполняются слишком часто. Очевидно, было бы быстрее пользоваться менее изящным синтаксисом, когда атом >XYZ представляется как список (>XYZ). Тогда вместо

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

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

Рис. 14.4. Переменные, которым предшествует *, могут быть подставлены вместо произвольного числа фактов. Успешное сопоставление с образцом ведет к установке значения переменной со * равным соответствующим элементам факта

Этим начинается построение списка, когда * окончательно сопоставляется с последним атомом и в рекурсии больше не участвует.

Затем, по мере развития процесса на уровнях, где * была сохранена для сопоставления с атомами, расположенными дальше в списке, мы находим выражение (SET

Функция EVAL получает список атомов, просмотренных к настоящему моменту, используя (ATOMCDR (CAR Р)), функция CONS добавляет атом, успешно сопоставленный на текущем уровне, а функция SET делает этот расширенный список новым значением переменной, отмеченной И так продолжается до тех пор, пока все атомы в списке не будут сопоставлены.

Посмотрите внимательно на следующий пример.

Рис. 14.4 показывает, что *L должна быть сопоставима с X и Y, при этом L присваивается значение (X Y).

Ограничения на то, чему может быть сопоставлена переменная образца

Другое усовершенствование может быть сделано, если мы не хотим указывать на конкретный атом в определенном положении или допустить какой-либо атом вообще. Вместо этого нам нужен член некоторого класса атомов, например чисел или атомов определенной длины или атомов со специальным свойством в списке свойств. С этой целью мы введем свойство ограничения. Чтобы им воспользоваться, необходимо подставить некоторый описательный список в образец, где прежде ожидались только атомы. Этот список имеет следующую форму:

Идея состоит в том, что соответствующая позиция в действительности должна быть занята атомом, который удовлетворяет всем предикатам, перечисленным в этом ограничении. Так мы могли бы определить предикат, который имеет значение Т только для атомов из четырех букв 4LETTERP:

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

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

V теперь имеет значение БЛОК.

Ограничения для ? могут быть реализованы следующим образом:

После того как проделаны соответствующие тесты по проверке пакета ограничений, атом из факта подается на предикаты в ограничении посредством функции MAPCAR. Затем AND проверяет, все ли предикаты возвращают значения Т, и если так, то весь тест в функции COND успешен, и на этом элементе осуществляется рекурсия. Конечно, подобное свойство может быть добавлено и для переменных со звездочкой.

Ниже идет определение для функции MATCH, которое включает все, кроме ограниченных * переменных, опущенных лишь потому, чтобы сделать программу более компактной:

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

Глава 10 сопоставление с образцом

тБУУНПФТЙН УМЕДХАЭХА РТПУФХА ЪБДБЮХ. чЩ ИПФЙФЕ ЪБДБФШ ЖХОЛГЙА, ЛПФПТБС ПРТЕДЕМСЕФ ДМС МАВПК ЪБДБООПК УФТПЛЙ УЙНЧПМПЧ, СЧМСЕФУС МЙ ПОБ РБМЙОДТПНПН. рБМЙОДТПН — ЬФП УФТПЛБ, ПДЙОБЛПЧП ЮЙФБЕНБС ЛБЛ УМЕЧБ ОБРТБЧП, ФБЛ Й УРТБЧБ ОБМЕЧП. йНЕАФУС ДЧБ ПЮЕЧЙДОЩИ УРПУПВБ ХФПЮОЙФШ ФБЛПЕ ПРТЕДЕМЕОЙЕ РБМЙОДТПНБ. рЕТЧЩК — ЬФП ПРТЕДЕМЙФШ РТПГЕДХТХ ТЕЧЕТУЙТПЧБОЙС УФТПЛЙ (ЪБРЙУЙ РПУЙНЧПМШОП ЪБДПН ОБРЕТЕД), Б ЪБФЕН УТБЧОЙЧБФШ ТЕЧЕТУЙТПЧБООХА УФТПЛХ У ЙУИПДОПК. пЮЕЧЙДОП, БМЗПТЙФН, УПЪДБЧБЕНЩК ОБ ПУОПЧЕ ФБЛПЗП ХФПЮОЕОЙС, ВХДЕФ ОЕ УБНЩН ЬЖЖЕЛФЙЧОЩН . еУМЙ УФТПЛБ ПЛБОЮЙЧБЕФУС УЙНЧПМПН, ПФМЙЮОЩН ПФ ОБЮБМШОПЗП, ФП ПОБ ОЕ СЧМСЕФУС РБМЙОДТПНПН, Б ЬФП НПЦЕФ ВЩФШ ХУФБОПЧМЕОП ВЕЪ ТЕЧЕТУЙТПЧБОЙС ЧУЕК УФТПЛЙ. рПЬФПНХ НЩ РТЙНЕН ЪБ ПУОПЧХ ДТХЗПЕ ХФПЮОЕОЙЕ, ЛПФПТПЕ НПЦОП ЪБРЙУБФШ Ч ПВЩЮОПК НБФЕНБФЙЮЕУЛПК ЖПТНЕ:

1) рХУФБС УФТПЛБ СЧМСЕФУС РБМЙОДТПНПН.

2) уФТПЛБ ЙЪ ПДОПЗП УЙНЧПМБ СЧМСЕФУС РБМЙОДТПНПН.

3) еУМЙ УФТПЛБ ОБЮЙОБЕФУС Й ПЛБОЮЙЧБЕФУС ПДОЙН Й ФЕН ЦЕ УЙНЧПМПН, ФП ПОБ СЧМСЕФУС РБМЙОДТПНПН ФПЗДБ Й ФПМШЛП ФПЗДБ, ЛПЗДБ УФТПЛБ, РПМХЮЕООБС ЙЪ ОЕЕ РХФЕН ХДБМЕОЙС ОБЮБМШОПЗП Й ЛПОЕЮОПЗП УЙНЧПМПЧ, СЧМСЕФУС РБМЙОДТПНПН.

4) еУМЙ ОЕ ЧЩРПМОЕОП ОЙ ПДОП ЙЪ ЧЩЫЕРТЙЧЕДЕООЩИ ХУМПЧЙК, УФТПЛБ РБМЙОДТПНПН ОЕ СЧМСЕФУС.

рХУФШ Pal — ЙНС ЖХОЛГЙЙ, ЛПФПТХА НЩ ИПФЙН ПРТЕДЕМЙФШ, Й РХУФШ ПОБ РТЙОЙНБЕФ ЪОБЮЕОЙЕ True Ч УМХЮБЕ, ЛПЗДБ ЕЕ БТЗХНЕОФ — РБМЙОДТПН, Й False Ч РТПФЙЧОПН УМХЮБЕ. пРТЕДЕМЕОЙЕ Ч тежбмЕ РПЮФЙ ВХЛЧБМШОП УМЕДХЕФ НБФЕНБФЙЮЕУЛПНХ ПРТЕДЕМЕОЙА:

ьФБ РТПЗТБННБ ОБЮЙОБЕФУС У ЙНЕОЙ ЖХОЛГЙЙ, ЪБ ЛПФПТЩН УМЕДХЕФ ВМПЛ , ЪБЛМАЮЕООЩК Ч ЖЙЗХТОЩЕ УЛПВЛЙ. вМПЛ — ЬФП УРЙУПЛ РТЕДМПЦЕОЙК, ТБЪДЕМСЕНЩИ ФПЮЛПК У ЪБРСФПК. ч ОБЫЕН УМХЮБЕ ЙНЕЕН ЮЕФЩТЕ РТЕДМПЦЕОЙС, ЛБЦДПЕ ЙЪ ЛПФПТЩИ УППФЧЕФУФЧХЕФ ПДОПНХ РХОЛФХ Ч РТЙЧЕДЕООПН ЧЩЫЕ НБФЕНБФЙЮЕУЛПН ПРЙУБОЙЙ РБМЙОДТПНБ. рТЕДМПЦЕОЙЕ РТЕДУФБЧМСЕФ УПВПК РТБЧЙМП ЪБНЕОЩ. еЗП МЕЧБС ЮБУФШ РТЕДУФБЧМСЕФ ПВТБЪЕГ БТЗХНЕОФБ ЖХОЛГЙЙ, РТБЧБС ЦЕ ЮБУФШ РПУМЕ ЪОБЛБ ТБЧЕОУФЧБ СЧМСЕФУС ЪБНЕОПК ДМС ЧЩЪПЧБ ЖХОЛГЙЙ.

ч РЕТЧПН РТЕДМПЦЕОЙЙ БТЗХНЕОФ ЖХОЛГЙЙ Pal — РХУФБС УФТПЛБ, РПЬФПНХ ЪОБЮЕОЙЕН ЖХОЛГЙЙ ДПМЦОП ВЩФШ True .

чП ЧФПТПН РТЕДМПЦЕОЙЙ БТЗХНЕОФ ЪБДБО ЛБЛ УЧПВПДОБС РЕТЕНЕООБС УЙНЧПМБ s.1 . ьФПНХ ПВТБЪГХ ВХДЕФ ХДПЧМЕФЧПТСФШ МАВПК УЙНЧПМ, ОБРТЙНЕТ, ВХЛЧБ, ОП ФПМШЛП ПДЙО УЙНЧПМ. фБЛЙН ПВТБЪПН, РТЕДМПЦЕОЙЕ ЮЙФБЕФУС: ЕУМЙ БТЗХНЕОФ — ЕДЙОУФЧЕООЩК УЙНЧПМ, ЪБНЕОЙФШ ЧЩЪПЧ ОБ True .

фТЕФШЕ РТЕДМПЦЕОЙЕ РТЕДУФБЧМСЕФ УМХЮБК, ЛПЗДБ БТЗХНЕОФ ОБЮЙОБЕФУС Й ПЛБОЮЙЧБЕФУС ПДОЙН Й ФЕН ЦЕ УЙНЧПМПН s.1 , Й УПДЕТЦЙФ МАВПЕ ЧЩТБЦЕОЙЕ e.2 НЕЦДХ ОЙНЙ. чЩТБЦЕОЙЕ СЧМСЕФУС УБНПК ПВЭЕК УФТХЛФХТПК ДБООЩИ Ч тежбмЕ; Ч ЮБУФОПУФЙ, ПОП НПЦЕФ ВЩФШ УФТПЛПК УЙНЧПМПЧ. рТБЧБС ЮБУФШ ЬФПЗП РТЕДМПЦЕОЙС ЕУФШ ЧЩЪПЧ ЖХОЛГЙЙ Pal ПФ БТЗХНЕОФБ e.2 . вХДЕН ЙУРПМШЪПЧБФШ ЛТХЗМЩЕ УЛПВЛЙ ДМС ЖПТНЙТХЕНЩИ УФТХЛФХТ ДБООЩИ, Б ХЗМПЧЩЕ — ДМС ПВПЪОБЮЕОЙС ЧЩЪПЧБ ЖХОЛГЙЙ. ъБРЙУЩЧБЕН

Ч УМХЮБЕ, ЛПФПТЩК УППФЧЕФУФЧХЕФ НБФЕНБФЙЮЕУЛПНХ ПВПЪОБЮЕОЙА pal(e2) .

оБЛПОЕГ, БТЗХНЕОФПН Ч РПУМЕДОЕН РТЕДМПЦЕОЙЙ СЧМСЕФУС РТПЙЪЧПМШОПЕ ЧЩТБЦЕОЙЕ (УФТПЛБ). лБЦДПЕ РТЕДМПЦЕОЙЕ Ч ПРТЕДЕМЕОЙЙ ЖХОЛГЙЙ Ч тежбмЕ РТЙНЕОСЕФУС ФПМШЛП ФПЗДБ, ЛПЗДБ ОЙ ПДОП ЙЪ РТЕДЫЕУФЧХАЭЙИ РТЕДМПЦЕОЙК ОЕ ВЩМП РТЙНЕОЙНП. фБЛЙН ПВТБЪПН, РПУМЕДОЕЕ РТЕДМПЦЕОЙЕ ПЪОБЮБЕФ: ЕУМЙ ОЙ ПДЙО ЙЪ ЧЩЫЕТБУУНПФТЕООЩИ УМХЮБЕЧ ОЕ ЙНЕМ НЕУФБ, ФПЗДБ РТЙ МАВПН БТЗХНЕОФЕ ЪОБЮЕОЙЕН ЧЩЪПЧБ ЖХОЛГЙЙ СЧМСЕФУС False .

фПЮОПЕ ЪБДБОЙЕ БМЗПТЙФНЙЮЕУЛПК УЕНБОФЙЛЙ тежбм-РТПЗТБНН ДБЕФУС ЮЕТЕЪ ПРТЕДЕМЕОЙЕ БВУФТБЛФОПК тежбм-НБЫЙОЩ (УН. тБЪД. 1.5) , ЛПФПТБС ЧЩРПМОСЕФ тежбм-РТПЗТБННЩ, Ф.Е. ЧЩЮЙУМСЕФ ЖХОЛГЙЙ, ПРТЕДЕМСЕНЩЕ Ч тежбмЕ. тежбм-НБЫЙОБ ТБВПФБЕФ РПЫБЗПЧП, РТЙЮЕН ЛБЦДЩК ЫБЗ УПУФПЙФ Ч ЧЩРПМОЕОЙЙ ПДОПЗП РТЕДМПЦЕОЙС. еУМЙ, ОБРТЙНЕТ, НЩ ДБЕН тежбм-НБЫЙОЕ ЧЩЪПЧ Pal У БТЗХНЕОФПН 'revolver' , Ф.Е.

, ФП ТБВПЮЕЕ РТПУФТБОУФЧП тежбм-НБЫЙОЩ (ЛПФПТПЕ НЩ ВХДЕН ОБЪЩЧБФШ РПМЕН ЪТЕОЙС ) РТПИПДЙФ ЮЕТЕЪ УМЕДХАЭЙЕ УФБДЙЙ:

ьФП ДЕНПОУФТЙТХЕФ ДЕФБМШОХА ЛБТФЙОХ РТПГЕУУБ ЧЩЮЙУМЕОЙС. рТПЗТБННЙУФ НПЦЕФ ХРТБЧМСФШ ЬФЙН РТПГЕУУПН У РПНПЭША ФТБУУЙТПЧЭЙЛБ. ч РТПУФЕКЫЕН УМХЮБЕ ПО НПЦЕФ РТПУНБФТЙЧБФШ Й ЧЩДБЧБФШ ОБ РЕЮБФШ ЧУЕ РПУМЕДПЧБФЕМШОЩЕ УФБДЙЙ РТПГЕУУБ, ЛБЛ ЬФП ВЩМП ПРЙУБОП ЧЩЫЕ.

фЕРЕТШ ОБЮОЕН УЙУФЕНБФЙЮЕУЛПЕ ПРТЕДЕМЕОЙЕ тежбмБ. лТБФЛПЕ ПРЙУБОЙЕ УЙОФБЛУЙУБ СЪЩЛБ РТЙЧЕДЕОП ФБЛЦЕ Ч Reference Section B.

уЙНЧПМ Ч тежбмЕ — ЬФП НЙОЙНБМШОЩК УЙОФБЛУЙЮЕУЛЙК ЬМЕНЕОФ УФТХЛФХТ ДБООЩИ. йУРПМШЪХАФУС УМЕДХАЭЙЕ ЧЙДЩ УЙНЧПМПЧ:

  • УЙНЧПМЩ-ЙНЕОБ, ОБЪЩЧБЕНЩЕ ФБЛЦЕ ЙДЕОФЙЖЙЛБФПТБНЙ;
  • ЪОБЛЙ ЛМБЧЙБФХТЩ;
  • ОЕПФТЙГБФЕМШОЩЕ ГЕМЩЕ ЮЙУМБ (НБЛТПГЙЖТЩ);
  • ДЕКУФЧЙФЕМШОЩЕ ЮЙУМБ.


йДЕОФЙЖЙЛБФПТПН СЧМСЕФУС РПУМЕДПЧБФЕМШОПУФШ ЪОБЛПЧ, ЛПФПТБС ОБЮЙОБЕФУС У ЪБЗМБЧОПК ВХЛЧЩ Й НПЦЕФ ЧЛМАЮБФШ ВХЛЧЩ, ГЙЖТЩ, ЮЕТФПЮЛЙ — Й РПДЮЕТЛЙЧБОЙС _. тБЪНЕТ ВХЛЧ, ЪБ ЙУЛМАЮЕОЙЕН РЕТЧПК, ОЕ ЙЗТБЕФ ТПМЙ; ФБЛ, SUM1 Й Sum1 РТЕДУФБЧМСАФ ПДЙО Й ФПФ ЦЕ ЙДЕОФЙЖЙЛБФПТ. юЕТФПЮЛЙ Й РПДЮЕТЛЙЧБОЙС ФБЛЦЕ ЧЪБЙНПЪБНЕОСЕНЩ: Sum-1 Й Sum_1 ПЪОБЮБАФ ПДОП Й ФП ЦЕ. йДЕОФЙЖЙЛБФПТЩ ОЕ ДПМЦОЩ ТБЪДЕМСФШУС РТПВЕМБНЙ Й ЪОБЛБНЙ РЕТЕОПУБ. пВЭБС ДМЙОБ ЙДЕОФЙЖЙЛБФПТБ ОЕ ДПМЦОБ РТЕЧЩЫБФШ 15 ЪОБЛПЧ.

рТБЧЙМШОЩНЙ ЙДЕОФЙЖЙЛБФПТБНЙ СЧМСАФУС:

оЕ СЧМСАФУС РТБЧЙМШОЩНЙ ЙДЕОФЙЖЙЛБФПТБНЙ:

чУЕ РЕЮБФОЩЕ ЪОБЛЙ ЛПНРШАФЕТОПК УЙУФЕНЩ НПЗХФ ЙУРПМШЪПЧБФШУС Ч ЛБЮЕУФЧЕ УЙНЧПМПЧ. юФПВЩ ПФМЙЮБФШ ЪОБЛЙ ПФ УЙНЧПМПЧ-ЙНЕО, НЩ ВХДЕН ЪБЛМАЮБФШ РЕТЧЩЕ Ч ЛБЧЩЮЛЙ. дМС ЧЩДЕМЕОЙС УФТПЛЙ ЪОБЛПЧЩИ УЙНЧПМПЧ ВХДЕН ЪБЛМАЮБФШ Ч ЛБЧЩЮЛЙ ЧУА УФТПЛХ. нПЗХФ ЙУРПМШЪПЧБФШУС ЛБЛ ПДЙОБТОЩЕ ' , ФБЛ Й ДЧПКОЩЕ " ЛБЧЩЮЛЙ, ОП ПФЛТЩЧБАЭБС Й ЪБЛТЩЧБАЭБС ЛБЧЩЮЛЙ ДПМЦОЩ ВЩФШ ПДОПЗП ФЙРБ. фБЛЙН ПВТБЪПН, 'A' ЕУФШ ПДЙО УЙНЧПМ, Ч ФП ЧТЕНС ЛБЛ 'A+B' ЕУФШ УФТПЛБ (РПУМЕДПЧБФЕМШОПУФШ) ФТЕИ УЙНЧПМПЧ: ЪОБЛПЧ 'A' , '+' Й 'B' .

дМС РТЕДУФБЧМЕОЙС УБНЙИ ЛБЧЩЮЕЛ НЩ ДХВМЙТХЕН ЙИ, ОЕЪБЧЙУЙНП ПФ ФПЗП, ЙЪПМЙТПЧБОЩ ПОЙ ЙМЙ ОБИПДСФУС ЧОХФТЙ УФТПЛЙ, ПЗТБОЙЮЙЧБЕНПК ФПЗП ЦЕ ЧЙДБ ЛБЧЩЮЛБНЙ. фБЛ '*,''' СЧМСЕФУС УФТПЛПК ЙЪ ФТЕИ УЙНЧПМПЧ: ЪЧЕЪДПЮЛЙ, ЪБРСФПК Й ПДЙОБТОПК ЛБЧЩЮЛЙ. ьФП НПЦЕФ ВЩФШ ФБЛЦЕ ЪБРЙУБОП ЛБЛ "*,'" .

пДОПУЙНЧПМШОЩЕ ЙДЕОФЙЖЙЛБФПТЩ ОЕ УМЕДХЕФ РХФБФШ У БМЖБЧЙФОЩНЙ УЙНЧПМБНЙ: A ПФМЙЮБЕФУС ПФ'A' . бМЖБЧЙФОЩЕ УЙНЧПМЩ ТБЪОЩИ ТЕЗЙУФТПЧ ФБЛЦЕ ТБЪМЙЮБАФУС: 'A' ПФМЙЮОП ПФ 'a' .

нБЛТПГЙЖТБНЙ Ч ОБЫЕК ТЕБМЙЪБГЙЙ тежбмБ-5 СЧМСАФУС РПМПЦЙФЕМШОЩЕ ГЕМЩЕ ЮЙУМБ Ч ДЙБРБЪПОЕ ПФ 0 ДП 2 32 -1. рТЕЧПУИПДСЭЙЕ 2 32 -1 ЮЙУМБ НПЗХФ ВЩФШ УПУФБЧМЕОЩ ЙЪ НБЛТПГЙЖТ У ЙУРПМШЪПЧБОЙН ПУОПЧБОЙС 2 32 , ФБЛ ЦЕ ЛБЛ ДЕУСФЙЮОЩЕ ГЕМЩЕ ЮЙУМБ УПУФБЧМСАФУС ЙЪ ПВЩЮОЩИ (ДЕУСФЙЮОЩИ) ГЙЖТ; ЬФЙН Й ПВЯСУОСЕФУС ЙНС «НБЛТПГЙЖТБ». дМС РТЕДУФБЧМЕОЙС ПФТЙГБФЕМШОЩИ ГЕМЩИ ЮЙУЕМ НЩ РПНЕЭБЕН '-' РЕТЕД ГЙЖТБНЙ, ФБЛ ЦЕ ЛБЛ ДЕМБЕФУС РТЙ ЙУРПМШЪПЧБОЙЙ ДЕУСФЙЮОЩИ ГЙЖТ. рПДПВОП ВХЛЧБН БМЖБЧЙФБ, ЛПФПТЩЕ ПФМЙЮБАФУС ПФ ВХЛЧ-ЙДЕОФЙЖЙЛБФПТПЧ, ГЙЖТЩ ПФМЙЮБАФУС ПФ ЮЙУМПЧЩИ УЙНЧПМПЧ. '1' — ЬФП ОЕ ФП ЦЕ УБНПЕ, ЮФП 1 . ч ПФМЙЮЙЕ ПФ РЕТЧПК ЕДЙОЙГЩ — ПВЩЮОПК ДЕУСФЙЮОПК ГЙЖТЩ — ЧФПТБС ЕДЙОЙГБ ТБУУНБФТЙЧБЕФУС ЛБЛ НБЛТПГЙЖТБ.

рТЙНЕТЩ: 3306 СЧМСЕФУС УЙНЧПМПН — НБЛТПГЙЖТПК У ЮЙУМЕООЩН ЪОБЮЕОЙЕН 3306 . '-'25 СЧМСЕФУС РПУМЕДПЧБФЕМШОПУФША ДЧХИ УЙНЧПМПЧ; ЪБ БМЖБЧЙФОЩН УЙНЧПМПН '-' УМЕДХЕФ НБЛТПГЙЖТБ 25 . чНЕУФЕ ПОЙ ВХДХФ ЧПУРТЙОЙНБФШУС БТЙЖНЕФЙЮЕУЛЙНЙ ЖХОЛГЙСНЙ ЛБЛ ЮЙУМП -25. (ч РТПЗТБННБИ ЧУЕ ЪОБЛЙ ДПМЦОЩ ЪБЛМАЮБФШУС Ч ЛБЧЩЮЛЙ; РТЙ УЮЙФЩЧБОЙЙ ДБООЩИ ЖХОЛГЙЕК Input [УН. тБЪД.2.3] ЛБЧЩЮЛЙ ОЕ СЧМСАФУС ПВСЪБФЕМШОЩНЙ.) ч УМЕДХАЭЕН РТЙНЕТЕ:

СЧМСЕФУС РПУМЕДПЧБФЕМШОПУФША ФТЕИ НБЛТПГЙЖТ, ЛПФПТБС ВХДЕФ РПОЙНБФШУС ЛБЛ

2543*2 64 + 88918*2 32 + 9

ъбнеюбойе: еУМЙ ЧЩ ЪБРЙУЩЧБЕФЕ ОЕЮФП ЧТПДЕ '--'25 , ЬФП ОЕ ВХДЕФ УЮЙФБФШУС УЙОФБЛУЙЮЕУЛПК ПЫЙВЛПК. ьФП ЧРПМОЕ ДПРХУФЙНБС УФТПЛБ ЙЪ ФТЕИ УЙНЧПМПЧ. пЫЙВПЮОПК ПОБ УФБОЕФ ФПМШЛП ФПЗДБ, ЛПЗДБ ЧЩ РПРЩФБЕФЕУШ ЙУРПМШЪПЧБФШ ФБЛХА УФТПЛХ Ч ЛБЮЕУФЧЕ ПРЕТБОДБ Ч БТЙЖНЕФЙЮЕУЛПК ЖХОЛГЙЙ.

дЕКУФЧЙФЕМШОПЕ ЮЙУМП Ч СЪЩЛЕ тежбм-5 ЧУЕЗДБ РТЕДУФБЧМЕОП УЙНЧПМПН, ЪБОЙНБАЭЙН ПДОП НБЫЙООПЕ УМПЧП. дЕКУФЧЙФЕМШОПЕ ЮЙУМП НПЦЕФ ВЩФШ РПМПЦЙФЕМШОЩН, ПФТЙГБФЕМШОЩН ЙМЙ ОХМЕН. ч РТПЗТБННЕ ДЕКУФЧЙФЕМШОЩЕ ЮЙУМБ ЪБРЙУЩЧБАФУС Ч ПВЩЮОПН ЧЙДЕ У ФПЮЛПК, ПФДЕМСАЭЕК ДТПВОХА ЮБУФШ ПФ ГЕМПК, Й У ЪОБЛПН E, ПФДЕМСАЭЙН ДЕУСФЙЮОЩК РПТСДПЛ. рТЙНЕТЩ:

(УН. Ч Reference Section B ВПМЕЕ РПДТПВОЩК УЙОФБЛУЙУ). уЙНЧПМЩ, РТЕДУФБЧМСАЫЙЕ ДЕКУФЧЙФЕМШОЩЕ ЮЙУМБ, ПФМЙЮБАФУС ПФ НБЛТПГЙЖТ: 215 — ОЕ ФП ЦЕ УБНПЕ, ЮФП 215.0 .

чППВЭЕ ЗПЧПТС, РТПВЕМЩ ОЕ УЮЙФБАФУС УЙНЧПМБНЙ; РТПВЕМЩ Й УЙНЧПМЩ РЕТЕОПУБ ЙУРПМШЪХАФУС ДМС ТБЪДЕМЕОЙС МЕЛУЙЮЕУЛЙИ ЕДЙОЙГ тежбмБ ЧУАДХ, ЗДЕ ЬФП ОЕПВИПДЙНП, Й ДМС ВПМЕЕ ХДПВОПЗП ТБЪНЕЭЕОЙС ЙИ ОБ УФТБОЙГЕ. еДЙОУФЧЕООПК УЙФХБГЙЕК, ЛПЗДБ РТПВЕМ УФБОПЧЙФУС УЙНЧПМПН, СЧМСЕФУС УМХЮБК ЕЗП ЙУРПМШЪПЧБОЙС ЧОХФТЙ ЛБЧЩЮЕЛ. еУМЙ '' — ЬФП УЙНЧПМ ЛБЧЩЮЕЛ, ФП ' ' — ЬФП УЙНЧПМ РТПВЕМБ. рТЙ ЙУРПМШЪПЧБОЙЙ НЕЦДХ УФТПЛБНЙ, ЪБЛМАЮЕООЩНЙ Ч ЛБЧЩЮЛЙ, РТПВЕМ ЗПЧПТЙФ П ФПН, ЮФП УОСФШ ЛБЧЩЮЛЙ НПЦОП ФПМШЛП У ЛБЦДПК ЙЪ ОЙИ РП ПФДЕМШОПУФЙ. фБЛ, 'a' 'b' СЧМСЕФУС УФТПЛПК ЙЪ ДЧХИ УЙНЧПМПЧ, a Й b , Ч ФП ЧТЕНС ЛБЛ 'a''b' — ЬФП УФТПЛБ ЙЪ ФТЕИ УЙНЧПМПЧ: a , ЛБЧЩЮЛЙ Й b .

дМС УПЪДБОЙС УФТХЛФХТ ДБООЩИ Ч тежбмЕ ЙУРПМШЪХАФУС УЛПВЛЙ. оЕ ЪБЛМАЮБЕНЩЕ Ч ЛБЧЩЮЛЙ ЛТХЗМЩЕ УЛПВЛЙ — ЬФП ОЕ УЙНЧПМЩ, ОП УРЕГЙБМШОЩЕ ЪОБЛЙ тежбмБ. нЩ ФБЛЦЕ ОБЪЩЧБЕН ЙИ УФТХЛФХТОЩЕ УЛПВЛЙ Ч ПФМЙЮЙЕ ПФ ХЗМПЧЩИ ЧЩЮЙУМЙФЕМШОЩИ УЛПВПЛ. уФТХЛФХТОЩЕ УЛПВЛЙ УМЕДХЕФ ПВЯЕДЙОСФШ Ч РБТЩ УПЗМБУОП ПВЭЕРТЙОСФЩН РТПУФЩН РТБЧЙМБН. вХДЕН ОБЪЩЧБФШ РТПЙЪЧПМШОХА РПУМЕДПЧБФЕМШОПУФШ УЙНЧПМПЧ, ЧЛМАЮБАЭХА Й РТБЧЙМШОП ТБУУФБЧМЕООЩe УЛПВЛЙ, ПВЯЕЛФОЩН ЧЩТБЦЕОЙЕН. вПМЕЕ ФПЮОП, ПВЯЕЛФОПЕ ЧЩТБЦЕОЙЕ — ЬФП РПУМЕДПЧБФЕМШОПУФШ ЛПОЕЮОПЗП ЮЙУМБ ФЕТНПЧ, ЗДЕ ЛБЦДЩК ФЕТН СЧМСЕФУС МЙВП ПДОЙН УЙНЧПМПН, МЙВП ЧЩТБЦЕОЙЕН, ЪБЛМАЮЕООЩН Ч УЛПВЛЙ. лПМЙЮЕУФЧП ФЕТНПЧ Ч ЧЩТБЦЕОЙЙ НПЦЕФ ВЩФШ Й ОХМЕН, ФБЛ ЮФП РХУФПЕ ПВЯЕЛФОПЕ ЧЩТБЦЕОЙЕ (ВХЛЧБМШОП ОЙЮЕЗП ОЕ УПДЕТЦБЭЕЕ) СЧМСЕФУС ДПРХУФЙНЩН. чПФ ОЕЛПФПТЩЕ РТЙНЕТЩ ЧЩТБЦЕОЙК:

рТЙНЕТЩ РПУМЕДПЧБФЕМШОПУФЕК, ОЕ СЧМСАЭЙИУС (ПВЯЕЛФОЩНЙ) ЧЩТБЦЕОЙСНЙ:

ъбнеюбойе: ъБЛМАЮЕОЙЕ Ч ЛБЧЩЮЛЙ ЛБЦДПЗП ЪОБЛБ, ЛБЛ Ч ПДОПН ЙЪ ТБУУНБФТЙЧБЕНЩИ ЧЩЫЕ РТЙНЕТПЧ:

НПЦЕФ РТЕДУФБЧМСФШ ОЕХДПВУФЧП. уМЕДХЕФ, ПДОБЛП, ЙНЕФШ Ч ЧЙДХ, ЮФП РПДПВОПЕ ЪБЛМАЮЕОЙЕ ОЕПВИПДЙНП ФПМШЛП Ч ФЕЛУФЕ тежбм-РТПЗТБННЩ, ЗДЕ РПСЧМЕОЙЕ ВПМШЫЙИ ЧЩТБЦЕОЙК ФБЛПЗП ТПДБ НБМПЧЕТПСФОП. фБЛПЕ ЧЩТБЦЕОЙЕ ФЙРЙЮОП ДМС ДБООЩИ. лПЗДБ ПОП ОБВЙТБЕФУС МЙВП ЮЙФБЕФУС ЙЪ ЖБКМБ ЛБЛ ДБООЩЕ, РТЙ ЙУРПМШЪПЧБОЙЙ УРЕГЙБМШОПК ЖХОЛГЙЙ Input , ЛБЧЩЮЛБНЙ ПЛТХЦБАФУС ФПМШЛП УЛПВПЮОЩЕ УЙНЧПМЩ ДМС ФПЗП, ЮФПВЩ ПФМЙЮБФШ ЙИ ПФ УФТХЛФХТОЩИ УЛПВПЛ. нЩ НПЗМЙ ВЩ, ФБЛЙН ПВТБЪПН, ОБВТБФШ:

ч БМЗЕВТЕ НЩ ЙУРПМШЪХЕН ЧЩТБЦЕОЙС ДМС РТЕДУФБЧМЕОЙС ОЕЛПФПТПК РПУМЕДПЧБФЕМШОПУФЙ ПРЕТБГЙК ОБД ЮЙУМБНЙ Й РЕТЕНЕООЩНЙ; УЛПВЛЙ Ч ЧЩТБЦЕОЙЙ ПФНЕЮБАФ РПТСДПЛ ЧЩРПМОЕОЙС ПРЕТБГЙК. еУМЙ ЧЩТБЦЕОЙЕ, РТЙЧЕДЕООПЕ ЧЩЫЕ, РПОЙНБФШ ЛБЛ БМЗЕВТБЙЮЕУЛПЕ, ФП ПОП НПЦЕФ ВЩФШ РТЕДУФБЧМЕОП Ч ЧЙДЕ ДЕТЕЧБ, РПЛБЪБООПЗП ОБ тЙУ. 1.1.

тЙУ. 1.1 дЕТЕЧП ДМС БМЗЕВТБЙЮЕУЛПЗП ЧЩТБЦЕОЙС

уМЕДХЕФ РПДЮЕТЛОХФШ, ЮФП ЛПОГЕРГЙС ЧЩТБЦЕОЙС Ч тежбмЕ СЧМСЕФУС ВПМЕЕ ПВЭЕК. нЩ ОЕ РТЕДРПМБЗБЕН ОЙЛБЛПК УРЕГЙБМШОПК ЙОФЕТРТЕФБГЙЙ ЧЩТБЦЕОЙК; ПОЙ НПЗХФ ВЩФШ ЙУРПМШЪПЧБОЩ ТБЪМЙЮОЩН ПВТБЪПН. тежбм-ЧЩТБЦЕОЙЕ РТПУФП СЧМСЕФУС УФТХЛФХТЙТПЧБООЩН ПВЯЕЛФПН, ЛПФПТЩК УЛПОУФТХЙТПЧБО ОЕЛПФПТЩН УРПУПВПН ЙЪ УЙНЧПМПЧ Й УФТХЛФХТОЩИ УЛПВПЛ. дМС ЛБЦДПК УФТХЛФХТОПК УЛПВЛЙ Ч ОЕН ЙНЕЕФУС Ч ФПЮОПУФЙ ПДОБ РБТОБС УЛПВЛБ РТПФЙЧПРПМПЦОПЗП ЧЙДБ. чНЕУФЕ ПОЙ ПВТБЪХАФ ОЕЮФП ЧТПДЕ ЛПТПВЛЙ ЙМЙ ЛБТНБОБ. пОЙ ЧЩДЕМСАФ ФБЛХА РПДУЙУФЕНХ ЧП ЧЛМАЮБАЭЕК УЙУФЕНЕ, ЛПФПТБС СЧМСЕФУС ЮБУФША ГЕМПЗП, ОП Ч ФП ЦЕ ЧТЕНС УПИТБОСЕФ Й УПВУФЧЕООХА ГЕМПУФОПУФШ. еУМЙ ЧЩ ЧЩДЕМСЕФЕ ПДОХ ЗТБОЙГХ Ч ФБЛПК РПДУФТХЛФХТЕ, ФП ЧФПТБС ЗТБОЙГБ ПРТЕДЕМСЕФУС ЕДЙОУФЧЕООЩН ПВТБЪПН. пФОПЫЕОЙЕ НЕЦДХ УЙУФЕНПК Й ЕЕ РПДУЙУФЕНБНЙ СЧМСЕФУС ПЮЕОШ ЧБЦОЩН БУРЕЛФПН ПЛТХЦБАЭЕЗП НЙТБ. лПЗДБ НЩ УПЪДБЕН УЙНЧПМШОЩЕ НПДЕМЙ НЙТБ, УФТХЛФХТОЩЕ УЛПВЛЙ НПДЕМЙТХАФ ФБЛПЕ ПФОПЫЕОЙЕ. еУМЙ ЖПТФЕРЙБОП (Piano), УЛТЙРЛБ (Violin) Й БМШФ (Viola) ОБИПДСФУС Ч ЛЧБТФЙТЕ ьОО, Б ЧЙПМПОЮЕМШ (Cello) Й ЛПОФТБВБУ (Bass) — Ч ЛЧБТФЙТЕ вПВБ, ФП ЬФБ УЙФХБГЙС НПЦЕФ ВЩФШ РТПНПДЕМЙТПЧБОБ тежбм-ЧЩТБЦЕОЙЕН:

тежбм-ЧЩТБЦЕОЙЕ НПЦЕФ ВЩФШ РТЕДУФБЧМЕОП ДЕТЕЧПН ФБЛ ЦЕ, ЛБЛ Й БМЗЕВТБЙЮЕУЛПЕ ЧЩТБЦЕОЙЕ. пДОБЛП, ЕУМЙ НЩ РПОЙНБЕН ЧЩТБЦЕОЙЕ ЙНЕООП ЛБЛ тежбм-ЧЩТБЦЕОЙЕ, ВЕЪ ЛБЛПК-МЙВП ЙОФЕТРТЕФБГЙЙ, ДЕТЕЧП ДПМЦОП ЛПЕ-ЮЕН ПФМЙЮБФШУС. оБ тЙУ. 1.1 НЩ ТБУРПМБЗБМЙ ПРЕТБГЙЙ ЧЩЫЕ ЙИ БТЗХНЕОФПЧ. оП ЕУМЙ НЩ ОЕ ЙОФЕТРТЕФЙТХЕН ЧЩТБЦЕОЙЕ ЛБЛ БМЗЕВТБЙЮЕУЛПЕ, ФП A + B СЧМСЕФУС РТПУФП ЛПОЛБФЕОБГЙЕК ФТЕИ УЙНЧПМПЧ, Й ЧУЕ ПОЙ ДПМЦОЩ ТБУРПМБЗБФШУС ОБ ПДОПН Й ФПН ЦЕ ХТПЧОЕ. дЕТЕЧП ДПМЦОП ЧЩЗМСДЕФШ, ЛБЛ ЬФП РПЛБЪБОП ОБ тЙУ. 1.2. мЙУФШСНЙ (ЛПОЕЮОЩНЙ ХЪМБНЙ) ДЕТЕЧБ СЧМСАФУС УЙНЧПМЩ; ЧУЕ ДТХЗЙЕ ХЪМЩ — ЬФП ЪБЛМАЮЕООЩЕ Ч УЛПВЛЙ РПДЧЩТБЦЕОЙС.

тЙУ. 1.2 дЕТЕЧП тежбм-ЧЩТБЦЕОЙС

дТХЗЙН УРПУПВПН ДЧХНЕТОПЗП ЗТБЖЙЮЕУЛПЗП РТЕДУФБЧМЕОЙС ЧЩТБЦЕОЙК СЧМСЕФУС УПЕДЙОЕОЙЕ РБТОЩИ УЛПВПЛ МЙОЙСНЙ, ЛБЛ ВЩ УЧСЪЩЧБС ЙИ ЧЕТЕЧПЮЛБНЙ; ЙЕТБТИЙС РПДЧЩТБЦЕОЙК РТЙ ЬФПН УФБОПЧЙФУС ВПМЕЕ ОБЗМСДОПК (УН. тЙУ. 1.3). лПЗДБ тежбм-ЧЩТБЦЕОЙС РТЕДУФБЧМЕОЩ Ч ЛПНРШАФЕТЕ, БДТЕУ РБТЩ УЛПВПЛ ИТБОЙФУС ЧНЕУФЕ У ЛБЦДЩН ЮМЕОПН РБТЩ, ФБЛ ЮФП УФБОПЧЙФУС ЧПЪНПЦОЩН УПЧЕТЫБФШ УЛБЮПЛ ПФ ЛБЦДПК УЛПВЛЙ Л ЕЕ ДПРПМОСАЭЕК ЪБ ПДЙО ЫБЗ, ЛБЛ ВЩ РТПВЕЗБС ЧДПМШ МЙОЙК ТЙУХОЛБ.

тЙУ. 1.3 рБТОЩЕ УЛПВЛЙ УПЕДЙОЕОЩ ДМС ВПМШЫЕК ОБЗМСДОПУФЙ.

хРТБЦОЕОЙЕ 1.1 ъБРЙУБФШ УФТПЛХ Joe's Pizza is "cute" , ЙУРПМШЪХС ПДЙОБТОЩЕ Й ДЧПКОЩЕ ЛБЧЩЮЛЙ Ч ЛБЮЕУФЧЕ ПЗТБОЙЮЙФЕМЕК.

хРТБЦОЕОЙЕ 1.2 ъБРЙУБФШ -2 36 ЛБЛ ГЕМПЕ ЮЙУМП Ч тежбмЕ.

чЩТБЦЕОЙС-ПВТБЪГЩ (ЙМЙ РТПУФП ПВТБЪГЩ) тежбмБ ПФМЙЮБАФУС ПФ ПВЯЕЛФОЩИ ЧЩТБЦЕОЙК ФЕН, ЮФП ПОЙ НПЗХФ ЧЛМАЮБФШ УЧПВПДОЩЕ РЕТЕНЕООЩЕ. чПФ ОЕЛПФПТЩЕ РТЙНЕТЩ УЧПВПДОЩИ РЕТЕНЕООЩИ:

уЧПВПДОЩЕ РЕТЕНЕООЩЕ УПУФПСФ ЙЪ ХЛБЪБФЕМС ФЙРБ, ФПЮЛЙ Й ЙОДЕЛУБ. йОДЕЛУПН РЕТЕНЕООПК СЧМСЕФУС ЙДЕОФЙЖЙЛБФПТ МЙВП ГЕМПЕ ЮЙУМП. еУМЙ ЙОДЕЛУ СЧМСЕФУС ПДОПВХЛЧЕООЩН ЙДЕОФЙЖЙЛБФПТПН ЙМЙ ПДОПТБЪТСДОЩН ЮЙУМПН, ФПЮЛБ НПЦЕФ ВЩФШ ПРХЭЕОБ. йДЕОФЙЖЙЛБФПТ, ЙУРПМШЪХЕНЩК ЛБЛ ЙОДЕЛУ РПУМЕ ФПЮЛЙ, НПЦЕФ ОБЮЙОБФШУС ЛБЛ УП УФТПЮОПК ВХЛЧЩ, ФБЛ Й У РТПРЙУОПК. еУФШ ФТЙ ХЛБЪБФЕМС ФЙРБ. пОЙ ПВПЪОБЮБАФУС НБМЩНЙ ВХЛЧБНЙ s , t Й e ; УППФЧЕФУФЧХАЭЙЕ ЙН РЕТЕНЕООЩЕ ОБЪЩЧБАФУС ЛБЛ s-, t- Й e-РЕТЕНЕООЩНЙ. тБЪМЙЮЙЕ НЕЦДХ ОЙНЙ УПУФПЙФ Ч НОПЦЕУФЧБИ ЙИ ДПРХУФЙНЩИ ЪОБЮЕОЙК. ъОБЮЕОЙЕН s-РЕТЕНЕООПК НПЦЕФ УМХЦЙФ ФПМШЛП ПДЙО УЙНЧПМ. ъОБЮЕОЙЕН t-РЕТЕНЕООПК НПЦЕФ ВЩФШ МАВПК ФЕТН (ОБРПНОЙН, ЮФП ФЕТН — ЬФП МЙВП УЙНЧПМ, МЙВП ЧЩТБЦЕОЙЕ Ч УФТХЛФХТОЩИ УЛПВЛБИ). ъОБЮЕОЙЕН e-РЕТЕНЕООПК НПЦЕФ ВЩФШ МАВПЕ ЧЩТБЦЕОЙЕ.

пВТБЪЕГ НПЦОП ТБУУНБФТЙЧБФШ ЛБЛ НОПЦЕУФЧП ПВЯЕЛФОЩИ ЧЩТБЦЕОЙК, ЛПФПТЩЕ НПЗХФ ВЩФШ РПМХЮЕОЩ Ч ТЕЪХМШФБФЕ РТЙДБОЙС ДПРХУФЙНЩИ ЪОБЮЕОЙК ЧУЕН РЕТЕНЕООЩН. фБЛ, ПВТБЪЕГ A e.1 РТЕДУФБЧМСЕФ НОПЦЕУФЧП ЧУЕИ ПВЯЕЛФОЩИ ЧЩТБЦЕОЙК, ОБЮЙОБАЭЙИУС У УЙНЧПМБ A. чУЕН ЧИПЦДЕОЙСН ПДОПК Й ФПК ЦЕ РЕТЕНЕООПК УМЕДХЕФ РТЙДБЧБФШ ПДОП Й ФП ЦЕ ЪОБЮЕОЙЕ. пВТБЪЕГ s.1 e.2 s.1 НПЦОП ТБУУНБФТЙЧБФШ ЛБЛ НОПЦЕУФЧП ЧУЕИ ПВЯЕЛФОЩИ ЧЩТБЦЕОЙК, ЛПФПТЩЕ ОБЮЙОБАФУС Й ЪБЛБОЮЙЧБАФУС ПДОЙН Й ФЕН ЦЕ УЙНЧПМПН Й УПУФПСФ РП ЛТБКОЕК НЕТЕ ЙЪ ДЧХИ УЙНЧПМПЧ.

оП ЧЩТБЦЕОЙС-ПВТБЪГЩ ЧЩРПМОСАФ ФБЛЦЕ ЕЭЕ ПДОХ ЖХОЛГЙА: ПОЙ ПРЙУЩЧБАФ ДЕЛПНРПЪЙГЙА ПВЯЕЛФОЩИ ЧЩТБЦЕОЙК, Ч ИПДЕ ЛПФПТПК РЕТЕНЕООЩЕ ПВТБЪГБ ПФПЦДЕУФЧМСАФУС У ОЕЛПФПТЩНЙ ЮБУФСНЙ ПВЯЕЛФОПЗП ЧЩТБЦЕОЙС, ФП ЕУФШ РТЙОЙНБАФ ОЕЛПФПТЩЕ ЪОБЮЕОЙС. у ЬФПК ФПЮЛЙ ЪТЕОЙС, A e.1 СЧМСЕФУС РТПГЕДХТПК, ЛПФПТБС РТПЧЕТСЕФ, ЮФП РЕТЧЩН УЙНЧПМПН ДБООПЗП ПВЯЕЛФОПЗП ЧЩТБЦЕОЙС СЧМСЕФУС A , Й РТЙУЧБЙЧБЕФ ПУФБМШОХА ЕЗП ЮБУФШ РЕТЕНЕООПК e.1 Ч ЛБЮЕУФЧЕ ЪОБЮЕОЙС. ьФБ РТПГЕДХТБ ЙЪЧЕУФОБ ЛБЛ УПРПУФБЧМЕОЙЕ У ПВТБЪГПН.

дМС ЪБДБООЩИ ПВЯЕЛФОПЗП ЧЩТБЦЕОЙС E Й ПВТБЪГБ P ВХДЕН ПВПЪОБЮБФШ ПРЕТБГЙА УПРПУФБЧМЕОЙС E У P ЮЕТЕЪ E : P , ЗДЕ ДЧПЕФПЮЙЕ — ЕЭЕ ПДЙО УРЕГЙБМШОЩК ЪОБЛ тежбмБ, ЪОБЛ УПРПУФБЧМЕОЙС. вХДЕН ЗПЧПТЙФШ ФБЛЦЕ, ЮФП E ТБУРПЪОБЕФУС ЛБЛ (ЮБУФОЩК УМХЮБК) P . ч РБТЕ E : P ОБЪПЧЕН E БТЗХНЕОФПН , Б PПВТБЪГПН ПРЕТБГЙЙ УПРПУФБЧМЕОЙС.

еУМЙ УХЭЕУФЧХЕФ РПДУФБОПЧЛБ S ДМС РЕТЕНЕООЩИ Ч P ФБЛБС, ЮФП РТЙНЕОЕОЙЕ S Л P РТЙЧПДЙФ Л E , ФПЗДБ ВХДЕН ЗПЧПТЙФШ, ЮФП УПРПУФБЧМЕОЙЕ, ЙМЙ ТБУРПЪОБЧБОЙЕ, СЧМСЕФУС ХУРЕЫОЩН. рЕТЕНЕООЩЕ Ч P РТЙОЙНБАФ ЪОБЮЕОЙС, РТЕДРЙУЩЧБЕНЩЕ РПДУФБОПЧЛПК S . ч РТПФЙЧОПН УМХЮБЕ УПРПУФБЧМЕОЙЕ УЮЙФБЕН ОЕХДБЧЫЙНУС. еУМЙ ЙНЕЕФУС ОЕУЛПМШЛП УРПУПВПЧ РТЙУЧБЙЧБОЙС ЪОБЮЕОЙК УЧПВПДОЩН РЕТЕНЕООЩН Ч ПВТБЪГЕ, РТЙ ЛПФПТЩИ УПРПУФБЧМЕОЙЕ НПЦЕФ ВЩФШ ХУРЕЫОП, ФП ФПЗДБ ЧЩВЙТБЕФУС ФБЛПК УРПУПВ, РТЙ ЛПФПТПН УБНБС МЕЧБС e-РЕТЕНЕООБС РТЙОЙНБЕФ ОБЙВПМЕЕ ЛПТПФЛПЕ ЪОБЮЕОЙЕ. еУМЙ ЬФП ОЕ РТЙЧПДЙФ Л ПДОПЪОБЮОПУФЙ, РПДПВОЩК ЧЩВПТ ДЕМБЕФУС ДМС УМЕДХАЭЕК (УБНПК МЕЧПК) e-РЕТЕНЕООПК, Й Ф.Д. йОЩНЙ УМПЧБНЙ, РТЙ ЧЩРПМОЕОЙЙ ТБУРПЪОБЧБОЙС БТЗХНЕОФ E ПВПЪТЕЧБЕФУС УМЕЧБ ОБРТБЧП Й ЧЩВЙТБЕФУС РЕТЧПЕ ХУРЕЫОПЕ УПРПУФБЧМЕОЙЕ E У P .

рТЙЧЕДЕН ОЕУЛПМШЛП РТЙНЕТПЧ. уПРПУФБЧМЕОЙЕ

УЮЙФБЕФУС ХУРЕЫОЩН , ЕУМЙ e.1 РТЙОЙНБЕФ ЪОБЮЕОЙЕ B C . уПРПУФБЧМЕОЙЕ

ФЕТРЙФ ОЕХДБЮХ, РПУЛПМШЛХ МЕЧБС УЛПВЛБ ОЕ УЙНЧПМ, ФБЛ ЮФП ПОБ ОЕ НПЦЕФ ВЩФШ УПРПУФБЧМЕОБ У s.X. у ДТХЗПК УФПТПОЩ, ЕЕ ОЕМШЪС ЙЗОПТЙТПЧБФШ. пДОБЛП,

тБУРПЪОБЧБОЙЕ '++' ЛБЛ s.1 e.2 s.1 СЧМСЕФУС ХУРЕЫОЩН — РТЙ s.1, РТЙОЙНБАЭЕН ЪОБЮЕОЙЕ '+', Й РТЙ РТЙУЧПЕОЙЙ e.2 РХУФПЗП ЧЩТБЦЕОЙС. оП УПРПУФБЧМЕОЙЕ

СЧМСЕФУС РТЙНЕТПН УЙФХБГЙЙ, ЛПЗДБ ЙНЕЕФУС ВПМЕЕ ЮЕН ПДЙО УРПУПВ РТЙДБОЙС ЪОБЮЕОЙК ДМС УПРПУФБЧМЕОЙЙ. уПЗМБУОП РТЙЧЕДЕООПНХ ЧЩЫЕ ПРТЕДЕМЕОЙА, УЙНЧПМ '+' Ч ПВТБЪГЕ ВХДЕФ ЙДЕОФЙЖЙГЙТПЧБФШУС У РЕТЧЩН УЙНЧПМПН '+' Ч БТЗХНЕОФЕ (УПРПУФБЧМЕОЙЕ УМЕЧБ-ОБРТБЧП). фБЛЙН ПВТБЪПН, e.1 РТЙНЕФ ЪОБЮЕОЙЕ A B, Б e.2 — УФБОЕФ ГЕРПЮЛПК C '+' D E F.

ч УМЕДХАЭЕН РТЙНЕТЕ:

УПРПУФБЧМЕОЙЕ РПФЕТРЙФ ОЕХДБЮХ, ФБЛ ЛБЛ ЕДЙОУФЧЕООЩК УЙНЧПМ '+' Ч БТЗХНЕОФЕ ОБИПДЙФУС ЧОХФТЙ УЛПВПЛ. рТЙ УПРПУФБЧМЕОЙЙ ЕЗП У '+' Ч ПВТБЪГЕ НЩ ДПМЦОЩ ВЩМЙ ВЩ РТЙУЧПЙФШ e.1 Й e.2 ФБЛЙЕ ЪОБЮЕОЙС, ЛПФПТЩЕ ОЕУВБМБОУЙТПЧБОЩ РП УЛПВЛБН, Б ЬФП ОЕЧПЪНПЦОП. уФТХЛФХТОЩЕ УЛПВЛЙ Ч тежбмЕ — ЧЕЭШ ЧЕУШНБ УЕТШЕЪОБС. юБУФЙ ЧЩТБЦЕОЙК, ЛПФПТЩЕ УБНЙ ОЕ СЧМСАФУС ЧЩТБЦЕОЙСНЙ, ОЕ НПЗХФ ПВТБВБФЩЧБФШУС УБНПУФПСФЕМШОП ОЙ Ч ЛБЛПН ЛПОФЕЛУФЕ.

хРТБЦОЕОЙЕ 1.3 ъБРЙЫЙФЕ ПВТБЪГЩ, ЛПФПТЩЕ НПЗХФ ВЩФШ ЪБДБОЩ УМЕДХАЭЙНЙ УМПЧЕУОЩНЙ ПРЙУБОЙСНЙ: (a) ЧЩТБЦЕОЙЕ, ПЛБОЮЙЧБАЭЕЕУС ДЧХНС ПДЙОБЛПЧЩНЙ УЙНЧПМБНЙ; (b) ЧЩТБЦЕОЙЕ, ЛПФПТПЕ УПДЕТЦЙФ РП ЛТБКОЕК НЕТЕ ДЧБ ПДЙОБЛПЧЩИ ФЕТНБ ОБ ЧЕТИОЕН ХТПЧОЕ УФТХЛФХТЩ; (c) ОЕРХУФПЕ ЧЩТБЦЕОЙЕ.

хРТБЦОЕОЙЕ 1.4 пРТЕДЕМЙФЕ ТЕЪХМШФБФЩ УМЕДХАЭЙИ УПРПУФБЧМЕОЙК:

тежбм-РТПЗТБННБ ЕУФШ РЕТЕЮЕОШ ЖХОЛГЙПОБМШОЩИ ПРТЕДЕМЕОЙК. пОБ НПЦЕФ ФБЛЦЕ УПДЕТЦБФШ ЧОЕЫОЙЕ УУЩМЛЙ (ЛПФПТЩЕ ВХДХФ ПВУХЦДБФШУС Ч Chapter 2) Й ЛПННЕОФЙТХАЭЙЕ УФТПЛЙ. лПННЕОФЙТХАЭБС УФТПЛБ ОБЮЙОБЕФУС У УЙНЧПМБ ЪЧЕЪДПЮЛЙ * , Й ОЕ ЧМЙСЕФ ОБ ЧЩРПМОЕОЙЕ РТПЗТБННЩ. лПННЕОФЙТХАЭЙЕ УФТПЛЙ НПЗХФ ЧУФБЧМСФШУС ЛБЛ ЧОХФТШ ЖХОЛГЙПОБМШОЩИ ПРТЕДЕМЕОЙК ФБЛ Й НЕЦДХ ОЙНЙ. рПТСДПЛ ЖХОЛГЙПОБМШОЩИ ПРТЕДЕМЕОЙК Ч РТПЗТБННЕ ОЕ ЙНЕЕФ ЪОБЮЕОЙС.

жХОЛГЙПОБМШОПЕ ПРТЕДЕМЕОЙЕ ЙНЕЕФ ПДОХ ЙЪ УМЕДХАЭЙИ ЖПТН:

ъОБЮЙНПУФШ РТЕЖЙЛУБ $ENTRY ВХДЕФ ТБУУНПФТЕОБ Ч Chapter 2 ОБТСДХ У РТЙНЕОЕОЙЕН ЧОЕЫОЙИ УУЩМПЛ.

йНС ЖХОЛГЙЙ СЧМСЕФУС ЙДЕОФЙЖЙЛБФПТПН. вМПЛ ЕУФШ РЕТЕЮЕОШ РТЕДМПЦЕОЙК, ТБЪДЕМСЕНЩИ ФПЮЛБНЙ У ЪБРСФПК; РПУМЕДОЕЕ РТЕДМПЦЕОЙЕ ФБЛЦЕ НПЦЕФ ЪБЛБОЮЙЧБФШУС ФПЮЛПК У ЪБРСФПК. рПТСДПЛ РТЕДМПЦЕОЙК Ч ЖХОЛГЙПОБМШОПН ПРТЕДЕМЕОЙЙ СЧМСЕФУС УХЭЕУФЧЕООЩН.

рТЕДМПЦЕОЙЕ ЙНЕЕФ ЧЙД:

ЗДЕ МЕЧБС ЮБУФШ СЧМСЕФУС ЧЩТБЦЕОЙЕН-ПВТБЪГПН, Б РТБЧБС ЮБУФШ СЧМСЕФУС ПВЭЙН ЧЩТБЦЕОЙЕН. оБРПНОЙН, ЮФП ПВЯЕЛФОПЕ ЧЩТБЦЕОЙЕ НПЦЕФ ЧЛМАЮБФШ ФПМШЛП УЙНЧПМЩ Й УФТХЛФХТОЩЕ УЛПВЛЙ, Б ЧЩТБЦЕОЙЕ-ПВТБЪЕГ НПЦЕФ, ЛТПНЕ ЬФПЗП, ЧЛМАЮБФШ Й УЧПВПДОЩЕ РЕТЕНЕООЩЕ. пВЭЕЕ ЦЕ ЧЩТБЦЕОЙЕ, Ч ДПРПМОЕОЙЕ Л УПУФБЧМСАЭЙН ЧЩТБЦЕОЙС-ПВТБЪГБ, НПЦЕФ ЧЛМАЮБФШ ЕЭЕ ЧЩЮЙУМЙФЕМШОЩЕ УЛПВЛЙ . пОЙ ЧИПДСФ Ч ОЕЗП ЛБЛ ЮБУФЙ ЧЩЪПЧПЧ ЖХОЛГЙК:

ЗДЕ ЙНСЖХОЛГЙЙ СЧМСЕФУС МЙВП ЙОДЕОФЙЖЙЛБФПТПН, МЙВП ПДОЙН ЙЪ ЮЕФЩТЕИ ЪОБЛПЧ БТЙЖНЕФЙЮЕУЛЙИ ПРЕТБГЙК (+ , - , * , Й / ); Б БТЗХНЕОФ СЧМСЕФУС ПВЭЙН тежбм-ЧЩТБЦЕОЙЕН. фБЛЙН ПВТБЪПН, ЧЩЮЙУМЙФЕМШОЩЕ УЛПВЛЙ НПЗХФ ВЩФШ ЧМПЦЕООЩНЙ. ъБНЕФЙН, ЮФП ЙНС ЖХОЛГЙЙ ДПМЦОП УМЕДПЧБФШ ОЕРПУТЕДУФЧЕООП ЪБ ПФЛТЩЧБАЭЕК ЧЩЮЙУМЙФЕМШОПК УЛПВЛПК, ПОП ОЕ ДПРХУЛБЕФ ЧЛМАЮЕОЙС РТПВЕМПЧ ЙМЙ ЛПОГБ УФТПЛЙ.

йНЕАФУС УМЕДХАЭЙЕ ЧБЦОЩЕ ПЗТБОЙЮЕОЙС ОБ РТБЧХА ЮБУФШ РТЕДМПЦЕОЙС: РТБЧБС ЮБУФШ НПЦЕФ ЧЛМАЮБФШ ФПМШЛП ФБЛЙЕ УЧПВПДОЩЕ РЕТЕНЕООЩЕ, ЛПФПТЩЕ ЧИПДСФ ФБЛЦЕ Й Ч МЕЧХА ЮБУФШ (УН. УМЕДХАЭЙК ТБЪДЕМ). йНЕЕФУС ФБЛЦЕ ФЕИОЙЮЕУЛПЕ ПЗТБОЙЮЕОЙЕ: ЙОДЕЛУЩ РЕТЕНЕООЩИ ДПМЦОЩ ВЩФШ ХОЙЛБМШОЩНЙ, Ф.Е. НПЦОП ЙУРПМШЪПЧБФШ e.X Й s.1 МАВПЕ ЮЙУМП ТБЪ, ОП ЕУМЙ ХЦЕ ЙУРПМШЪХЕФУС e.X , ФП ЪБРТЕЭЕОП ЙУРПМШЪПЧБФШ s.X ЙМЙ t.X Ч ЬФПН ЦЕ РТЕДМПЦЕОЙЙ; ЙУРПМШЪПЧБОЙЕ s.1 ЙУЛМАЮБЕФ РТЙНЕОЕОЙЕ e- Й t-РЕТЕНЕООЩИ У ЙОДЕЛУПН 1 .

оБТСДХ У ЛПННЕОФЙТХАЭЙНЙ УФТПЛБНЙ, РТЕДМПЦЕОЙС НПЗХФ ЧЛМАЮБФШ ДМЙООЩЕ ЛПННЕОФБТЙЙ, ЛПФПТЩЕ ОБЮЙОБАФУС ЛПНВЙОБГЙЕК /* Й ЪБЛБОЮЙЧБАФУС ЛПНВЙОБГЙЕК */ . пОЙ НПЗХФ РПСЧМСФШУС ЧУАДХ РТЙ ХУМПЧЙЙ, ЮФП ЙНЙ ОЕ ОБТХЫБАФУС МЕЛУЙЮЕУЛЙЕ ЬМЕНЕОФЩ (ЙДЕОФЙЖЙЛБФПТЩ, ЮЙУМБ, УФТПЛЙ, РЕТЕНЕООЩЕ) Й МЕЧБС ЧЩЮЙУМЙФЕМШОБС УЛПВЛБ ОЕ ПФТЩЧБЕФУС ПФ УМЕДХАЭЕЗП ЪБ ОЕК ЙНЕОЙ ЖХОЛГЙЙ.

тежбм-НБЫЙОПК ОБЪЩЧБЕФУС БВУФТБЛФОПЕ ХУФТПКУФЧП, ЛПФПТПЕ ЧЩРПМОСЕФ тежбм-РТПЗТБННЩ. пОБ ЙНЕЕФ ДЧБ РПФЕОГЙБМШОП ВЕУЛПОЕЮОЩИ ИТБОЙМЙЭБ ЙОЖПТНБГЙЙ: РПМЕ РТПЗТБННЩ Й РПМЕ ЪТЕОЙС. рПМЕ РТПЗТБННЩ УПДЕТЦЙФ тежбм-РТПЗТБННХ, ЛПФПТБС ЪБЗТХЦБЕФУС Ч НБЫЙОХ РЕТЕД ЪБРХУЛПН Й ОЕ ЙЪНЕОСЕФУС Ч ИПДЕ ЧЩРПМОЕОЙС. рПМЕ ЪТЕОЙС ИТБОЙФ ЧЩТБЦЕОЙЕ ВЕЪ УЧПВПДОЩИ РЕТЕНЕООЩИ; ФБЛЙЕ ЧЩТБЦЕОЙС ОБЪЩЧБАФУС ПРТЕДЕМЕООЩНЙ. рПМЕ ЪТЕОЙС (Ф.Е. ЧЩТБЦЕОЙЕ Ч ЬФПН РПМЕ) ЙЪНЕОСЕФУС Ч ИПДЕ ТБВПФЩ НБЫЙОЩ.

тБВПФБ тежбм-НБЫЙОЩ ПУХЭЕУФЧМСЕФУС Ч РПЫБЗПЧПН ТЕЦЙНЕ. лБЦДЩК ЫБЗ ЧЩРПМОСЕФУС УМЕДХАЭЙН ПВТБЪПН. еУМЙ ЧЩТБЦЕОЙЕ Ч РПМЕ ЪТЕОЙС ОЕ ЧЛМАЮБЕФ ЧЩЮЙУМЙФЕМШОЩИ УЛПВПЛ (НЩ ВХДЕН ОБЪЩЧБФШ ФБЛЙЕ ЧЩТБЦЕОЙС РБУУЙЧОЩНЙ), тежбм-НБЫЙОБ РТЙИПДЙФ Л ОПТНБМШОПНХ ПУФБОПЧХ. ч РТПФЙЧОПН УМХЮБЕ ПОБ ЧЩВЙТБЕФ Ч РПМЕ ЪТЕОЙС ПДОП ЙЪ РПДЧЩТБЦЕОЙК ЧЙДБ , ЗДЕ F СЧМСЕФУС ЖХОЛГЙПОБМШОЩН УЙНЧПМПН, Б E — ЧЩТБЦЕОЙЕН, ДМС ФПЗП ЮФПВЩ ФТБОУЖПТНЙТПЧБФШ ЕЗП, ЙУРПМШЪХС ПРТЕДЕМЕОЙЕ F ЙЪ РТПЗТБННЩ. ьФП РПДЧЩТБЦЕОЙЕ ОБЪЩЧБЕФУС РЕТЧЙЮОЩН БЛФЙЧОЩН РПДЧЩТБЦЕОЙЕН. пОП ПРТЕДЕМСЕФУС ЛБЛ РЕТЧПЕ (УМЕЧБ) РПДЧЩТБЦЕОЙЕ , ФБЛПЕ, ЮФП E РБУУЙЧОП, Ф.Е. ОЕ УПДЕТЦЙФ ЧЩЮЙУМЙФЕМШОЩИ УЛПВПЛ.

рЕТЧЙЮОПЕ РПДЧЩТБЦЕОЙЕ ФТБОУЖПТНЙТХЕФУС УМЕДХАЭЙН ПВТБЪПН. тежбм-НБЫЙОБ УТБЧОЙЧБЕФ E У РПУМЕДПЧБФЕМШОЩНЙ РТЕДМПЦЕОЙСНЙ ЙЪ ПРТЕДЕМЕОЙС F , ОБЮЙОБС У РЕТЧПЗП, ПУХЭЕУФЧМСС РПЙУЛ РЕТЧПЗП РТЙНЕОЙНПЗП РТЕДМПЦЕОЙС.

рТЕДМПЦЕОЙЕ РТЙНЕОЙНП, ЕУМЙ E НПЦЕФ ВЩФШ ТБУРПЪОБОП ЛБЛ ЕЗП МЕЧБС ЮБУФШ L, Ф.Е. УПРПУФБЧМЕОЙЕ E : L СЧМСЕФУС ХУРЕЫОЩН. рПУМЕ ОБИПЦДЕОЙС РЕТЧПЗП РТЙНЕОЙНПЗП РТЕДМПЦЕОЙС тежбм-НБЫЙОБ ЛПРЙТХЕФ ЕЗП РТБЧХА ЮБУФШ R Й РТЙНЕОСЕФ Л ОЕК РПДУФБОПЧЛХ, РПМХЮЕООХА РТЙ УПРПУФБЧМЕОЙЙ E : L . фБЛЙН ПВТБЪПН, УЧПВПДОЩЕ РЕТЕНЕООЩЕ Ч R ЪБНЕЭБАФУС ЪОБЮЕОЙСНЙ, ЛПФПТЩЕ ПОЙ ДПМЦОЩ РТЙОСФШ ДМС ХУРЕЫОПЗП УПРПУФБЧМЕОЙС. ъБФЕН ПРТЕДЕМЕООПЕ ЧЩТБЦЕОЙЕ, УЖПТНЙТПЧБООПЕ РТЙ ЬФПН, ЪБНЕЭБЕФ РЕТЧЙЮОПЕ БЛФЙЧОПЕ РПДЧЩТБЦЕОЙЕ Ч РПМЕ ЪТЕОЙС. ьФЙН ЪБЧЕТЫБЕФУС ФЕЛХЭЙК ЫБЗ Й НБЫЙОБ РЕТЕИПДЙФ Л ЧЩРПМОЕОЙА УМЕДХАЭЕЗП ЫБЗБ. еУМЙ ЦЕ РТЙНЕОЙНЩИ РТЕДМПЦЕОЙК Ч ПРТЕДЕМЕОЙЙ F ОЕ ЙНЕЕФУС, тежбм-НБЫЙОБ РТЙИПДЙФ Л БЧБТЙКОПНХ ПУФБОПЧХ `пФПЦДЕУФЧМЕОЙЕ ОЕЧПЪНПЦОП.

дМС ФПЗП, ЮФПВЩ ЧЩЮЙУМЙФШ ЪОБЮЕОЙЕ ОЕЛПФПТПК ЖХОЛГЙЙ F У БТЗХНЕОФПН E (ЛПФПТЩК ДПМЦЕО ВЩФШ ПВЯЕЛФОЩН ЧЩТБЦЕОЙЕН), РПНЕЭБЕФУС Ч РПМЕ ЪТЕОЙС тежбм-НБЫЙОЩ Й НБЫЙОБ ЪБРХУЛБЕФУС. еУМЙ РПУМЕ ЛПОЕЮОПЗП ЮЙУМБ ЫБЗПЧ тежбм-НБЫЙОБ РТЙИПДЙФ Л ОПТНБМШОПНХ ПУФБОПЧХ, ФП УПДЕТЦЙНПЕ РПМС ЪТЕОЙС (ФБЛЦЕ ПВЯЕЛФОПЕ ЧЩТБЦЕОЙЕ) СЧМСЕФУС ЪОБЮЕОЙЕН ЖХОЛГЙЙ. еУМЙ ЦЕ НБЫЙОБ ЪБГЙЛМЙЧБЕФУС ЙМЙ РТЙИПДЙФ Л БЧБТЙКОПНХ ПУФБОПЧХ, ЪОБЮЕОЙЕ ЖХОЛГЙЙ УЮЙФБЕФУС ОЕПРТЕДЕМЕООЩН.

рПТСДПЛ ЧЩЮЙУМЕОЙС ЧМПЦЕООЩИ ЧЩЪПЧПЧ ЖХОЛГЙК, ЙУРПМШЪХЕНЩК Ч тежбм-НБЫЙОЕ, ОБЪЩЧБЕФУС БРРМЙЛБФЙЧОЩН ЙМЙ РПТСДЛПН ФЙРБ ЙЪОХФТЙОБТХЦХ . рЕТЕД ЪБРХУЛПН ЧЩЮЙУМЕОЙС МАВПЗП ЧЩЪПЧБ ЖХОЛГЙЙ ДПМЦОЩ ВЩФШ ЪБЧЕТЫЕОЩ ЧУЕ ЧЩЮЙУМЕОЙС ЧЩЪПЧПЧ ЖХОЛГЙК Ч БТЗХНЕОФЕ.

лТПНЕ ЖХОЛГЙК, ПРТЕДЕМСЕНЩИ Ч тежбмЕ РПУТЕДУФЧПН РТЕДМПЦЕОЙК, УХЭЕУФЧХЕФ ОЕУЛПМШЛП ЖХОЛГЙК, ЛПФПТЩЕ ОЕ ДПМЦОЩ (Б ЧП НОПЗЙИ УМХЮБСИ Й ОЕ НПЗХФ) ПРТЕДЕМСФШУС Ч тежбмЕ, ОП ЧУЕ-ФБЛЙ НПЗХФ РТЙНЕОСФШУС, РПУЛПМШЛХ ПОЙ ЧУФТПЕОЩ Ч УЙУФЕНХ. л ЬФПК ЛБФЕЗПТЙЙ, Ч ЮЙУМЕ РТПЮЙИ, ПФОПУСФУС ЖХОЛГЙЙ ЧЧПДБ-ЧЩЧПДБ Й ЖХОЛГЙЙ ЧЩРПМОЕОЙС БТЙЖНЕФЙЮЕУЛЙИ ПРЕТБГЙК. тЕБМЙЪБГЙС тежбм-НБЫЙОЩ ОБ ЛПНРШАФЕТЕ ПФМЙЮБЕФУС ПФ БВУФТБЛФОПК тежбм-НБЫЙОЩ ФЕН, ЮФП РЕТЕД РТПУНПФТПН ПРТЕДЕМЕОЙС ЖХОЛГЙЙ Ч РПМЕ РТПЗТБННЩ УЙУФЕНБ РТПЧЕТСЕФ, ЧИПДЙФ МЙ ЙНС ЖХОЛГЙЙ Ч УРЙУПЛ ЙНЕАЭЙИУС ЧУФТПЕООЩИ ЖХОЛГЙК. еУМЙ ПОП ПВОБТХЦЕОП Ч УРЙУЛЕ, БЛФЙЧЙЪЙТХЕФУС УППФЧЕФУФЧХАЭБС РПДРТПЗТБННБ, ЛПФПТБС ЧЩРПМОСЕФ ФТЕВХЕНЩЕ ПРЕТБГЙЙ Й ЪБНЕЭБЕФ ЧЩЪПЧ ЖХОЛГЙЙ Ч РПМЕ ЪТЕОЙС ОБ ЕЗП ЧЩЮЙУМЕООПЕ ЪОБЮЕОЙЕ.

рТЙНЕТ 1. ъБНЕОБ РМАУПЧ ОБ НЙОХУЩ

дПРХУФЙН, ЦЕМБФЕМШОП ЙНЕФШ ЖХОЛГЙА, ЛПФПТБС ПВТБВБФЩЧБЕФ УЙНЧПМШОЩЕ УФТПЛЙ Й ЛПОЧЕТФЙТХЕФ ЛБЦДЩК ЪОБЛ '+' Ч '-' . уРЕТЧБ ПРТЕДЕМЙН БМЗПТЙФН УМПЧЕУОП:

  1. чЪСФШ РЕТЧЩК УЙНЧПМ БТЗХНЕОФБ. еУМЙ ЬФП '+' , ЪБНЕОЙФШ ЕЗП ОБ '-' . фЕРЕТШ РТЙНЕОЙФШ ФТБОУЖПТНБГЙА Л ПУФБЧЫЕКУС ЮБУФЙ БТЗХНЕОФБ ФБЛ, ЮФПВЩ ТЕЪХМШФБФ ВЩМ ДПРЙУБО Л УЙНЧПМХ '-' .
  2. еУМЙ РЕТЧЩК УЙНЧПМ ОЕ '+' , ПУФБЧЙФШ ЕЗП ВЕЪ ЙЪНЕОЕОЙС Й РТЙНЕОЙФШ ФТБОУЖПТНБГЙА Л ПУФБЧЫЕКУС ЮБУФЙ ФБЛ ЦЕ, ЛБЛ Й Ч РХОЛФЕ 1.
  3. еУМЙ УФТПЛБ РХУФБС, ЧЩИПДОБС УФТПЛБ ФБЛЦЕ РХУФБ. лПОЕГ ТБВПФЩ.

фЕРЕТШ ЧЩТБЪЙН ЬФП ОБ тежбмЕ. рХУФШ ЙНЕОЕН ЖХОЛГЙЙ УМХЦЙФ Chpm :

дБМЕЕ РТЙЧЕДЕОБ РПУМЕДПЧБФЕМШОПУФШ ЧЩЮЙУМЕОЙК ДМС УМХЮБС, ЛПЗДБ БТЗХНЕОФПН Chpm СЧМСЕФУС 'ab+c-+d' :

йНЕЕФУС МХЮЫЕЕ ТЕЫЕОЙЕ РТПВМЕНЩ. ъБ ПДЙО ЫБЗ тежбм-НБЫЙОЩ НПЦОП ОБКФЙ РЕТЧЩК УЙНЧПМ '+' Й ЪБНЕОЙФШ ЕЗП ОБ '-' . еУМЙ Ч УФТПЛЕ ОЕФ ОЙ ПДОПЗП УЙНЧПМБ '+', ПОБ ФТБОУЖПТНЙТХЕФУС Ч УБНПЕ УЕВС:

рТЙ ФПН ЦЕ БТЗХНЕОФЕ, ЮФП Й ЧЩЫЕ, ЧЩЮЙУМЕОЙЕ РТПЙЪЧПДЙФУС ЧУЕЗП ЪБ ФТЙ ЫБЗБ:


рТЙНЕТ 2. жБЛФПТЙБМ

пРТЕДЕМЙН Ч тежбмЕ ЖХОЛГЙА ЖБЛФПТЙБМ ДМС ГЕМЩИ ОЕПФТЙГБФЕМШОЩИ ЮЙУЕМ. бТЙЖНЕФЙЮЕУЛЙЕ ЖХОЛГЙЙ Ч тежбмЕ (УН. Chapter 2 Й Reference Section C) ЙНЕАФ ЙНЕОБ Add , Sub , Mul , Div . пОЙ НПЗХФ ВЩФШ ФБЛЦЕ РТЕДУФБЧМЕОЩ УЙНЧПМБНЙ + , - , * Й / УППФЧЕФУФЧЕООП.

рТЙНЕТ 3. рЕТЕЧПД УМПЧБ

йОПЗДБ ЖХОЛГЙЙ ПРТЕДЕМСАФУС У РПНПЭША ФБВМЙГЩ. рТЕДРПМПЦЙН, НЩ ИПФЙН ФТБОУМЙТПЧБФШ ЙФБМШСОУЛЙЕ УМПЧБ Ч БОЗМЙКУЛЙЕ. нЩ, ТБЪХНЕЕФУС, ДПМЦОЩ ТБЪМЙЮБФШ ПРТЕДЕМЕОЙЕ ФБВМЙГЩ Й ПРТЕДЕМЕОЙЕ ЖХОЛГЙЙ, ЛПФПТБС ПУХЭЕУФЧМСЕФ РЕТЕЧПД У ЙУРПМШЪПЧБОЙЕН ФБВМЙГЩ. рХУФШ РЕТЧБС ЙНЕОХЕФУС Table — ЬФП ЖХОЛГЙС, ОЕ ЙНЕАЭБС РЕТЕНЕООЩИ, ЛПФПТБС ЧПЪЧТБЭБЕФ ФБВМЙГХ Ч ЛБЮЕУФЧЕ ЪОБЮЕОЙС. рХУФШ ЧФПТБС ОБЪЩЧБЕФУС Italian , ЬФП ЖХОЛГЙС ПДОПК РЕТЕНЕООПК ДМС РЕТЕЧПДБ ЙФБМШСОУЛЙИ УМПЧ. уТБЪХ ЦЕ НПЦОП ЪБНЕФЙФШ, ЮФП ЖХОЛГЙС, ЛПФПТБС ДЕКУФЧЙФЕМШОП ЙУРПМШЪХЕФ ФБВМЙГХ, ДПМЦОБ ЙНЕФШ ЕЕ Ч ЛБЮЕУФЧЕ ПДОПЗП ЙЪ УЧПЙИ БТЗХНЕОФПЧ. рПЬФПНХ ЧЧЕДЕН ЖХОЛГЙА Trans ПФ ДЧХИ БТЗХНЕОФПЧ, ЛПФПТХА ВХДЕН ЧЩЪЩЧБФШ Ч ЖПТНБФЕ:

уЛПВЛЙ ПФДЕМСАФ РЕТЧЩК БТЗХНЕОФ — УМПЧП, ЛПФПТПЕ ОХЦОП РЕТЕЧЕУФЙ — ПФ ЧФПТПЗП БТЗХНЕОФБ, ФБВМЙГЩ, ЛПФПТБС РТЙ ЬФПН ЙУРПМШЪХЕФУС. фЕРЕТШ НПЦОП ПРТЕДЕМЙФШ Ital-Engl ЮЕТЕЪ ЧЩЪПЧ Trans :

жПТНБФ ФБВМЙГЩ ДПМЦЕО ВЩФШ ФБЛЙН, ЮФПВЩ ОЕПВИПДЙНПЕ УМПЧП НПЗМП ВЩФШ ОБКДЕОП ЪБ УЮЕФ РТЙНЕОЕОЙС РТПУФПЗП Й ЬЖЖЕЛФЙЧОПЗП ПВТБЪГБ . фБВМЙГБ ДМС РСФЙ ЙФБМШСОУЛЙИ УМПЧ НПЦЕФ ЙНЕФШ ЧЙД:

рТЙ ФБВМЙГЕ ЬФПЗП ЖПТНБФБ ПРТЕДЕМЕОЙЕ ЖХОЛГЙЙ Trans ЙНЕЕФ ЧЙД:

чФПТПЕ РТЕДМПЦЕОЙЕ ЗПЧПТЙФ, ЮФП ЕУМЙ УМПЧП ОЕ ОБКДЕОП Ч ФБВМЙГЕ, ФП Ч РЕТЕЧПД РПДУФБЧМСАФУС ФТЙ ЪЧЕЪДПЮЛЙ.

хРТБЦОЕОЙЕ 1.5 ч ТЕЛХТУЙЧОПК БТЙЖНЕФЙЛЕ ОБФХТБМШОЩЕ ЮЙУМБ РТЕДУФБЧМСАФУС ЛБЛ 0,0′,0», Й Ф.Д. пРЕТБГЙС УМПЦЕОЙС ПРТЕДЕМСЕФУС УППФОПЫЕОЙСНЙ:

оБРЙУБФШ ОБЙВПМЕЕ ВМЙЪЛЙК Л ЬФПНХ ЧБТЙБОФ ОБ тежбмЕ , ЙУРПМШЪХС '0' Ч ЛБЮЕУФЧЕ Й 's' ЧНЕУФП'.

хРТБЦОЕОЙЕ 1.6 пРТЕДЕМЙФШ ЖХОЛГЙА , ЛПФПТБС УЛМБДЩЧБЕФ ДЧПЙЮОЩЕ ЮЙУМБ e.1 Й e.2 .

о python, it, виртуализации и Co

блог о python, виртуализации, программировании и другом

December 27, 2011

Сопоставление объектов с образцом (pattern matching)

В функциональных языках есть интересная возможность, фактически являющаяся расширением идеи перегрузки функций — сопоставление с образцом. Для этого поддерживается специальный синтаксис шаблонов структур данных, позволяющий проверить что объект имеет определенный тип и/или поля, а также извлечь из него некоторые данные. Пример из haskell (частично взято тут wiki):

Примерно тоже можно сделать во многих функциональных языках, но я никогда не видел подобных возможностей в императивных языках. Самое близкое что есть по интеллектуальности — перегрузка функций в C++. Такое положение связанно и с особенностями задач, обычно решаемыми в функциональных языках, и с их ориентированностью на рекурсивные структуры данных и с попытками уйти от if и других императивных особенностей.

Но тем не менее желание сделать что-то подобное для python возникало после каждого ковыряния в функциональщине и после каждой конструкции вида:

А тут что-то захотелось посмотреть внимательно на модуль ast (abstract syntax tree) — давно не использовал его, последний раз еще во времена 2.4 — тогда очень жалел, что он не позволяет компилировать измененный ast (кстати делал интересный проект по портированию большого куска кода с PyQt3 на PyQt4 и ast позволил значительно автоматизировать этот перенос).

ast позволяет получить из python кода его результат после синтаксического разбора, но еще до компиляции в байтокод, исследовать его и/или изменять и компилировать новый вариант. Пример ast:

Фактически мы получаем исходный текст в удобном для ковыряния виде (правда несколько громоздком). Именно с абстрактными синтаксически деревьями работаю всяческие анализаторы кода, оптимизаторы и прочее. ast предоставляет некоторое количество вспомогательных функций и два класса — NodeVisitor для просмотра ast и NodeTransformer для модификации.

На этом все про ast. Что хотелось от сопоставления с образцом:

    Чистый python синтаксис, что-бы никаких новых зарезервированных слов и >После некоторого времени размышлений остановился на таком варианте:

Как это должно было-бы работать:

Совсем так, как хотелось, сразу не вышло. Вышло так:

Из необязательных ограничений — нужно импортировать модуль python_match без переименования. Обернуть все функции, где используется сопоставление с образцом, декоратором ‘python_match.mathing‘.

Как это работает:

  • декоратор с помощью модуля inspect получает исходный код функции, разбирает его в ast и прогоняет через класс MatchReplacer
  • MatchReplacer наследует ast.NodeTransformer и перегружает метод visit_With, в котором подменяет ноду with на измененную конструкцию со сравнениями. Строка до >> изменяется на сравнение, а в строка после — подменяются переменные.
  • класс Match делает сопоставление объектов с образцом, если использовалось сравнение атрибутов.

Осталось некоторое количество ограничений, которые однако не принципиальные, так что поскольку задача скорее стояла из разряда — «как бы это сделать» я не стал заниматься дальнейшими оптимизациями/улучшениями.

Сопоставление с образцом

10.1. Простейший пример

10.1.1. Имеется последовательность символов . Определить, имеются ли в ней идущие друг за другом символы abcd . (Другими словами, требуется выяснить, есть ли в слове подслово abcd .)

Решение. Имеется примерно n (если быть точным, n-3 ) позиций, на которых может находиться искомое подслово в исходном слове. Для каждой из позиций можно проверить, действительно ли там оно находится, сравнив четыре символа. Однако есть более эффективный способ. Читая слово слева направо, мы ожидаем появления буквы a . Как только она появилась, мы ищем за ней букву b , затем c , и, наконец, d . Если наши ожидания оправдываются, то слово abcd обнаружено. Если же какая-то из нужных букв не появляется, мы оказываемся у разбитого корыта и начинаем все сначала.

Этот простой алгоритм можно описать в разных терминах. Используя терминологию так называемых конечных автоматов , можно сказать, что при чтении слова x слева направо мы в каждый момент находимся в одном из следующих состояний: «начальное» (0), «сразу после a » (1), «сразу после ab » (2), «сразу после abc » (3) и «сразу после abcd » (4). Читая очередную букву, мы переходим в следующее состояние по правилу, указанному в таблице.

Правила перехода для конечного автомата
Текущее состояние Очередная буква Новое состояние
a 1
кроме а
1 b 2
1 a 1
1 кроме a, b
2 c 3
2 a 1
2 кроме a, c
3 d 4
3 a 1
3 кроме a, d

Как только мы попадем в состояние 4, работа заканчивается.

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

Соответствующая программа очевидна (мы указываем новое состояние, даже если оно совпадает со старым; эти строки можно опустить):

Иными словами, мы в каждый момент храним информацию о том, какое максимальное начало нашего образца abcd является концом прочитанной части. (Его длина и есть то » состояние», о котором шла речь.)

Терминология, нами используемая, такова. Слово — это любая последовательность символов из некоторого фиксированного конечного множества . Это множество называется алфавитом, его элементы — буквами. Если отбросить несколько букв с конца слова, останется другое слово , называемое началом первого. Любое слово также считается своим началом. Конец слова — то, что останется, если отбросить несколько первых букв. Любое слово считается своим концом. Подслово — то, что останется, если отбросить буквы и с начала, и с конца. (Другими словами, подслова — это концы начал, или, что то же, начала концов.)

В терминах индуктивных функций (см. «Переменные, выражения, присваивания» ) ситуацию можно описать так: рассмотрим функцию на словах, которая принимает два значения » истина » и » ложь » и истинна на словах, имеющих abcd своим подсловом. Эта функция не является индуктивной, но имеет индуктивное расширение

Erlang для самых маленьких. Глава 1: Типы данных, переменные, списки и кортежи

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

Что бы начать работать с Erlang, в терминале выполните:

Запустится интерпретатор, в нем и надо выполнять примеры из статьи. В Erlang в конце выражения ставится точка, а не точка с запятой, как в большинстве языков. Комментарии начинаются со знака % и продолжаются до конца строки.

Итак, давайте начнем.

Числа

Erlang поддерживает два типа численных переменных: целочисленные и числа с плавающей точкой. Над числами можно производить такие математические операции как сложение, вычитание, умножение и деление:

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

Так же Erlang позволяет производить несколько операций за раз. Математические операции подчиняются стандартным правилам приоритета. Поэтому результатом выражения 2 + 3 * 4 . будет 14 , потому что умножение имеет более высокий приоритет, чем сложение. Для того, что бы явно задать порядок вычислений нужно использовать скобки:

К тому же, вы не обязаны ограничиваться только десятичной системой счисления. Вы можете использовать числа с любым основанием от 2 до 36. Для этого число необходимо указывать в виде Base#Value .

Но и это еще не все. В Erlang вы можете использовать числа с разными основаниями в одном выражении:

Атомы

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

Атомы должны начинаться со строчной буквы и могут содержать в себе строчные и заглавные буквы, цифры, знак подчеркивания( _ ) и собаку( @ ). Так же атом можно заключить в одинарные кавычки и тогда он может включать в себя любые символы. Ну и конечно же атом не может совпадать с зарезервированным словом. Поэтому названия атомов after , and , andalso , band , begin , bnot , bor , bsl , bsr , bxor , case , catch , cond , div , end , fun , if , let , not , of , or , orelse , query , receive , rem , try , when и xor недопустимы.

Логические типы данных и операторы сравнения

Булевы типы данных в Erlang — это два зарезервированных атома: true и false . С этим связан один любопытный и не очевидный факт. Но об этом чуть позже.

В языке реализованы все основные логические операции такие как «и»( and ), «или»( or ), «исключающее или»( xor ) и «отрицание»( not ).

Операторы and и or всегда вычисляют значения выражений с обеих сторон от себя. Поэтому при выполнении кода (1 > 2) or (3 будут найдены значения обоих выражений, хотя после вычисления правого выражения результат уже известен. Если вы хотите избежать этого, используйте операторы andalso и orelse .

Для сравнения значений между собой используются операторы «равно»( == ), «соответственно равно»( =:= ), «соответственно неравно»( =/= ), «неравно»( /= ), «меньше»( ), «меньше или равно»( = ), «больше»( > ) и «больше или равно»( >= ).

Если вы раньше программировали на других языках, то, скорее всего, привыкли, что в них true равно 1 , а false равно 0 . В Erlang это правило не работает:

Обратили внимание на третью строку? Странно, неправда ли? А все дело в том, что Erlang позволяет сравнивать значения разных типов и при сравнении руководствуется следующим правилом: число(number) true и false — атомы, а из приведенного выражения видно, что атомы «больше» чисел. Поэтому и получается, что false > 19 .

Переменные

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

Имя переменной должно начинаться с заглавной буквы или знака подчеркивания( _ ). Имя переменной может состоять из одного только знака подчеркивания. Но переменная с таким именем не запоминает значение. Такие переменные используются для сопоставления с образцом (об этом смотрите далее).

Кортежи


Иногда группу переменных, которые каким-либо образом связаны между собой, удобнее хранить вместе. Для этого Erlang предоставляет такую конструкцию, как кортеж. Кортеж имеет следующий вид: и может содержать любое количество переменных.

Давайте рассмотрим на примере, как можно использовать кортежи. Довольно заезженный пример: нам необходимо хранить информацию о точке на координатной плоскости (координаты X и Y). Мы могли бы завести две отдельных переменных и хранить координаты в них, но ведь проще хранить их вместе.

Как указано выше, размер кортежа не ограничивается двумя значениями. Так же кортеж может содержать значения разных типов, в том числе и другие кортежи.

Сопоставление с образцом

Для извлечения значений из кортежа (и не только для этого) используется сопоставление с образцом. Для начала давайте еще раз разберем, как работает оператор сопоставления( = ). Он берет значения справа и сопоставляет их с переменными, находящимися слева. Грубо говоря, это то же самое присваивание из императивных языков с одним лишь отличием: сопоставить возможно только несвязанные переменные, т.е. те у которых еще нет значения.

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

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

Не всегда нам нужны все данные. К примеру, нам может понадобиться только второе значение тройки (тройка — это кортеж из трех значений). Что бы не «плодить» бесполезные сущности, мы можем использовать специальную переменную, о которой говорили раньше: _ . Тем самым мы укажем, что в этом месте шаблона должно быть некое значение, но нам оно не нужно. Причем в шаблоне может быть несколько таких переменных. Удобно, не правда ли?

Списки

Список — это аналог массивов из императивных языков. Список имеет следующий вид: [Value1, Value2, . ValueN] . Элементы списка не обязательно должны быть одного типа. Один список может содержать числа, атомы, кортежи, другие списки и т.д.

При работе со списками в Erlang есть один странный момент:

Erlang вывел список в виде строки. Не стоит волноваться. Это касается только его отображения в терминале. На самом деле наш список все так же содержит числа. Такое поведение связанно с особенностями происхождения языка. Изначально в Erlang не было строк. И для работы с ними использовали списки, которые хранили номера символов. К счастью, язык развивается и сегодня у нас есть возможность нормально работать со строками.

Списки можно складывать ( ++ ) и вычитать друг из друга( — ). Помните, что эти операторы тоже правоассоциативны.

Так же списки можно сравнивать между собой. Для этого используются стандартные операторы сравнения. Сначала сравниваются головы списков. Если они равны, то сравниваются головы хвостов и т.д. Списки сравниваются по первым различным элементам. В приведенном ниже примере первый список больше потому, что первый элемент, который отличается от соответствующего элемента второго списка больше ( 4 > 1 ).

Списки делятся на две части: голову(head) и хвост(tail). Голова — это первый элемент списка, а хвост — все остальное. У хвоста, в свою очередь, тоже есть голова и хвост. При сопоставлении с образцом используется оператор | , что бы указать, где проходит граница между головой и хвостом.

Генераторы списков

Конечно же мы не будем постоянно задавать списки вручную. Это довольно утомительно и совсем не интересно. К счастью, создатели языка придерживаются такого же мнения и поэтому Erlang имеет инструмент для автоматического создания списков. Принцип его работы лучше всего рассматривать на примере. Давайте для начала напишем код, который автоматически составит список, который будет содержать в себе числа от 1 до 10, умноженные на 3.

Наше выражение имеет вид [Expr || Item . Erlang поочередно берет каждый элемент из SourceList и подставляет его в выражение Expr , на место переменной Item . Результат этого выражения добавляется в результирующий список. Достаточно просто, не правда ли?

Но генератор в том виде, в котором он есть сейчас практически бесполезен. Усложним задачу. Сделаем так, что бы генератор работал только с четными числами из исходного списка, которые больше 5.

Теперь наш генератор имеет вид [Expr || Item . Работает он в точности, как и первый вариант, но теперь Erlang проверяет, чтобы каждый элемент исходного списка подходил под указанные условия. Если элемент не подходит хотя бы под одно — он пропускается.

Но и это еще не все. Исходных списков может быть несколько. Давайте для примера напишем генератор, который вернет все возможные комбинации четных чисел от 1 до 5 и нечетных чисел от 6 до 10. Пусть комбинация будет представлена кортежем из двух элементов — парой.

В самом общем случае генератор имеет вид [Expr || Item1 . В этом случае Erlang вернет декартово произведение исходных списков (точнее их элементов, которые подойдут под условия).

Генераторы списков — очень мощный инструмент, предоставляемый нам языком. И мы будем очень часто использовать его.

Заключение

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

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

  • Глава 1: Типы данных, переменные, списки и кортежи
  • Глава 2: Модули и функции
  • Глава 3: Базовый синтаксис функций
  • Глава 4: Система типов

Коментарии

Thank you for comment!
Ваше сообщение будет доступно после проверки.

Linux.yaroslavl.ru

Регулярные выражения

Регулярное выражение представляет собой образец — шаблон — который сопоставляется со строкой. Сопоставление регулярного выражения со строкой дает либо успешный результат, либо неудачный. Иногда получение того или иного результата может быть единственной целью использования регулярного выражения, а иногда ставится задача замены совпавшего образца другой строкой.

Регулярные выражения используются многими программами, в частности, UNIX-командами, программами grep, sed, awk, ed, vi, emacs и даже различными shell. В каждой программе используется свой набор метасимволов (большей частью они совпадают). Perl — семантическое надмножество всех этих средств: любое регулярное выражение, которое можно записать в одной из подобных программ, может быть записано и на языке Perl, но не обязательно теми же символами.

Основные направления использования регулярных выражений

Если бы нам нужно было найти в каком-то файле все строки, содержащие строку abc, мы могли бы использовать команду grep:

grep abc somefile >results

В этом случае abc — регулярное выражение, которое команда grep сверяет с каждой входной строкой. Строки, соответствующие этому регулярному выражению, посылаются на стандартный вывод и попадают в файл results (так как в командной строке стоит оператор переадресации).

В Perl мы можем превратить строку abc в регулярное выражение, заключив ее между косыми:

if (/abc/) ( print $_;

Но что же сверяется с регулярным выражением abc в данном случае? Да наша старая подруга, переменная $_! Если регулярное выражение заключено между косыми (как в этом примере), то переменная $_ сверяется с регулярным выражением. Если значение переменной совпадает с регулярным выражением, операция сопоставления возвращает значение «истина». В противном случае она возвращает «ложь».

В данном примере предполагается, что переменная $_ содержит какую-то строку текста и выводится, если в любом месте этой строки обнаруживается последовательность символов abc (аналогичные действия производит приведенная выше команда grep. Однако в отличие от grep, которая оперирует всеми строками файла, данный фрагмент Perl-программы просматривает только одну строку). Чтобы обрабатывались все строки, добавьте операцию цикла:

А что, если мы не знаем, сколько символов b стоит между а и с? То есть что нужно делать, если мы хотим вывести на экран строку только в том случае, если она содержит символ а, за которым следует ни одного или более символов b и символ с? Работая с grep, мы написали бы так:

grep «ab*c» somefile >results

(Аргумент, содержащий звездочку, заключен в кавычки, потому что мы не хотим, чтобы shell обработал его так, как будто это метасимвол, встретившийся в имени файла. Чтобы звездочка сработала, ее нужно передать в grep как есть.) В Perl мы можем сделать то же самое:

if (/ab*c/) ( print $_;

Как и в grep, такая запись обозначает последовательность, содержащую символ а, ни одного или более символов b и символ с.

Другие варианты сопоставления с образцом мы рассмотрим в разделе «Еще об операции сопоставления» после того, как поговорим обо всех видах регулярных выражений.

Еще одна простая операция, в которой используются регулярные выражения, — операция замены, посредством которой часть строки, соответствующая регулярному выражению, заменяется другой строкой. Операция замены похожа на команду s UNIX-утилиты sed: она состоит из буквы s, косой черты, регулярного выражения, еще одной косой, заменяющей строки и третьей косой черты:

Переменная (в данном случае $_) сопоставляется с регулярным выражением (ab*c). Если сопоставление оказалось успешным, то соответствующая часть строки отбрасывается и заменяется строкой (def). Если сопоставление неудачно, ничего не происходит.

Позже, в разделе «Операция замены», мы рассмотрим множество опций операции замены.

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

Образцы, обозначающие один символ

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

Следующий из самых известных символов сопоставления — точка («.»). Точка обозначает любой одиночный символ, кроме символа новой строки (\п). Например, образцу /а . / соответствует любая двухбуквенная последовательность, которая начинается с буквы а и не является последовательностью «а\п».

Класс символов сопоставления задается списком символов, заключенных в квадратные скобки. Чтобы строка считалась совпавшей с образцом, в соответствующей ее части должен присутствовать один и только один из этих символов. Например, образцу

соответствует строка, содержащая любую из первых пяти строчных букв алфавита, тогда как образцу

соответствует любая из первых пяти гласных, причем как строчных, так и прописных. Если вы хотите вставить в список правую квадратную скобку (]), поставьте перед ней обратную косую или же поставьте эту скобку на первое место в списке. Диапазоны символов (например, от а до z) можно приводить в сокращенной записи, указав конечные точки диапазона через дефис (-). Чтобы включить в список дефис как таковой, поставьте перед ним обратную косую или поместите его в конец. Вот еще несколько примеров:

[0123456789] # обозначает любую цифру

[0-9] # то же самое

[0-9\-] # обозначает цифры 0-9 или знак минус

[a-z0-9] # обозначает любую строчную букву или цифру


[a-zA-ZO-9_] # обозначает любую букву, цифру или знак подчеркивания

Существует также такое понятие, как отрицание класса символов: оно обозначается знаком л , который ставится сразу же за левой скобкой. Такому классу символов соответствует любой символ, отсутствующий в этом списке. Например:

[«0-9] # обозначает любой нецифровой символ

[«aeiouAElOU] # обозначает любую негласную букву

[«\»] # обозначает любой символ, кроме символа «

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

Таблица 7.1. Предопределенные классы символов

Конструкция

Эквивалентный класс

Конструкция с отрицанием

Эквивалентный класс с отрицанием

\w (обычный символ)

\s (пробельный символ)

[0-9] [a-zA-ZO-9] [ \r\t\n\f]

\d (нецифровые символы)

\w (специальные символы)

\s (непробельный символ)

^0-9] [^a-zA-ZO-9] [» \r\t\n\f]

Образцу \d соответствует одна цифра. Образцу \w формально соответствует один обычный символ, но на самом деле ему соответствует любой символ, который допустим в именах переменных Perl. Образцу \s соответствует один пробельный символ. К пробельным символам относятся пробел, возврат каретки (редко используемый в UNIX), символ табуляции, символы перехода на новую строку и на новую страницу. Варианты конструкций с ‘использованием прописных букв соответствуют дополнениям (отрицаниям) этих классов. Так, \w обозначает один специальный символ, \s — один символ, который не является пробельным (т.е. является буквой, знаком препинания, управляющим символом и т.д.), a \D — один нецифровой символ.

Приведенные выше конструкции можно использовать при задании других классов символов:

[\da-fA-F] # соответствует одной шестнадцатеричной цифре

Образцы, обозначающие группу символов

Свою истинную силу регулярные выражения показывают, когда вам нужно сказать, например, «один и более из этих символов» или «до пяти из этих символов». Давайте посмотрим, как это делается.

Первый (и, вероятно, самый неочевидный) образец данного вида — последовательность. Например, образец abc соответствует букве а, за которой следует буква Ь, за которой идет буква с. Вроде бы просто, но название этому виду образца все равно нужно дать, чтобы в дальнейшем знать, о чем идет речь.

Мы уже встречались со звездочкой (*) в роли образца, обозначающего группу символов. Звездочка обозначает ни одного или более экземпляров стоящего непосредственно перед ней символа (или класса символов).

Есть еще два образца, работающих подобным образом: знак «плюс» (+), который обозначает один или более экземпляров стоящего непосредственно перед ним символа, и вопросительный знак (?), который обозначает ни одного или один экземпляр стоящего непосредственно перед ним символа. Например, регулярное выражение /fo+ba?r/ обозначает символ f, за которым следует один или более символов о, затем символ Ь, затем ни одного или один символ а и, наконец, символ г.

Однако все описанные выше образцы (множители) характеризуются «прожорливостью». Например, если множителю может соответствовать 5-10 символов, то каждый раз он будет выбирать десятисимвольную строку. Например,

$_ = «fred xxxxxxxxxx barney»;

всегда заменяет словом boom все символы х (что в результате дает fred boom barney), а не только один или два, несмотря на то, что более короткий набор иксов соответствовал бы этому же регулярному выражению.

Если нужно сказать «от пяти до десяти» символов х, можно поставить пять иксов, а затем еще пять, дав после каждого из последних пяти вопросительный знак. Это, однако, выглядит уродливо. Есть более простой способ — применение общего множителя. Общий множитель состоит из пары фигурных скобок, между которыми заключены одно-два числа, например /х<5,10>. Необходимо найти символ, стоящий непосредственно перед скобками (в данном случае это буква х), повторяющийся указанное число раз (в рассматриваемом случае — от пяти до десяти)*.

Если второе число не указано (например, /х <5, >/), это означает «столько или больше» (в данном случае пять и более), а если выпущена и запятая (например, /х<5>/) , это означает «ровно столько» (в данном случае пять символов х). Чтобы получить пять или менее символов х, нужно перед запятой поставить нуль: /х <0, 5>/.

Так, регулярное выражение /а . <5>b/ соответствует букве а, отделенной от буквы b любыми пятью символами, кроме символов новой строки, и все это может быть в любом месте строки. (Вспомните, что точка соответствует любому символу, кроме символа новой строки, а нам здесь нужно пять таких символов.) Эти пять символов не обязательно должны быть одинаковыми. (В следующем разделе мы увидим, как заставить их быть одинаковыми.)

Можно было бы вполне обойтись без *, + и ?, потому что эти образцы полностью эквивалентны образцам <0,>,(!,> и <0,1>, но проще ввести один эквивалентный знак препинания, к тому же это более привычно.

Если в одном выражении используются два множителя, то «правило прожорливости» дополняется правилом «чем левее, тем прожорливее». Например:

$_ = «а ххх с хххххххх с ххх d»;

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

Можно заставить любой множитель перестать быть «прожорливым» (т.е. сделать его ленивым), поставив после него вопросительный знак:

$_ = «а ххх с хххххххх с ххх d»;

Здесь а . * ? с теперь соответствует минимальному числу символов между а и с, а не максимальному. Это значит, что с образцом совпадает часть

* Конечно, /\d(3>/ соответствует не только трехзначным числам, но и любому числу с количеством знаков больше трех. Чтобы задать именно трехзначное число, нужно использовать фиксирующие точки, которые рассматриваются ниже в разделе «Фиксирующие образцы».

строки до первой буквы с, а не до второй. Такой модификатор можно ставить после любого множителя (?,+,* и ).

Что, если строка и регулярное выражение несколько изменятся, скажем, так:

$_ ° «а ххх се хххххххх ci xxx d»;

Символы .* в этом случае соответствуют максимально возможному числу символов, стоящих до следующей буквы с, но очередной символ регулярного выражения (е) не совпадает с очередным символом строки (i). В этом случае мы получаем автоматический поиск с возвратом: поиск начинается сначала и завершается остановкой в некоторой позиции до выбранной на первом этапе (в нашем случае — в позиции предыдущей с, рядом с е)*. Сложное регулярное выражение может включать множество уровней поиска с возвратом, в результате чего время выполнения значительно увеличивается. В данном случае превращение множителя в «ленивый» (с помощью вопросительного знака) упрощает задачу, которую должен выполнить Perl, поэтому рекомендуем хорошо изучить этот метод.

Круглые скобки как способ запоминания

Следующая групповая операция — пара круглых скобок, в которую заключается часть образца. При совпадении с образцом никаких изменений не происходит, просто совпавшая часть строки запоминается, и к ней можно впоследствии обращаться. Например, (а) продолжает соответствовать букве а, а ([a-z] ) — любой строчной букве.

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

соответствует строке, состоящей из слова fred, любого символа, кроме символа новой строки, слова barney и еще одного такого же символа. Таким образом, данному образцу соответствует последовательность символов fredxbarneyx, a не fredxbarneyy. Сравните это с

где два обозначенных точками символа могут быть одинаковыми или разными; роли это не играет.

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

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

то вторая часть (считая левые круглые скобки слева направо) обозначается как \2, третья — как \3 и т. д. Например,

обозначает а, какой-то символ (назовем его #1), b, еще один символ (назовем его #2), с, символ #2, d и символ #1. Таким образом, этот образец соответствует, в частности, строке axbycydx.

Запоминаемая часть может состоять не только из одного символа. Например,

обозначает а, любое количество символов (даже нуль), b, ту же последовательность символов и, наконец, с. Следовательно, этот образец совпадет со строкой aFREDbFREDc и даже со строкой abc, но не со строкой аХХЬХХХс.

Следующая групповая конструкция — дизъюнкция, т.е. а | b | с. Это значит, что данный образец соответствует только одному из указанных вариантов (в данном случае — а, b или с). Такая конструкция работает даже в том случае, если варианты содержат несколько символов, как в образце /song | blue/, что соответствует либо song, либо blue. (Для односимвольных альтернатив определенно лучше будет использовать класс символов, например, / [ abc ] /.)

Что, если бы мы хотели найти songbird или bluebird? Мы могли бы написать /songbird | bluebird/, но часть bird не хотелось бы указывать дважды. Из такой ситуации есть выход, однако вначале нам следует поговорить о приоритете группирующих образцов, который рассматривается ниже, в разделе «Приоритет».

Некоторые особые виды записи позволяют фиксировать образец относительно позиции в строке, в которой ищется соответствие. Обычно при сопоставлении образец «перемещается» по строке слева направо; сообщение о совпадении дается при первой же возможности. Фиксирующие точки позволяют гарантировать, что с образцом совпадают определенные части сравниваемой строки.

Первая пара фиксирующих директив требует, чтобы определенная часть символов, соответствующих образцу, была расположена либо на границе слова, либо не на границе слова. Фиксирующая директива \Ь требует, чтобы совпадение с образцом b происходило только на границе слова. Граница слова — это место между символами, которые соответствуют предопределенным классам \w или \w, либо между символами, которые соответствуют классу \w, а также начало или окончание строки. Отметим, что все это больше предназначено для работы с С, а не с английскими словами, но вполне применимо и к словам. Например:

/fred\b/; # соответствует слову fred, но не Frederick /\bmo/; # соответствует словам тое и mole, но не Eimo /\bFred\b/; # соответствует слову Fred, но не Frederick или alFred /\b\+\b/; # соответствует «х+у», но не «++» или » + » /abc/bdef/; # никогда не дает совпадения(границы там быть не может)

Аналогичным образом \в требует, чтобы в указанной точке границы слова не было. Например:

/\bFred\B/; # соответствует «Frederick», но не «Fred Flintstone»

Две другие фиксирующие точки требуют, чтобы определенная часть образца стояла рядом с концом строки. Символ л обозначает начало строки, если стоит в месте, где сопоставление с началом строки имеет смысл. Например, «а соответствует символу а в том и только в том случае, если а — первый символ в строке, a л соответствует двум символам, а и л , стоящим в любом месте строки. Другими словами, символ л утратил свое специальное значение. Если вы хотите, чтобы он имел буквальный смысл и в начале строки, поставьте перед ним обратную косую черту.

Символ $, как и л , фиксирует образец, но не по началу, а по концу строки. Другими словами, с$ соответствует символу с только в том случае, если он стоит в конце строки*. Знак доллара в любом другом месте образца, вероятно, будет интерпретироваться как представление скалярного значения, поэтому для того, чтобы использовать его в строке буквально, перед ним следует поставить обратную косую.

Поддерживаются и другие фиксирующие точки, включая \А, \2 и упреждающие фиксирующие точки, создаваемые с помощью комбинаций (?=. ) и (. ). Они подробно описаны в главе 2 книги Programming Perl и на man-странице perlre(Y).

Что произойдет, если объединить а | Ь*? Что будет отыскиваться — любое количество символов а или Ь или один символ а и любое количество Ь?

Групповые и фиксированные образцы, как и операции, имеют приоритет. Приоритет образцов (от высшего к низшему) приведен в таблице 7.2.


Таблица 7.2. Приоритет групповых регулярных выражений**

Наименование

Обозначение

Круглые скобки Множители Последовательность и фиксация Дизъюнкция

( ) (?: ) ? + * ?? +? *? (m,n>? abc л $ \А \Z (?= ) (?! )

* Или прямо перед символом новой строки в конце строки.

** Некоторые из этих символов в нашей книге не описываются. См. книгу Programming Perl или man-страницу perlreii(l).

Согласно этой таблице, специальный символ * имеет более высокий приоритет, чем | . В силу этого /а |Ь*/ интерпретируется как один символ а или любое число символов ь.

Что, если нам понадобится другое — например, «любое число символов а или Ь»? В этом случае нужно просто использовать пару круглых скобок. В нашем примере в скобки нужно заключить ту часть выражения, к которой должна относиться *, т.е. (а|Ь)*. Если вы хотите подчеркнуть, какое выражение вычисляется первым, можно дать избыточные круглые скобки:

Изменение приоритета с помощью круглых скобок одновременно активизирует режим запоминания для данного образца, как мы рассказывали выше. То есть эти круглые скобки учитываются, когда вы определяете, соответствует ли какой-то элемент \2, \3 и т.д. Если вы хотите использовать круглые скобки без включения режима запоминания, применяйте форму (. ), а не (. ). Она тоже позволяет указывать множители, но не изменяет значение счетчика подлежащих запоминанию лексем, используя, например, переменную $4 и т.п. Например, /(?: Fred |Wilma) Flintstone/ ничего не записывает в переменную $ 1; здесь просто предполагается группирование.

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

abc* # соответствует ab, abc, abcc, abccc, abcccc, и т.д. (abc)* # соответствует «», ab, abc, abcabc, abcabcabc, и т.д. ^х |у # соответствует х в начале строки или у в любом месте л ^x.^y) # соответствует х или у в начале строки а| be Id # либо а, либо be, либо d (alb) (с Id) # ас, ad, be или bd (song|blue)bird # songbird или bluebird

Еще об операции сопоставления

Мы уже рассматривали простейшие варианты использования операции сопоставления (регулярного выражения, заключенного между косыми). Теперь давайте изучим способы, которыми можно заставить эту операцию делать нечто иное.

Выбор другого объекта для сопоставления (операция : =’•)

Обычно строка, которую нужно сопоставить с образцом, не находится в переменной $_, и помещать ее туда довольно утомительно. (Может быть, в переменной $__ уже хранится значение, которое вам не хочется терять.) Ничего страшного — здесь нам поможет операция =

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

Эта переменная указывается справа от знака операции. Выглядит это так:

/(.)\1/; # тоже истина (соответствует двум 1)

/(.)\1/) ( t истина, поэтому проводятся дальнейшие операции

Справа от знака операции =

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

и операцией сопоставления с регулярным выражением, мы получим компактную программу проверки входных данных:

print «any last request? «;

# и чтобы это мог быть за запрос? ; # получить строку со стандартного ввода print «Sorry, I’m unable to do that.\n»;

# прошу прощения, но я не могу этого сделать )

В данном случае при помощи берется очередная строка со стандартного ввода, которая затем сразу же используется как строка, сопоставляемая с образцом л [ yY ]. Отметим, что мы не сохраняли входные данные в переменной, поэтому если мы захотим сопоставить эти данные с другим образцом или же вывести их в сообщении об ошибке, то у нас ничего не выйдет. Тем не менее эта форма часто оказывается удобной.

В предыдущем примере мы указывали образец [yY] для обозначения строчной и прописной буквы у. Если речь идет об очень коротких строках, например, у или fred, то данный способ обозначения достаточно удобен, скажем, [fF] [rR] [eE] [dD]. А что делать, если сопоставляемая строка — это слово procedure в нижнем или верхнем регистре?

В некоторых версиях grep флаг -i означает «игнорировать регистр». В Perl тоже есть такая опция. Чтобы ею воспользоваться, нужно добавить строчную i к закрывающей косой черте, т.е. написать / образец/ i. Такая запись говорит о том, что буквы образца будут соответствовать буквам строки в любом регистре. Например, чтобы найти слово procedure в любом регистре, стоящее в начале строки, запишите /^procedure/i.

Теперь наш предыдущий пример будет выглядеть так:

print «any last request? «;

Использование другого разделителя

Чтобы найти строку, которая содержит несколько косых (/), в соответствующем регулярном выражении нужно перед каждой из них поставить обратную косую черту (\). Например, чтобы найти строку, которая начинается с названия директории /usr/etc, нужно записать:

$path = ; # прочитать путевое имя (вероятно, из find?) if ($path =

# начинается с /usr/etc. >

Как видите, комбинация «обратная косая — косая» создает между элементами текста своеобразные «проходы». Если косых очень много, это занятие может стать весьма утомительным, поэтому в Perl предусмотрена возможность использования другого разделителя (delimiter). Поставьте перед любым специальным символом* (выбранным вами в качестве разделителя) букву т, укажите свой образец и дайте еще один такой же разделитель:

/»•VusrVetc/ # использование стандартного разделителя — косой черты m@^/usr/etc@ # использование в качестве разделителя символа @ m#^/usr/etc# # использование в качестве разделителя символа # # (это мой любимый символ)

Если хотите, можете опять использовать косые, например, m/fred/. Таким образом, m — общепринятое обозначение операции сопоставления с регулярным выражением, но если в качестве разделителя выбрана косая черта, то m не обязательна.

Использование интерполяции переменных

Перед тем как регулярное выражение рассматривается на предмет наличия специальных символов, в нем производится интерполяция переменных. Следовательно, регулярное выражение можно строить не только из литералов, но и из вычисляемых строк. Например:

$sentence = «Every good bird does fly.»;

print «The sentence contains the word $what!\n»;

Здесь мы использовали ссылку на переменную для построения операции сопоставления с регулярным выражением \bbird\b/.

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

Вот несколько более сложный пример:

$sentence = «Every good bird does fly.»;

print «What should I look for? «;

/$what/) ( # нашли! print «I saw $what in $sentence.\n»;

print «nope. didn’t find it.\n»;

Если вы введете слово bird, оно будет найдено, а если слово scream — не будет. Если ввести [bw] ird, результаты поиска тоже будут успешными. Это говорит о том, что квадратные скобки в данном случае воспринимаются как символы сопоставления с образцом.

Чтобы избежать этого, следует поставить перед этими символами обратную косую, которая превратит их в символы буквального сопоставления. Это кажется сложным, если в вашем распоряжении нет закавычивающей управляющей последовательности \Q:

foreach (qw(in([box] out [box] white [sox] ) ) < if (/\Q$what\E/) <

print «$_ matched!\n»;

Здесь конструкция \Q$what\E превращается в \[box\], в результате чего операция сопоставления ищет пару квадратных скобок, а не рассматривает всю конструкцию как класс символов.

Специальные переменные, защищенные от записи

После успешного сопоставления с образцом переменным $1, $2, $3 и т.д. присваиваются те же значения, что и \1, \2,\3 и т.д. Это можно использовать для поиска соответствия в последующем коде. Например:

$_ = «this is a test»;

/(\w+)\W+(\w+)/; # сопоставление первых двух слов

# $1 теперь содержит this, а $2 — is

Доступ к тем же значениям ($1, $2, $3 и т.д.) можно также получить, использовав операцию сопоставления для соответствующих списков. Если результаты сопоставления окажутся положительными, будет получен список значений от $1 до $п (где n — количество занесенных в память элементов). В противном случае значения не определены. Запишем последний пример по-другому:

$_ = «this is a test»;

($first, $second) = /(\w+)\W+(\w+)/; # сопоставление первых двух слов # $first теперь содержит this, a $second — is

К другим предопределенным защищенным от записи переменным относятся: $& (часть строки, совпавшая с регулярным выражением); $’ (часть строки, стоящая перед совпавшей частью); $ ‘ (часть строки, стоящая после совпавшей части). Например:

$_ = «this is a sample string»;

/sa.*le/; # соответствует слову sample внутри строки

# $’ теперь содержит «this is a «

# $& теперь содержит «sample»


# $’ теперь содержит «string»

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

Мы уже говорили о простейшей форме операции замены: s/ регуляр-ное_выражение/новая_строка/. Пора рассмотреть несколько разновидностей этой операции.

Если вы хотите, чтобы замена выполнялась при всех возможных совпадениях, а не только при первом, добавьте в запись, задающую проведение операции замены, букву д, например:

$_ = «foot fool buffoon»;

s/foo/bar/g; # $_ теперь содержит «bart barl bufbarn»

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

s/hello/$new/; # заменяет hello на goodbye

Символы сопоставления (метасимволы) в регулярном выражении позволяют выполнять сопоставление с образцом, а не просто с символами, трактуемыми буквально:

$_ = «this is a test»;

s/(\w+()/ /g; # $_ теперь содержит » «

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

Суффикс i (перед буквой g или после нее, если она есть) заставляет используемое в операции замены регулярное выражение игнорировать регистр, как и аналогичная опция в ранее рассмотренной нами операции сопоставления.

* О влиянии этих переменных на производительность рассказывается в книге Mastering Regular Expressions (издательство O’Reilly).

г ; Как и в операции сопоставления, можно выбрать другой разделитель, если косая черта неудобна. Для этого просто нужно использовать один символ три раза*:

s#fred#barney#; # заменить fred на barney, как в s/fred/barney/

Как и при сопоставлении, можно с помощью операции =

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

$which = «this is a test»;

s/test/quiz/; # $which теперь содержит «this is a quiz»

s/left/right/; # заменить элемент массива

s/^/x /; # поставить «х » перед элементом массива

Функции split и join

Регулярные выражения можно использовать для разбивки строки на поля. Это делает функция split. Функция join выполняет противоположное действие — вновь «склеивает» эти кусочки.

Функция split получает регулярное выражение и строку и ищет в этой строке все экземпляры указанного регулярного выражения. Те части строки, которые не совпадают с регулярным выражением, возвращаются по порядку как список значений. Вот, например, код синтаксического анализа разделенных двоеточиями полей, аналогичных тем, которые используются в UNIX-файлах /etc/passwd:

@fields = split (/:/,$line); # разбить $line, используя в качестве t разделителя двоеточие

# теперь @fields содержит («merlyn»,»»,»118″,»10″,

Обратите внимание на то, что второе пустое поле стало пустой строкой. Если вы этого не хотите, задайте сопоставление следующим образом:

Sfields = split(/:+/, $line);

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

Очень часто приходится разбивать на поля значение переменной $_, поэтому этот случай предлагается по умолчанию:

Swords = split (/ /); # то же самое, что и Swords = split(/ /, $_); *

# Или две пары, если используется символ из пары «левая-правая».

При такой разбивке соседние пробелы в разбиваемой строке вызовут появление пустых полей (пустых строк). Лучше использовать образец / +/, а лучше /\s+/, который соответствует одному и более пробельным символам. Этот образец, по сути дела, используется по умолчанию*, поэтому, если вы разбиваете переменную $_ по пробельным символам, вы можете использовать все стандартные значения и просто написать :

Swords = split; # то же самое, что и (Swords = split(/\s+/, $_) ;

Завершающие строки пустые поля в список, как правило, не включаются. Особой роли это обычно не играет. Решение вроде

# разбить $line, используя в качестве разделителя двоеточие

просто присваивает переменной $shell нулевое значение (undef), если эта строка недостаточно длинна или содержит в последнем поле пустые значения. (Разбиение выполняется так, что лишние поля просто игнорируются.)

Функция join берет список значений и «склеивает» их, ставя между элементами списка строку-связку. Выглядит это так:

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

$outline = join(«:», @fields) ;

Отметим, что строка-связка — это не регулярное выражение, а обычная строка, состоящая из символов общим числом нуль или более.

Если нужно поставить связку не между элементами, а перед каждым элементом, то достаточно такого трюка:

$result = (join «+», «», @fields);

Здесь пустая строка «» рассматривается как пустой элемент, который должен быть связан с первым элементом данных массива @fields.B результате связка помещается перед каждым элементом. Аналогичным образом можно поставить пустой элемент-связку в конец списка:

$output = join («\n», @data, «»);

* На самом деле образец по умолчанию — строка «», поэтому начальный пробельный разделитель игнорируется, но для нас вышесказанного пока достаточно.

1. Постройте регулярное выражение, которое соответствует:

а) минимум одному символу а, за которым следует любое число символов Ь;

б) любому числу обратных косых, за которым следует любое число звездочек (любое число может быть и нулем);

в) трем стоящим подряд копиям того, что содержится в переменной

г) любым пяти символам, включая символ новой строки;

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

2. а) Напишите программу, которая принимает список слов из stdin и ищет строку, содержащую все пять гласных (a,e,i,o ии). Запустите эту программу с /usr/dict/words* и посмотрите, что получится. Другими словами, введите

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

в) Модифицируйте программу так, чтобы все гласные должны были стоять в порядке возрастания, чтобы все пять гласных должны были присутствовать и чтобы перед буквой «а» не стояла буква «е», перед буквой «е» не стояла буква «i» и т.д.

3. Напишите программу, которая просматривает файл /etc/passwcf* (из stdin), выводя на экран регистрационное имя и реальное имя каждого пользователя. (Совет: с помощью функции split разбейте строку на поля, а затем с помощью sill избавьтесь от тех частей поля comment, которые стоят после первой запятой.)

4. Напишите программу, которая просматривает файл /etc/passwd (из stdin) на предмет наличия двух пользователей с одинаковыми именами и выводит эти имена. (Совет: после извлечения первого имени создайте хеш с этим именем в качестве ключа и числом его экземпляров в качестве значения. Прочитав последнюю строку stdin, ищите в этом хеше счетчики с показанием больше единицы.)

5. Повторите последнее упражнение, но с выдачей имен всех пользователей, зарегистрировавшихся под одинаковыми именами. (Совет: в хеше вместо числа экземпляров сохраните список регистрационных имен, записанных через пробелы. Затем ищите значения, содержащие пробел.)

* Словарь вашей системы может находиться не в каталоге /usr/dict/words; обратитесь к man-странице spell(l).

** Если используется NIS, то файл /etc/passwd в вашей системе будет содержать мало данных. Посмотрите, может быть, ypcat passwd даст больше информации.

Глава 10 сопоставление с образцом

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

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

Книга: Вычислительное мышление: Метод решения сложных задач

Сопоставление с образцом


Сопоставление с образцом

Умение видеть две одинаковые (или очень похожие) задачи — важный элемент вычислительного мышления, Мы все время занимаемся этим, даже не задумываясь, и специалисты постоянно используют в работе сопоставление с образцом — они узнают ситуацию и без колебаний делают то, что нужно. Этот же принцип лежит в основе многих программ: они сопоставляют правила с ситуацией и определяют, каким именно указаниям надо следовать. Программисты, создающие подобные программы, должны разработать образцы, на которые будет ориентироваться программа. Машинное самообучение тоже подразумевает сопоставление с образцом, но в этом случаи образцы подбирают сами программы.

При решении задач сопоставление с образцом помогает уменьшить объем работы, потому что при получении новой задачи позволяет не повторять одни и те же сложные операции каждый раз. Нужно найти аналогичную задачу из числа уже решенных и взять старое решение. Например, когда вы видите задачу или головоломку, связанную с составлением маршрута, нужно вспомнить о графах. Эту же мысль можно сформулировать по-другому: если вы видите, что задача соответствует модели передвижения из одной точки в другую, то для ее представления стоит использовать . Точки необязательно должны быть физически существующими местами. Например, это могут быть веб-страницы (с гиперссылками между ними), режимы будильника (с кнопочным переходом между ними), города (с перелетами из одного в другой) и так далее.

Иллюстрированный самоучитель по введению в экспертные системы

Сопоставление с образцом

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

В главе 3 мы обращали ваше внимание на то, что факты, относящиеся к состоянию окружающего мира, представляются в форме «предикат– аргумент». Тот факт, что робот находится в комнате, был представлен в модели мира формулой:

Где blah – любой символ. На языке LISP несложно разработать простой анализатор соответствия, который будет сравнивать два ординарных списка (т.е. списка, на имеющего подсписков в качестве элементов) и возвращать значение TRUE, если один из них, sample (пример), можно представить как реализацию другого – pattern (образец). Текст такой программы приведен ниже. Предполагается, что образец может иметь любую конечную длину и содержать любое количество символов универсальной подстановки.

Обращение к этой функции в выражении:

Даст результат Т, а обращение:

Даст результат NIL.

Можно усовершенствовать приведенный анализатор соответствия. Например, сделать так, чтобы он различал другой символ универсальной подстановки в качестве переменной, которой может быть присвоено значение символа, соответствие с которым анализируется. Например, образцу:

Должен соответствовать пример:

Который образуется при подстановке , как об этом говорилось в главе 3. Можно также потребовать, чтобы присвоение значений переменным было совместимым, т.е. чтобы пример:

Не соответствовал образцу:

Но, как мы видели в главе 3, главное назначение анализатора соответствия – показать, что имеющаяся в программе модель мира удовлетворяет условиям некоторого правила, которое в таком случае программа сможет затем применить. Пусть в программе имеется простое правило, утверждающее, что все объекты, находящиеся в комнате, нужно покрасить:

Нужно проверить, соответствует ли условию if (at?X room) этого правила модель мира, представленная списком:

Полученную подстановку применим затем к констатирующей части правила и получим в результате:

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

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

Глава 10 сопоставление с образцом

Регулярные выражения

Язык, созданный первоначально с главной целью — облегчить обработку большого количества отчетов, просто обязан располагать развитыми средствами для работы с текстом. Напомним, что в среде UNIX, из которой вышел язык Perl, средства для обработки текстовых строк имеются в различных утилитах: sed, awk, grep, cut. Командный интерпретатор shell, также обладающий некоторыми средствами для обработки строк, позволяет организовать совместную работу этих утилит, передавая выход одной программы на вход другой через механизм, называемый конвейером. Такой подход требует написания достаточно изощренных скриптов на языке shell в сочетании с обращением к внутренним командам утилит обработки текста sed или awk. Язык Perl, являясь средством создания программ-сценариев, в то же время один обладает всеми возможностями перечисленных утилит и даже их превосходит.

Типичная задача, возникающая при обработке текстового файла, заключается в том, чтобы найти в нем фрагмент, удовлетворяющий заданным условиям, и выполнить над ним некоторую операцию: удалить, заменить на другой фрагмент, извлечь для дальнейшего использования и т. д. Условия поиска можно достаточно просто выразить словами. Например: найти строку, содержащую слово Perl. Или: найти все фрагменты, находящиеся в конце строки и содержащие две цифры, за которыми следует произвольное количество прописных букв. Для формализованной записи подобных условий используются регулярные выражения, позволяющие описать образец или шаблон поиска при помощи специальных правил. Манипуляции с регулярными выражениями осуществляются при помощи соответствующих операций, которые мы также рассмотрим в этой главе.

Регулярное выражение, по сути, представляет собой набор правил для описания текстовых строк. Сами правила записываются в виде последовательности обычных символов и метасимволов, которая затем в качестве образца используется в операциях поиска и замены текста. Метасимволы — это символы, имеющие в регулярном выражении специальное значение. Пользователи DOS/Windows хорошо знают метасимвол *, используемый для порождения имен файлов и обозначающий любую допустимую последовательность. Регулярные выражения применяются многими программами UNIX, в том числе интерпретатором shell. Каждая из них использует свое множество метасимволов. В большинстве случаев они совпадают.

В языке Perl к Метасимволам относятся следующие символы:

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

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

Простейшее регулярное выражение состоит из одного обычного символа. Обычный символ в регулярном выражении представляет самого себя. Соответственно, последовательность обычных символов представляет саму себя и не нуждается в дополнительной интерпретации. Для использования в операциях в качестве образца регулярное выражение заключается между двумя одинаковыми символами-ограничителями. Часто в качестве ограничителя используется символ «/» (косая черта). Например, образцу /Peri/ будут соответствовать все строки, содержащие слово Perl.

Если, в регулярном выражении какой-либо метасимвол требуется использовать в буквальном, а не специальном значении, его нужно экранировать или маскировать при помощи другого метасимвола — «\». Например, образцу /\\\*/ соответствует фрагмент текста \*. Здесь первый метасимвол «\» экранирует второй метасимвол «\», а третий метасимвол «\» экранирует метасимвол «*».

Метасимвол «.» представляет любой одиночный символ, кроме символа новой строки. Так, образцу /./ будет соответствовать любая непустая строка. Если в операциях сопоставления с образцом установлен флаг s, то метасимволу «.» соответствует также и символ новой строки.

Метасимвол «[» используется в конструкции [. ] для представления любого одиночного символа из числа заключенных в скобки, т. е. он представляет класс символов. Два символа, соединенные знаком минус, задают диапазон значений, например, [A-za-z] задает все прописные и строчные буквы английского алфавита. Если первым символом в скобках является символ » ^ «, вся конструкция обозначает любой символ, не перечисленный в скобках. Например, [ ^ о-9] обозначает все нецифровые символы. Ниже мы рассмотрим и другие способы представления классов символов.

Метасимволы » ^ » и «$» используются для задания привязки к определенному месту строки. Метасимвол » ^ » в качестве первого символа регулярного выражения обозначает начало строки. Метасимвол «$» в качестве последнего символа регулярного выражения обозначает конец строки. Например, следующим образцам соответствуют:

/ ^ $/ — пустая строка (начало и конец, между которыми пусто); / ^ рег1/ — слово Perl в начале строки; /Per 1$/ —слово Perl в конце строки.

Метасимвол «|» можно рассматривать как символ операции, задающей выбор из нескольких вариантов (подобно логической операции ИЛИ). Например, образцу /а|Ь|с/ соответствует фрагмент текста, содержащий любой из символов а, Ь, с, Если вариантами выбора являются одиночные символы, как в данном примере, то лучше использовать конструкцию, определяющую класс символов, в данном случае [abc]. Но в отличие от конструкции [. ] операция «|» применима и тогда, когда вариантами выбора являются последовательности символов. Например, образцу /Word|Excel!windows/ соответствует фрагмент^текста^содержащий любое из слов Word, Excel, Windows.

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

  • r* — нуль и более повторений
  • r+— одно и более повторений
  • r? — нуль или одно повторение
  • r — ровно п повторений
  • r, — n и более повторений
  • r — минимум n, максимум m повторений r

Атомарные элементы, или атомы — это простейшие элементы, из которых строится регулярное выражение. Это не обязательно одиночный символ.

/• + / любая непустая строка;

/ [ о-9 ] <з>/ любая последовательность из трех цифр;

/\ [ +/ последовательность, состоящая из любого числа символов [.

В первых двух примерах атомом является метасимвол «.». В третьем образце в качестве атома выступает конструкция [0-9], определяющая класс цифровых символов. В четвертом образце атом — это пара символов «\[«, включающая метасимвол «\», отменяющий специальное значение следующего за ним метасимвола «[«. Полный список атомов мы приведем после изучения всех необходимых синтаксических конструкций.

Алгоритм, применяемый в операциях поиска и замены (см. ниже) для обработки регулярных выражений, содержащих множители, является «жадным»: он пытается найти для образца, снабженного множителем, максимальный сопоставимый фрагмент текста. Рассмотрим, например, что происходит при поиске в строке

«Скроен колпак не по-колпаковски, надо колпак переколпаковать» фрагмента, удовлетворяющего образцу /. * колпак/.

Алгоритм найдет максимальный фрагмент, удовлетворяющий выражению . * (вся строка без завершающего символа новой строки), затем начнет двигаться назад, отбрасывая в найденном фрагменте по одному символу, до тех пор, пока не будет достигнуто соответствие с образцом. Найденный фрагмент будет иметь вид «Скроен колпак не по-колпаковски, надо колпак переколпак».

Можно заставить алгоритм работать иначе, снабдив множитель «*» модификатором «?». В этом случае алгоритм из «жадного» превращается в «ленивый» и будет для образца, снабженного множителем, искать минимальный соответствующий фрагмент. «Ленивый» алгоритм для множителя «*?» начнет поиск в строке с пустого фрагмента «», добавляя к нему по одному символу из строки до тех пор, пока не достигнет соответствия с образцом. В этом случае найденный фрагмент будет иметь вид «Скроен колпак». Все сказанное справедливо и для других множителей. Например, в строке «1234567» будет найден:

  • для образца /\d*/ — максимальный фрагмент «1234567»;
  • для образца /\d+/ — максимальный фрагмент «1234567»;
  • для образца /\d?/ — максимальный фрагмент «1»;
  • для образца /\d<2,5>/ — максимальный фрагмент «12345»;
  • для образца /\d*?/ — минимальный фрагмент «»;
  • для образца /\d+?/ — минимальный фрагмент «1»;
  • для образца /\d??/ — минимальный фрагмент «»;
  • для образца /\d<2,5>?/ — минимальный фрагмент «12».

Символ «\», непосредственно предшествующий одному из метасимволов, отменяет специальное значение последнего. Если же «\» непосредственно предшествует обычному символу, то, напротив, такая последовательность во многих случаях приобретает специальное значение. Подобного рода последовательности будем называть метапоследователъностями. Метапоследова-тельности в регулярном выражении служат, в основном, для представления отдельных символов, их классов или определенного места в строке, дополняя и иногда дублируя/функции метасимволов. Рассмотрим существующие метапосл едовател ьности.

  • \nnrt — представляет\символ, восьмеричный код которого равен лил. Например, последовательность \120\145\162\154 представляет слово Perl (\120 — восьмеричный код буквы Р, \145 — буквы е, \1б2 — буквы г, \154- буквы!);
  • \хпп — представляет символ, шестнадцатеричный код которого равен пп. Слово Perl, например, представляется последовательностью \x50\x65\х72\хбс;
  • \сп — представляет управляющий символ, который генерируется при нажатии комбинации клавиш + , где N — символ, например, \со соответствует + ;
  • \$ — символ «$»; G \@ — символ «@»; О \% — символ «%»;
  • \а — представляет символ с десятичным ASCII-кодом 7 (звонок). При выводе производит звуковой сигнал;
  • \е — символ Esc, десятичный ASCII-код 27;
  • \f — символ перевода страницы, десятичный ASCII-код 12;
  • \п — символ новой строки, десятичный ASCII-код 10;
  • \г — символ «возврат каретки», десятичный ASCII-код 13;
  • \t — символ горизонтальной табуляции, десятичный ASCII-код 9;
  • \v — символ вертикальной табуляции, десятичный ASCII-код 11;
  • \з — представляет класс пробельных символов. К пробельным символам относятся: пробел, имвол табуляции, возврат каретки, символ новой строки и символ перевода страницы. То же самое, что и [\t,\r,\n,\fj;
  • \s — представляет класс непробельных символов, то же самое, что и класс [ л \t,\r,\n,\f];
  • \d — класс цифровых символов, то же, что и [0-9]; П \о — класс нецифровых символов, то же, что и [ Л о-9];
  • \w — представляет класс буквенно-цифровых символов, состоящий из букв, цифр и символа подчеркивания «_». То же самое, что и [a-zA-z_ o-9j. Обратите внимание, что в этот класс входят только буквы английского алфавита;
  • \w — представляет класс небуквенно-цифровых символов. То же, что и Pa-zA-Z_0-9];
  • \д — обозначает начало строки;
  • \z — обозначает конец строки;

Замечание

Последовательность \А эквивалентна метасимволу ^ в начале регулярного выражения, а последовательность \z— метасимволу $ в конце регулярного выражения, за исключением одного случая. Назовем строку, содержащую внутри себя символы новой строки (ASCII 10), мульти-строкой. Фактически муль-ти-строка состоит из отдельных строк, разделенных ограничителями — символами новой строки. При выводе мульти-строка отображается в виде нескольких строк. Если к мульти-строке применяется операция поиска или замены с опцией /т (см. ниже), то последовательности \А и \z обозначают соответственно начало и конец всей мульти-строки, а метасимволам ^ и $ соответствуют еще и границы внутренних строк, образующих мульти-строку.
  • \b — обозначает границы слова. Под словом понимается последовательность символов из класса \w. Граница слова определяется как точка между символами из класса \w и символами из класса \w;
  • \B — обозначает не-границы слова, т. е. класс символов [ Л \Ь];
  • \1 — обозначает, что следующий символ регулярного выражения преобразуется к нижнему регистру. Например, запись /\ip/ означает, что символ Р будет преобразован к нижнему регистру, после чего новый образец /р/ может быть использован в соответствующей операции поиска или замены;
  • \n — обозначает, что следующий символ регулярного выражения преобразуется к верхнему регистру;
  • \b.. .\Е — обозначает, что все символы в регулярном выражении между \ь и \Е преобразуются к нижнему регистру;
  • \n.. .\Е — обозначает, что все символы в регулярном выражении между \U и \Е преобразуются к верхнему регистру;
  • \Q. \E— обозначает, что все метасимволы в регулярном выражении между \Q и \Е экранируются при помощи символа «\». Например, запись /\0 Л *?+\Е/ эквивалентна записи /\ Л \*\?\+У;
  • \с — обозначает точку, в которой закончился предыдущий поиск m//g (см. описание операции поиска т//).

Из всех метасимволов, перечисленных в начале раздела, нам осталось рассмотреть «(» и «). Эти метасимволы служат для группирования ряда элементов, входящих в состав образца, в один элемент. Например, образцу /

Теперь мы можем перечислить «атомы», из которых строится регулярное выражение.

  • Регулярное выражение в скобках, представляющее несколько элементов, сгруппированных в один.
  • Любой обычный символ (не метасимвол).
  • Символ «.», представляющий любой одиночный символ, кроме символа новой строки.
  • Конструкция [. ], представляющая класс символов, перечисленных в квадратных скобках.
  • Метапоследовательность, представляющая символ или класс символов : \&, \n, \r, \t, \f, \e, \d, \D, \w, \w, \s, \s.
  • Метапоследовательность вида \nnn, определяющая символ при помощи его восьмеричного ASCII-кода nnn
  • Метапоследовательность вида \хnn, определяющая (символ при помощи его шестнадцатеричного ASCII-кода nn .
  • Метапоследовательность вида \сn, представляющая управляющий символ ctri-n .
  • Конструкция вида \number, представляющая обратную ссылку .
  • Любая конструкция вида \character, не имеющая специального значения, а представляющая собственно символ character, например: \*, \ у , \ь.
  • Напомним, что в регулярном выражении множители *, +, ?, применяются именно к атому, расположенному непосредственно слева.

Ранее мы установили, что группу элементов регулярного выражения можно заключить в скобки и рассматривать как один элемент. Заключение группы элементов в скобки имеет дополнительный и весьма полезный эффект. Если в результате поиска будет найден фрагмент текста, соответствующий образцу, заключенному в скобки, то этот фрагмент сохранится в специальной переменной. Внутри регулярного выражения к нему можно будет обратиться, используя запись \number, где number—номер конструкции () в исходном регулярном выражении. Запись \number, указывающую на найденный по образцу фрагмент текста, будем называть обратной ссылкой. Можно задать любое количество конструкций вида () и ссылаться на соответствующие найденные фрагменты текста, как на \i, \2 и т. д. Например, образцу /(. + ) -\1/ соответствуют слова «ха-ха», «хи-хи», «ку-ку» и т. п., а образцу /<.)(.). ?\2\1/ — все палиндромы из четырех или пяти букв. (Палиндром — слово или предложение, которое одинаково читается слева направо и справа налево.)

Внутри образца конструкция \n (n=i. 9) всегда обозначает обратную ссылку. Запись вида \пп также интерпретируется как обратная ссылка, но только в том случае, если в исходном выражении задано не менее, чем пп скобочных конструкций вида (). Иначе запись \пп обозначает символ с восьмеричным кодом nn.

Для ссылки на найденный фрагмент текста за пределами регулярного выражения, например, при задании замещающего текста в операции замены, вместо записи \number используется запись $пшпЬег. Например, операция замены

меняет местами первые два слова в строке $str.

Область действия переменных $1, $2 и т. д, распространяется до наступления одного из следующих событий: конец текущего блока; конец строки, являющейся аргументом функции evai; следующее совпадение с образцом. Аналогичным образом определяется область действия и для следующих предопределенных переменных, используемых в операциях сопоставления с образцом.

  • $& — часть строки, найденная при последней операции сопоставления с образцом.
  • $’ — часть строки, стоящая перед совпавшей частью при последней успешной операции сопоставления с образцом.
  • $’ — часть строки, стоящая после совпавшей части при последней успешной операции сопоставления с образцом.

Например, в результате выполнения операции поиска

в строке $str=»one two three» образца /two/ переменным будут присвоены следующие значения:


Эти значения будут сохраняться до наступления одного из перечисленных выше событий, и их можно использовать, например, для формирования строки с обратным порядком следования слов: $rstr=$’.$&.$». Строка $rstr будет иметь ВИД «three two one».

Следует отметить, что, если обращение к одной из переменных $&, $’, $• встречается где-либо в программе, то интерпретатор peri будет вычислять и запоминать их для каждой операции сопоставления с образцом, что, в свою очередь, замедляет выполнение всей программы. Поэтому не следует использовать данные переменные без особой необходимости.

Расширенный синтаксис регулярных выражений

Выше мы использовали скобки для группирования нескольких элементов регулярного выражения в один элемент. Побочным эффектом данной операции является запоминание найденного фрагмента текста, соответствующего образцу, заключенному в скобки, в специальной переменной. Если скобки используются только для группирования элементов регулярного выражения, то найденный фрагмент текста можно не запоминать. Для этого после открывающей скобки «(» следует поместить конструкцию «?:», например, в случае задания альтернативы / (?: pattern) /.

Конструкция относится к классу конструкций общего вида (. ), добавляющих новые возможности для задания образцов за счет расширения синтаксиса регулярного выражения, а не за счет введения новых метасимволов или метапоследовательностей. Символ, следующий за символом «?», опреде- , ляет функцию, выполняемую данной синтаксической конструкцией. В на^ стоящее время определены около десяти расширенных конструкций регулярного выражения, большая часть которых рассмотрена в данном разделе. Оставшиеся конструкции, на наш взгляд, не являются необходимыми для первоначального знакомства с языком.

Текст после символа tt и до закрывающей скобки ), комментарий, игнорируется интерпретатором и используется для добавления непосредственно в регулярное выражение.

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

Следующий фрагмент в тексте должен соответствовать образцу pattern. Обычно образец для операций поиска или замены задается при помощи регулярного выражения. Результатом операции поиска является фрагмент, соответствующий образцу, который сохраняется в специальной переменной $&. Конструкция (?=pattern) в составе регулярного выражения позволяет задать условие поиска, не включая найденный фрагмент, соответствующий образцу pattern, в результат, сохраняемый в переменной $&. Конструкция (?=pattern) в регулярном выражении задает условие, что следующий фрагмент текста должен удовлетворять образцу pattern. Обращаем внимание на слово следующий. Данная конструкция неприменима для задания условия, что предыдущий фрагмент текста должен соответствовать заданному образцу. Например, образцу /b+(?=с+)/ соответствует часть строки, состоящая из одной или более литер ь, за которыми следуют одна или более литер с, причем найденный фрагмент текста будет содержать только последовательность литер ь без последовательности литер с.

В результате операции поиска

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

$ ч — ааа $& — bbb $’ — cccddd

Если в операции поиска указать образец /b+с+/, то значения специальных переменных будут следующими:

$» — ааа $& — bbbссс $’ — ddd

В свою очередь, операция поиска по образцу / (?=b+) с+/ в нашем примере не даст результата. Данный образец задает условие, что следующий фрагмент текста должен содержать непустую последовательность литер ь. В нашей строке такой -фрагмент будет найден (это фрагмент bbb>, но не будет включен в результат поиска. Следующий фрагмент, в соответствии с образцом, должен представлять непустую последовательность литер с, но в нашем случае этого соответствия не будет, так как мы остановились перед фрагментом ььь, не включив его в результат, и поэтому следующим фрагментом будет bbb, а не ссс.

Конструкцию (?=pattern) будем называть регулярным выражением с положительным постусловием.

Конструкция (? [pattern) в регулярном выражении задает условие, что следующий фрагмент текста не должен удовлетворять образцу pattern. Найденный фрагмент не запоминается в переменной $&. Например, результат операции поиска

в рассмотренной выше строке $str будет зафиксирован в следующих значениях специальных переменных:

Найденная подстрока соответствует образцу: она состоит из двух литер ьь, за которыми не следует последовательность литер с.

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

Конструкция (? предыдущий фрагмент текста должен удовлетворять образцу pattern. Найденный фрагмент не запоминается в переменной $&. Образец pattern должен иметь фиксированную длину, т. е. не содержать множителей.

В нашем примере в результате операции поиска

значения специальных переменных будут распределены следующим образом:

Данную конструкцию назовем регулярным выражением с положительным предусловием. _/

Конструкция (? предыдущий фрагмент текста не должен удовлетворять образцу pattern. Найденный фрагмент не запоминается в переменной $&. Образец pattern должен иметь фиксированную длину, т. е. не содержать множителей.

В нашем примере в результате операции поиска

специальные переменные получат следующие значения:

$’ — aaabbbc $& — ее $’ — ddd

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

Задание флагов операции сопоставления с образцом осуществляется в самом образце. Флаги модифицируют выполнение операции и обычно являются частью синтаксиса самой операции. Расширенная конструкция (?imsx-imsx) позволяет задать флаги операции внутри самого образца. Эта возможность может быть полезной, например, в таблицах, когда разные элементы таблицы требуется по-разному сопоставлять с заданным образцом, например, некоторые элементы — с учетом регистра, другие — без учета. Допустимыми являются следующие флаги.

  • i — поиск без учета регистра;
  • dm — строка трактуется как мульти-строка, состоящая из нескольких строк, разделенных символом новой строки;
  • s — строка трактуется как одна строка, в этом случае метасимволу «.» соответствует любой одиночный символ, включая символ новой строки;
  • х — разрешается использовать в образцах пробелы и комментарии. При использовании флага х пробелы в образцах игнорируются. Признаком комментария является символ #, как и в основном тексте Peri-программы. Пробелы позволяют сделать образец более читаемым.

Одна из литер i, m, s, x после знака «-» обозначает отмену соответствующего флага.

При помощи данной расширенной конструкции можно задать, например, следующий образец

/(?ix) peri # игнорирование регистра при поиске/

Флаг i предписывает не учитывать регистр в операциях сопоставления с образцом, так что образцу будет соответствовать и слово peri, и слово Perl. Флаг х позволяет выделить слово «peri» пробелами и использовать в образце комментарий. И пробелы, и комментарий не будут учитываться в операции сопоставления с образцом.

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

  • Любой одиночный символ, не являющийся метасимволом, представляет самого себя.
  • Специальное значение метасимвола можно отменить, поместив перед ним специальный экранирующий метасимвол «\».
  • Можно определить класс символов, заключив их в квадратные скобки. Если первым после открывающей скобки «[» является символ » ^ «, то вся конструкция обозначает символы, не перечисленные в скобках. Внутри скобок два символа, соединенные знаком «-«, определяют диапазон. Чтобы включить в состав класса символ «-«, его следует поместить в начале или в конце списка, или экранировать при помощи символа «\».
  • Символы можно задавать при помощи метапоследовательностей, состоящих из символа «\», за оторым следует обычный символ или последовательность символов.
  • Альтернативный выбор задается перечислением альтернативных вариантов, разделенных символом «|». Обычно вся конструкция при этом заключается в круглые скобки.
  • Внутри регулярного выражения можно выделить подобразец, заключив его в круглые скобки. На и-ю конструкцию в скобках можно затем сослаться, используя нотацию \п внутри и $п — вне регулярного выражения.

В заключение раздела приведем в табл. 10.1 и 10.2 сводку метасимволов и метапоследовательностей, рассмотренных в данной главе.

Таблица 10.1. Символы, имеющие специальное значение у в регулярных выражениях Perl

Глава 10 сопоставление с образцом

На этом шаге мы рассмотрим реализацию задачи сопоставления с образцом .

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

Сопоставление с образцом — это процесс сравнения символьных выражений. Он является неотъемлемой частью любой развитой системы аналитических вычислений на ЭВМ.

В языке LISP в отличие, например, от Рефала [1, 2] нет встроенного механизма для работы с образцами. Однако программу, позволяющую сопоставлять достаточно сложные образцы, можно легко написать. В этом смысле говорят, что LISP является хорошим языком для реализации сопоставления образцов.

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

Ниже мы построим функцию MATCH , которая будет сопоставлять один образец и один факт [3,с.380-384].

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

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

Расширим полезные возможности функции MATCH . Предположим, что образец содержит специальный атом ? . Выделенный атом ? обладает тем свойством, что он сопоставим с любым атомом.

Обобщим функцию MATCH :

В MATCH совершается рекурсия пока текущий первый атом в образце является либо ? , либо совпадает с текущим первым атомом в факте.

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

Продолжим обобщение функции MATCH :

Переключаемое звездочкой предложение COND обеспечивает рекурсивное обращение к MATCH . Срабатывает одна из трех возможностей:

1) * ни с чем не сопоставима, в этом случае она выбрасывается и сопоставлению подвергается остальная часть образца;

2) * сопоставима с одним атомом, в этом случае отбрасывается и * , и этот атом;

3) * сопоставима с двумя или более атомами, в этом случае мы продолжаем действовать в рекурсивной манере, сохраняя * в образце, отбрасывая первые атомы, с которыми она сопоставима успешно.

Второй член в указанном предложении COND на самом деле излишен, если * может сопоставляться с любым числом атомов, включая нулевое их число. От него можно избавиться, и функция MATCH будет все равно работать. В этом случае MATCH отделяет * и сопоставляет оставшуюся часть P с нетронутым списком D или же сохраняет * и передвигается на один атом в данных в предположении, что это один из атомов, сопоставимых с * .

С другой стороны, в этой функции COND может быть опущено первое предложение, а не второе. Тогда * должна будет обязательно сопоставима, по крайней мере с одним атомом, как и определялось первоначально [3, с.383].

Следующее направление усовершенствования лежит в обобщении функции MATCH таким образом, чтобы она присваивала определенные значения, когда сопоставление проходит успешно [3, с.384-387].

Пусть атомы, P -имена которых начинаются с символов > или * , действуют как ? и * в процессе сопоставления, но в случае успеха их значениями становится то, с чем они сопоставимы. Ясно, что атомы, чьи P -имена начинаются с >, должны иметь в качестве значений атомы, тогда как атомы с P -именами, начинающимися с * , должны иметь в качестве значений списки сопоставляемых атомов. Обозначение >, использованное здесь, должно наводить на мысль о «заталкивании» значений в атомы, чьи P -имена содержат «предлог» >.

Сопоставление с > и присваивание могут быть реализованы путем использования функций ATOMCAR и ATOMCDR :

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

Переменные со * обрабатываются таким же образом , на этот раз путем присваивания им значения в виде списков атомов, которые сопоставимы с этими переменными, с использованием следующего:

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

Приведем окончательный вариант функции MATCH :

Описанная система сопоставления является простой, потому что она ориентирована на сопоставление одного списка атомов с другим. Более того, не существует представления о степени близости: либо сопоставление успешно, либо нет. Работа с сетями, фреймами или другими большими объемами знаний может оказаться намного более трудным делом, потому что возникают следующие возможности:

  • система сопоставления должна выдавать некоторый показатель по шкале, простирающейся от полного отсутствия совпадения до абсолютного совпадения;
  • система сопоставления должна работать с «более» разнообразными структурами.

Включение этих возможностей может оказаться чрезвычайно трудной задачей.

(1) Базисный Рефал и его реализация на вычислительных машинах. / ЦНИПИАСС. — М., 1977. — 238 с.
(2) Турчин В.Ф. Базисный РЕФАЛ. Описание языка и основные приемы программирования. — М.: ЦНИПИАСС, 1974. — 258 с.
(3) Уинстон П. Искусственный интеллект. — М.: Мир, 1980, с.303-512.

На следующем шаге мы смоделируем психиатра .

Илон Маск рекомендует:  Что такое код asp iiscustomlogmodule
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL