Опубликован: 03.12.2012 | Доступ: свободный | Студентов: 1141 / 279 | Длительность: 16:43:00
Лекция 11:

Программирование, основанное на правилах преобразований

10.2. Шаблоны

10.2.1. Использование шаблонов в глобальных правилах преобразования

В Mathematica, согласно А.Н. Прокопене и А.В. Чичурину [5, с. 89], "шаблоном является выражение, содержащее символ подчёркивания "_"(выражение Blanc[])". С подобными выражениями мы уже встречались в предыдущей лекции, посвящённой функциональному программированию, когда учились задавать пользовательские функции.

Е. М. Воробьёв [1, с. 148] весьма точно определяет назначение шаблонов: "В принципе шаблоны используются для выделения классов выражений "Математики"".

Самый широкий класс выражений очерчивает самый простой шаблон, состоящий только из одного символа подчёркивания " _ ". Этому классу соответствуют абсолютно все выражения Mathematica.

Можно объединить в один класс выражения, обладающие определённым заголовком head: для этого задаётся шаблон вида _head. Для того чтобы задать шаблон для действительных чисел, следует записать _Real, а чтобы выделить в отдельный класс все символьные выражения — задать _Symbol.

Для того чтобы определить, относится ли то или иное выражение expr к классу данных, задаваемому некоторым шаблоном pat, следует воспользоваться функцией MatchQ[expr,pat]: она возвращает значение True, если выражение expr соответствует шаблону pat, и значение False — если не соответствует.

В примере In[1] на рис. 10.9 мы проверяем на принадлежность классу данных, задаваемых шаблоном " _ ", ряд выражений различных типов данных. Как мы видим в Out[2], все они соответствуют данному шаблону. В примере In[2] для проверки мы задаём новый шаблон вида _Complex, описывающий комплексные числа, а в In[3]_List для поиска списков.

Заголовок head не обязательно должен быть стандартным выражением Mathematica. Для иллюстрации этого факта воспользуемся примером, аналогичным приведённому в книге П. Веллина и др. [14, с. 152] — см. пример In[4] на рис. 10.9: в качестве шаблона мы задаём выражение _g, где g — заголовок неопределённой функции, а затем проверяем ряд выражений на соответствие этому шаблону.

Проверка выражений на соответствие заданным шаблонам

Рис. 10.9. Проверка выражений на соответствие заданным шаблонам

Для иллюстрации следующей особенности задания шаблонов воспользуемся примером, приведённым в работе Е. М. Воробьёва [1, с.149] — см. In[1] на рис. 10.10. Очевидно и для пользователя, и для программы, что выражение x^3 соответствует шаблону _Symbol^_Integer. В математике любое целое число (в нашем примере показатель степени 3) можно представить как сумму двух других целых чисел. Поэтому у пользователя может возникнуть предположение, что приведённое выражение должно соответствовать и шаблону _Symbol^(_Integer+_Integer). Но в этой ситуации Mathematica не согласна с пользователем, поскольку, как справедливо пишет Е. М. Воробьёв [1, с. 149], она "сравнивает внутренние полные формы выражения и шаблона, а не устанавливает их математическую эквивалентность".

Шаблоны вида " _ " и _h являются анонимными: первый, как мы уже знаем, описывает абсолютно любые выражения, а второй задаёт ограничение по заголовку выражения. Однако для большей конкретизации критериев соответствия шаблону и, соответственно, сужения класса выражений может возникнуть необходимость прибегнуть к именованным шаблонам, которые задаются в виде symb_, где symb — некоторый символ. Проиллюстрируем разницу между шаблонами _Symbol и Symbol_ в примерах In[2] и In[3] на рис. 10.10. Мы воспользовались новой функцией Cases, которая, будучи заданной в виде Cases[{expr1,expr2,…},patts], выбирает из списка выражений {expr1,expr2,…} только те, которые соответствуют шаблонам patts. В обоих примерах (In[2] и In[3]) мы предоставляем для проверки соответствия шаблонам один и тот же список выражений {g^h,g^g,h^h,h^g,f[y]^f[y]}, но получаем (в Out[2] и Out[3], соответственно) совершенно разные результаты.

В первом примере (In[2]) при отборе играют роль два ключевых критерия.

Во-первых, отбираются только те выражения, и в основании, и в показателе степени которых содержатся выражения с заголовком Symbol: именно поэтому не функцией Cases игнорируется выражение f[y]^f[y], поскольку оба заголовка есть f.

Во-вторых, совершенно не имеет значения, совпадают выражения в основании и показателе степени (g^g,h^h) или нет (g^h,h^g): в обоих случаях выражения оказываются соответствующими шаблону.

Во втором примере Symbol определяет не требуемый для соответствия заголовок, а попросту указывает на присутствие некоторого выражения, поэтому никакого несоответствия в выражении f[y]^f[y] функция Cases не находит. Однако другой критерий задаёт необходимость того, чтобы выражения в основании и показателе степени были одинаковыми, поскольку в обеих частях шаблона используется одно и то же выражение Symbol_. Именно поэтому не проходят проверку на соответствие выражения g^h и h^g, и отбираются в результирующий список выражения g^g и h^h.

Подробней о шаблонах см. книги Е. М. Воробьёва [1, с. 148–151] и П. Веллина и др. [14, с. 151–153].

Особенности задания анонимных и именованных шаблонов

Рис. 10.10. Особенности задания анонимных и именованных шаблонов

Для задания шаблонов могут использоваться выражения, содержащие два и три символа подчёркивания, — " __ " и " ___ ". Их внутренние представления имеют, соответственно, следующий вид: BlankSequence[] и BlankNullSequence[]. Таки шаблоны оказываются необходимыми и эффективными при работе со списками.

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

Выражение вида h___ (содержащее тройное подчёркивание) очерчивает класс выражений, состоящих из нуля или более выражений с заголовком h, также разделённых запятыми.

Проиллюстрируем действие шаблонов с двойным и тройным подчёркиванием на примере, аналогичном приведённому в работе П. Веллина и др. [14, с. 153–154]. Пусть мы имеем двухуровневый вложенный список {{a,b},{c},{d,e},{},{f,g,h}}, элементами которого являются списки, содержащие от нуля до трёх элементов. В примере In[1] на рис. 10.11 при помощи функции Cases мы выберем из этого списка элементы, соответствующие шаблону x_, в примере In[2] — шаблону y__, a в примере In[3] — шаблону z___. В первом примере в результирующий список Out[1] попало только одно выражение, представляющее собой список, содержащий один элемент. Во втором примере результирующий список оказался значительно шире: помимо выражения {c}, отобранного и в предыдущем примере, в него также попали списки с двумя и тремя элементами. В последнем примере результирующий список оказался полностью идентичен исходному, поскольку помимо выражений, содержащихся и в Out[2], в него попали и пустые списки {}, проигнорированные в обоих предыдущих примерах.

Подробней о шаблонах с двумя и тремя подчёркиваниями см. книги Е. М. Воробьёва [1, с. 149–150] и П. Веллина и др. [14, с. 153–156].

Использование шаблонов, содержащих двойные и тройные подчёркивания

Рис. 10.11. Использование шаблонов, содержащих двойные и тройные подчёркивания