Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[143]

(string-append "?"

(if (number? (cadr variable))

(string-append (symbol->string (caddr variable))

"-"

(number->string (cadr variable))) (symbol->string (cadr variable))))))

4.4.4.8 Кадры и связывания

Кадры представляются как списки связываний, которые, в свою очередь, являются парами вида «переменная-значение»:

(define (make-binding variable value) (cons variable value))

(define (binding-variable binding) (car binding))

(define (binding-value binding) (cdr binding))

(define (binding-in-frame variable frame) (assoc variable frame))

(define (extend variable value frame)

(cons (make-binding variable value) frame))

Упражнение 4.71.

Хьюго Дум не понимает, почему процедуры simple-query и disjoin реализованы через явные операции delay, а не следующим образом:

(define (simple-query query-pattern frame-stream) (stream-flatmap (lambda (frame)

(stream-append (find-assertions query-pattern frame) (apply-rules query-pattern frame)))

frame-stream))

(define (disjoin disjuncts frame-stream) (if (empty-disjunction? disjuncts) the-empty-stream (interleave

(qeval (first-disjunct disjuncts) frame-stream) (disjoin (rest-disjuncts disjuncts) frame-stream))))

Можете ли Вы дать примеры запросов, с которыми эти простые определения приведут к нежелательному поведению?

Упражнение 4.72.

Почему adjoin и stream-flatmap чередуют потоки, а не просто их сцепляют? Приведите примеры, которые показывают, что чередование работает лучше. (Подсказка: зачем мы пользовались interleave в разделе 3.5.3?)


Упражнение 4.73.

Почему flatten-stream использует delay явно? Что было бы неправильно в таком определении:

(define (flatten-stream stream) (if (stream-null? stream) the-empty-stream (interleave (stream-car stream)

(flatten-stream (stream-cdr stream)))))

Упражнение 4.74.

Лиза П. Хакер предлагает использовать в negate, lisp-value и find-assertions упрощенную версию stream-flatmap. Она замечает, что в этих случаях процедура, которая отображает поток кадров, всегда порождает либо пустой поток, либо поток из одного элемента, и поэтому при слиянии этих потоков незачем использовать чередование.

a.Заполните пропущенные выражения в программе Лизы.

(define (simple-stream-flatmap proc s) (simple-flatten (stream-map proc s)))

(define (simple-flatten stream) (stream-map {??)

(stream-filter {??) stream)))

b.Если мы изменяем систему таким образом, меняется ли ее поведение? Упражнение 4.75.

Реализуйте в языке запросов новую особую форму unique. Выражение unique должно быть успешно, если в базе данных ровно одна запись, удовлетворяющая указанному запросу. Например запрос

(unique (должность ?x (компьютеры гуру)))

должен печатать одноэлементный поток

(unique (должность (Битобор Бен) (компьютеры гуру)))

поскольку Бен - единственный компьютерный гуру, а (unique (должность ?x (компьютеры программист)))

должно печатать пустой поток, поскольку программистов больше одного. Более того, (and (должность ?x ?j) (unique (должность ?anyone

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

Реализация unique состоит из двух частей. Первая заключается в том, чтобы написать процедуру, которая обрабатывает эту особую форму, а вторая в том, чтобы заставить qeval распознавать форму и вызывать ее процедуру. Вторая часть тривиальна, поскольку qeval написана в стиле программирования, управляемого данными. Если Ваша процедура называется uniquely-asserted, то нужно только написать

(put unique qeval uniquely-asserted)


и qeval будет передавать управление этой процедуре для всех запросов, у которых в type (car) стоит символ unique.

Собственно задача состоит в том, чтобы написать процедуру uniquely-asserted. В качестве входа она должна принимать contents (cdr) запроса unique и поток кадров. Для каждого кадра в потоке она должна с помощью qeval находить поток всех расширений, удовлетворяющих данному запросу. Потоки, в которых число элементов не равно одному, должны отбрасываться. Оставшиеся потоки нужно собирать в один большой поток. Он и становится результатом запроса unique. Эта процедура подобна реализации особой формы not.

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

Упражнение 4.76.

Наша реализация and в виде последовательной комбинации запросов (рисунок 4.5) изящна, но неэффективна, поскольку при обработке второго запроса приходится просматривать базу данных для каждого кадра, порожденного первым запросом. Если в базе данных N записей, а типичный запрос порождает число записей, пропорциональное N (скажем, N/k), то проход базы данных для каждого кадра, порожденного первым запросом, потребует N2/k вызовов сопоставителя. Другой подход может состоять в том, чтобы обрабатывать два подвыражения запроса and по отдельности а затем искать совместимые пары входных кадров. Если каждый запрос порождает N/k кадров, то нам придется проделать N2/k2 проверок на совместимость - в k раз меньше, чем число сопоставлений при нашем теперешнем методе.

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

Упражнение 4.77.

В разделе 4.4.3 мы видели, что выражения not и lisp-value могут заставить язык запросов выдавать «неправильные» значения, если эти фильтрующие операции применяются к кадрам с несвязанными переменными. Придумайте способ избавиться от этого недостатка. Одна из возможностей состоит в том, чтобы проводить «задержанную» фильтрацию, цепляя к кадру «обещание» провести ее, которое выполняется только тогда, когда связано достаточно переменных, чтобы операция стала возможна. Можно ждать и проводить фильтрацию только тогда, когда выполнены все остальные операции. Однако из соображений эффективности хотелось бы фильтровать как можно раньше, чтобы уменьшить число порождаемых промежуточных кадров.

Упражнение 4.78.

Перестройте язык запросов в виде недетерминистской программы, реализуемой интерпретатором из раздела 4.3, а не в виде процесса обработки потоков. При таком подходе каждый запрос будет порождать один ответ (а не поток всех возможных ответов), а пользователь может ввести try-again и получить следующий ответ. Вы увидите, что существенная часть механизмов, которые мы построили в этом разделе, заменяется недетерминистским поиском и перебором с возвратами. Однако помимо этого, Вы обнаружите, что новый язык запросов отличается в тонких деталях поведения от реализованного нами в этом разделе. Можете ли Вы привести примеры, показывающие эти отличия?



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]