AI-2010 Day 05 (1156503), страница 2
Текст из файла (страница 2)
[and e1 e2 … ek] (k≥1)
[or e1 e2 … ek] (k≥1)
[cond (p1 e1,1 e1,2 … e1,k1) … (pn en,1 en,2 … en,kn)] (n≥1, ki≥1)
Блочная и связанные с ней функции
[prog (v1 v2 … vn) e1 e2 … ek] (n≥0, k≥1)
Эту функцию называют «блочной», поскольку ее вычисление напоминает выполнение блоков в других языках программирования. Вычисление функции начинается с того, что вводятся локальные переменные, перечисленные в ее первом аргументе. Если vi – идентификатор (имя), вводится локальная переменная с этим именем и без начального значения. Если же vi – пара (id val), то вводится локальная переменная с именем id и начальным значением val (выражение val при этом не вычисляется). После этого функция последовательно вычисляет остальные свои аргументы – формы ei, которые принято называть операторами. Вычислив последний из них, функция с его значением заканчивает работу, уничтожив при этом свои локальные переменные.
Вычисленные значения всех операторов (кроме последнего) нигде не запоминаются, поэтому имеет смысл в качестве таких операторов использовать только функции/операторы с побочным эффектом. Некоторые из этих функций перечислены ниже.
[set v e]
Это аналог оператора присваивания. Сначала вычисляются оба аргумента, причем значением аргумента v должно быть имя переменной, существующей в данный момент. Функция присваивает этой переменной новое значение – значение аргумента e. Это же значение является значением функции set, но оно, как правило, не используется.
[return e]
Это оператор выхода из блока. Функция return может использоваться только внутри функции prog, поскольку она завершает вычисление ближайшей объемлющей блочной функции, объявляя ее значением значение своего аргумента e.
[go e]
Это оператор перехода. Отметим, что если в качестве оператора функции prog указан идентификатор, то он трактуется как метка. Значением аргумента функции go должен быть идентификатор – одна из меток ближайшей объемлющей блочной функции. Функция go полностью завершает выполнение того оператора этой блочной функции, в который она входит (на любом уровне), и передает управление на оператор, следующий за этой меткой.
В качестве операторов можно использовать составной оператор: [do e1 e2 … ek] ( k≥1),
а также операторы цикла (loop, while, until, for). Мы рассмотрим только первый вид оператора цикла: [loop x l e1 e2 … ek]
При выполнении этого оператора вводится параметр цикла x, локализованный внутри loop, затем x поочередно получает в качестве значения очередной элемент списка L (слева направо), к которому применяются операторы e1 e2 … ek.
Пример: [set L (1 2 3))]
[prog ((R ( ))) [loop E .L [set R (.E !.R)] .R]] - описанный блок переворачивает входной список (значение переменной L), помещая в конец списка R (в начальный момент пустого) элементы L: сначала первый, затем второй, затем третий. Результатом работы prog будет значение переменной R на момент завершения цикла – список (3 2 1).
Константы
Как и в Лиспе, константами в Плэнере называются глобальные перемеенные. Они вводятся так: [cset c v] – константе с именем C присваивается V.
Функции ввода-вывода
В Плэнере имеется достаточно богатый набор функций ввода-вывода, включающий: функции для работы с файловой системой; функции ввода и вывода символов, текста, строк; функции установки цвета фона и символов, управления курсором и др.
Ниже приводится фрагмент программы, использующей некоторые средства ввода-вывода:
[open screen get] файл screen открывается на ввод
[active screen get] файл screen переводится в состояние "активный файл ввода"
[cset a [read]] считывается очередное выражение (в данном случае, набираемое на клавиатуре)
и его значение присваивается константе a; пусть это выражение – (N O T).
[cset b [rev :a]] константе b присваивается (T O N).
[open ff put] файл с именем ff открывается на вывод
[active ff put] файл ff переводится в состояние "активный файл вывода"
[print :b] в файл ff "печатается" (записывается) выражение (T O N).
Специальные функции
В Плэнере имеется более десятка т.н. специальных функций, реализующих взаимодействие с операционной средой, интерпретатором (перехват синтаксических ошибок с целью их анализа в программе пользователя), а также преобразование типов. Несколько примеров:
[catch e1 e2]
Функция вычисляет E1 и, если вычисление закончилось успешно, с этим значением заканчивает свою работу. Если же в процессе вычисления возникла ошибка, вычисляется значение второго параметра.
[exit e fn n?]
Выход из функции FN со значением E, если параметр n задан, то выход из N+1 динамически вложенных обращений к функции FN.
Частный случай – выход на верхний уровень программы: [exit ( ) ( )].
[time]
Значение функции – время от начала решения задачи.
[clock]
Дата и астрономическое время.
[atl a]
Функция преобразует идентификатор A в список составляющих его символов. Например, [atl PLAN] → (P L A N).
Образцы и сопоставители
Для анализа данных в Плэнере наряду с традиционными способами (применение функций для работы со списками, логических функций, предикатов, блоков) можно использовать:
- функцию is, реализующую сопоставление образца с выражением,
- сопоставители – особые процедуры (к которым можно обращаться только в образцах), проверяющие те или иные свойства выражения и его соответствие образцу в целом или отдельному элементу образца.
Соответствующие возможности Плэнера мы рассмотрим кратко и в основном на примерах.
Образец – выражение, которое используется как шаблон при анализе другого выражения (задает структуру и отдельные компоненты этого выражения).
Если выражение удовлетворяет требованиям шаблона, то говорят, что оно соответствует образцу, если нет, то не соответствует. В первом случае сопоставление образца с выражением удачно, во втором – неудачно.
Обращение к функции is выглядит так:
[is pat e], где pat – образец, e – выражение (сопоставление производится с E – значением e).
Алгоритм сопоставления в общем случае сложен, он предполагает возвраты. Важно, что удачное сопоставление может сопровождаться побочными эффектами – переменным, входящим в состав образца могут присваиваться в качестве значений соответствующие фрагменты выражения. Это позволяет резко сократить запись сложных действий по анализу данных и выделению важных для работы фрагментов.
Примеры (считаем, что используемые переменные описаны вне обращений к is, например, в каком- то объемлющем блоке):
[is (*X .X) (b b)] T - сопоставление удачно, X (побочный эффект) получает значение b
отметим, что при сопоставлении первого элемента образца (*X) с
первым элементом выражения (b) переменная X получила значение b;
второй элемент образца (.X) требует, чтобы рассматривалось текущее
значение переменной X (префикс точка), т.е. как раз b; поэтому
удачным будет и сопоставление второго элемента образца со вторым
элементом выражения.
[is (*X .X) (b (b))] ( ) - сопоставление неудачно;
[is (*X !*Y) (1 2 3)] T - сопоставление удачно; X:= 1, Y:= (2 3)
[is (*X *Y) (1 2 3)] ( ) - сопоставление неудачно (образец описывает список длиной два).
Обращение к сопоставителю внешне выглядит как обращение к функции. Однако: значение не вырабатывается, проверяется соответствие выражения/подвыражения образцу/элементу образца, фактические параметры (аргументы) обычно уточняют вид проверки.
Пример: [list n] - сопоставитель, соответствующий списку из N элементов
[is [list 2] (a b)] T - сопоставление удачно;
[is [list 2] (a b c)] ( ) - сопоставление неудачно;
[is (a <list 2> a) (a b b a)] T - сопоставление удачно (сегмент b b соответствует сегментному
обращению к сопоставителю list;
[is (a [list 2] a) (a (b b) a)] T - сопоставление удачно.
В Плэнере есть около 30 встроенных сопоставителей, в том числе: логические (типа and и or), типа сond, типа prog (вводят локальные переменные).
Сопоставитель [ ] соответствует любому выражению, сопоставитель < > - любому сегменту.
Некоторые встроенные сопоставители
Сопоставители (без параметров): id (идентификатор), num (число), var. (обращение к переменной с префиксом "."), var*, var:, var!., var!*, var!:, atomic (атомарное выражение) – проверяют тип выражения.
[aut pat1 … patn] – сопоставитель "ИЛИ"; сопоставление с некоторым выражением успешно, если выражение соответствует одному из указанных образцов.
[et pat1 … patn] – сопоставитель "И"; сопоставление с некоторым выражением успешно, если выражение соответствует каждому из указанных образцов.
[when pat1 pat1,1 pat1,2 … pat1,k1) … (patn patn,1 patn,2 … patn,kn)] – "УСЛОВНЫЙ" сопоставитель; если выражение соответствует образцу pati, то применяется сопоставитель [et pati,1 pati,2 … pati,ki].
[star pat] – сопоставитель соответствует списку, каждый элемент (верхнего уровня) которого соответствует образцу pat.
Определение новых сопоставителей
[define <имя> (kappa <список параметров> pat)]
Пример:
[define pal (kappa ( )
[aut ( ) [list 1] [same (X) (*X <pal> .X)]])]
- рекурсивный сопоставитель pal соответствует любому списку-палиндрому; в нем использованы: логический сопоставитель aut (аналог or), известный нам сопоставитель list, сопоставитель-блок same (вводящий локальную переменную X). Сопоставитель pal проверяет (последовательно): не является ли выражение пустым списком; списком длиной 1; списком, первый и последний элементы которого совпадают, а «середина» удовлетворяет требованиям pal.
12
Программное обеспечение работ по ИИ