Шпора (Шпоры к первому коллоквиуму), страница 6
Описание файла
Файл "Шпора" внутри архива находится в папке "Шпоры к первому коллоквиуму". Документ из архива "Шпоры к первому коллоквиуму", который расположен в категории "". Всё это находится в предмете "искусственный интеллект" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Шпора"
Текст 6 страницы из документа "Шпора"
- S-списки (сегментные обращения к процедурам).
В языке Плэнер, как и в Лиспе, программа и обрабатываемые ею данные строятся из выражений, к которым относятся: атомы, обращения к переменным, состоящие из префикса и имени переменной (например, .X) и списки всех трех видов. Некоторые выражения (формы) можно вычислять, получая в результате значения (ими являются выражения). Программа на Плэнере представляет собой последовательность форм, ее выполнение заключается в вычислении этих форм.
В языке имеется много встроенных (стандартных) функций.
Определение новых функций
Для определения новой функции следует обратиться к встроенной функции define:
[define f dexp]
Вычисление функции define в качестве побочного эффекта приводит к появлению в программе новой функции с именем f и т.н. определяющим выражением dexp, которое должно иметь вид
(lambda (v1 v2 … vn) e) (n≥0)
где vi - формальные параметры новой функции, а e - форма, зависящая от vi.
При последующем обращении к этой новой функции
[f a1 a2 … an]
сначала вычисляются аргументы (фактические параметры) ai, затем вводятся локальные переменные vi, которым присваиваются значения соответствующих аргументов ai, и далее вычисляется форма e при этих значениях переменных vi, после чего эти переменные уничтожаются. Значение данной формы становится значением функции f при аргументах ai.
Операции над списками
[elem n l]
Значением аргумента n должно быть ненулевое целое число (обозначим его N), а значением второго аргумента - список (L) с любыми скобками. Значением функции является N-й от начала элемент списка L, если N>0, или |N|-й от конца элемент этого списка, если N<0. В случае, когда в качестве n явно указано число, имя функции в обращении можно опустить; например, [1 .X] - это сокращение от [elem 1 .X], т.е. выделяется первый от начала элемент списка, являющего значением переменной X.
[rest n l]
Значением аргумента n должно быть ненулевое целое число (N), а значением второго аргумента - список (L) с любыми скобками. Значением функции является результат отбрасывания N первых элементов списка L, если N>0, или |N|-й последних его элементов, если N<0.
[head n l]
В такой же ситуации значением функции является список из N первых элементов списка L, если N>0, или |N|-й последних его элементов, если N<0.
Пример: [rest 2 [head 5 (1 2 3 4 5 6) ] ] (3 4 5)
Если требуется вычислить список в круглых скобках
(e1 e2 … en) (n≥0)
т.е. если он рассматривается как форма, то все его элементы должны быть формами. Значением такого списка является список (с круглыми скобками) из значений его элементов. Например, если переменная X имеет значение (a b), то значением списка (.X c [-1 .X]) является список ((a b) c b).
В таких списках можно использовать сегментные формы (сегментные обращения к переменным и сегментные обращения к процедурам, <elem 5 .X>). Сегментная форма вычисляется как обычная (простая) форма, но затем у ее значения, если это список, отбрасываются внешние скобки, и полученная таким образом последовательность элементов поставляется вместо сегментной формы. Например, если переменная X имеет значение (a (b c)), то:
(5 .X ( )) (5 (a (b c)) ( )), (5 !.X ( )) (5 a (b c) ( )), (!.X !.X) (a (b c) a (b c)).
Если переменная X имеет значение (1 2), а переменная Y – значение (3 4):
(.X !.Y) ((1 2) 3 4) – на Лиспе эти действия задаются так: (cons X Y)
(!.X !.Y) (1 2 3 4) – на Лиспе эти действия задаются так: (append X Y)
Арифметические функции
[+ n1 n2 … nk] (k≥2)
Значениями аргументов должны быть числа. Результат вычисления функции – их сумма.
[- n1 n2]
Значениями обоих аргументов должны быть числа. Значение функции – их разность.
[max n1 n2 … nk] (k≥2)
Значениями аргументов должны быть числа. Результат вычисления функции – их максимум.
[min n1 n2 … nk] (k≥2)
Значениями аргументов должны быть числа. Результат вычисления функции – их минимум.
Предикаты
Предикатом называется форма, значение которой рассматривается как логическое значение «истина» или «ложь». При этом в Плэнере «ложью» считается пустой список ( ), а «истиной» – любое другое выражение (чаще всего в роли «истины» выступает атом T).
[num e]
Эта функция-предикат проверяет, является ли числом значение ее аргумента. Если да, то значение функции равно T («истина»), иначе – ( ) («ложь»).
[empty e]
Функция проверяет, является ли значение ее аргумента пустым списком (с любыми скобками). Если да, то значение функции равно T, иначе – ( ).
[eq e1 e2]
Функция сравнивает значения своих аргументов. Если они равны, то значение функции – T , иначе – ( ).
[neq e1 e2]
Аналог, но значения аргументов сравниваются на «не равно».
[memb e l]
Значением функции является номер первого вхождения формы E в список L.
[gt n1 n2], [ge n1 n2], [lt n1 n2] – сравнение, соответственно, на «больше», «больше или равно» и «меньше».
Предикаты, проверяющие состояние переменных
В Плэнере переменные (формальные параметры процедур или локальные переменные блоков) могут находиться в одном из трех состояний:
1) переменная не описана (в некоторой функции встретилась нелокальная переменная, которая не описана в динамически объемлющих процедурах/блоках),
2) переменная описана, но не имеет значения,
3) переменная описана и имеет некоторое значение.
Для анализа таких ситуаций используются предикаты: [bound v] и [hasval v].
Первый из этих предикатов проверяет, является ли значение его параметра описанной (в динамически объемлющих процедурах/блоках) переменной. Если да, возвращается значение T, иначе – ( ).
Значением аргумента предиката hasval должно быть имя переменной, существующей в данный момент. Функция проверяет, имеет ли сейчас эта переменная какое-либо значение или нет. Если имеет, то функция возвращает результат T, а иначе - результат ( ).
Функции для работы со списками свойств идентификаторов
Идентификаторы (и некоторые другие объекты) Плэнера могут иметь т.н. списки свойств – списки пар: свойство-значение. Если идентификатор является именем некоторого объекта проблемной среды (например, ящика, который может перемещаться роботом), в списке свойств могут быть указаны цвет этого ящика, его вес, линейные размеры и т.п.
Для задания списка свойств используется функция [plist i pl]. При выполнении обращения к ней идентификатор I получает список свойств PL = (ind1 val1 … indn valn). Отметим, что отсутствие некоторого свойства эквивалентно тому, что это свойство присутствует в списке со значением ( ).
Функция [put i ind val] позволяет изменить значение указанного свойства IND идентификатора I, а функция [get i ind?] – получить весь список свойств I (если параметр ind не задан), или же узнать значение указанного свойства.
Логические функции
Функции «отрицание», «конъюнкция», «дизъюнкция» и «условное выражение» аналогичны соответствующим лисп-функциям:
[not e]
[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).
Специальные функции
В Плэнере имеется более десятка т.н. специальных функций, реализующих взаимодействие с операционной средой, интерпретатором (перехват синтаксических ошибок с целью их анализа в программе пользователя), а также преобразование типов. Несколько примеров: