Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Spec_Mov_3k_4k_Lect.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
1.46 Mб
Скачать

Переменные в образцах

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

  • (?> x) – переменная х сопоставляется с произвольным элементом образа,

  • (+> x) – переменная х сопоставляется с непустым сегментом образа,

  • (*> x) – переменная х сопоставляется с пустым или непустым сегментом образа.

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

Пример

(match1 '((?> x) or (+> y)) '(before or after afternoon)) -> ((x.before)(y after afternoon))

(match1 '(? or *) '(before or after afternoon)) -> t

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

(defun match1 (m h &optional (pairs nil)

(cond

((null m) (if (null h) (if pairs pairs t) nil)) ;; успеш.завершение сопоставления

((null h) nil) ;; неуспех сопоставления

((equal (car m) (car h)) (match1 (cdr m) (cdr h) pairs)

((atom (car m)) ;;простой сопоставитель

(if (get (car m) 'matcher)

(funcall (get (car m) 'matcher) m h pairs)

nil)

)

(t ;; сопоставление с переменной

(funcall (get (first (car m)) 'matcher) m h (second (car m)) pairs))

)

)

Функции first и second вычисляют первый и второй элементы списка-аргумента. В реализации функции match1 предполагается, что теперь простые сопоставители получают на вход дополнительный аргумент, - список пар, поскольку его необходимо передавать дальше в рекурсивных вызовах функции match1. Функции, реализующие сопоставление с переменными в качестве 3-го аргумента получают на вход имя переменной, с которой выполняется сопоставление. Т.о., имеем следующие определения для простых сопоставителей:

(setf (get '? 'matcher) '(lambda (m h pairs) (match1 (cdr m) (cdr h) pairs)))

(setf (get '+ 'matcher) '(lambda (m h pairs) (or (match1 (cdr m) (cdr h) pairs)

(match1 m (cdr h) pairs))

)

)

(setf (get '* 'matcher) '(lambda (m h pairs) (or (match1 (cdr m) (cdr h) pairs)

(match1 (cdr m) h pairs)

(match1 m (cdr h) pairs))

)

)

В данной реализации следует учесть то, что системная функция or возвращает в ч качестве результата значение 1-го из своих аргументов, отличающееся от nil. Если все аргументы имеют значение nil, то возвращаемый результат – nil.

Для сопоставителей с переменными определения будут следующими:

(setf (get '?> 'matcher) '(lambda (m h v pairs)

(match1 (cdr m) (cdr h) (acons v (car h) pairs))))

Функция acons добавляет точечную пару (ключ.значение) в начало списка, который указывается в качестве 3-го аргумента.

(setf (get '+> 'matcher) '(lambda (m h v pairs)

(or (match1 (cdr m) (cdr h) (toadd v (car h) pairs))

(match1 m (cdr h) (toadd v (car h) pairs))

))

)

(setf (get '*> 'matcher) '(lambda (m h v pairs)

(or (match1 (cdr m) (cdr h) (toadd v (car h) pairs))

(match1 m (cdr h) (toadd v (car h) pairs))

(match1 (cdr m) h pairs)

)))

Функция toadd образует новую пару в списке сопоставлений переменных или обновляет старую связь символьной переменной.

(defun toadd (n val pairs)

(cond

((null pairs) (acons n val nil))

((eql n (caar pairs))

(if (atom (cdar pairs))

(acons n (list (cdar pairs) val) (cdr pairs))

(acons n (append (cdar pairs) (list val)) (cdr pairs)))

)

(t (cons (car pairs) (toadd n val (cdr pairs))))

)

)

Значение, связанное с переменной в списке (pairs)можно в дальнейшем использовать в процессе сопоставления. Для того, чтобы иметь возможность ссылаться на значение ранее сопоставленной переменной можно ввести еще одну форму образца – (< x), где x – имя переменной. Естественно, что это требует определения еще одного сопоставителя, который при распознавании вышеуказанной формы в образце, будет обращаться к списку сопоставленных переменных и сравнивать выбранное значение с текущим атомом или сегментом образа.

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