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


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




[86]

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

Внутренняя процедура accept-action-procedure!, определенная в make-wire, требует, чтобы в момент, когда процедура-действие добавляется к проводу, она немедленно исполнялась. Объясните, зачем требуется такая инициализация. В частности, проследите работу процедуры half-adder из этого текста и скажите, как отличалась бы реакция системы, если бы accept-action-procedure! была определена как

(define (accept-action-procedure! proc)

(set! action-procedures (cons proc action-procedures)))

Реализация плана действий

Наконец, мы описываем детали структуры данных плана действий, которая хранит процедуры, предназначенные для исполнения в будущем.

План состоит из временных отрезков (time segments). Каждый временной отрезок является парой, состоящей из числа (значения времени) и очереди (см. упражнение 3.32), которая содержит процедуры, предназначенные к исполнению в этот временной отрезок.

(define (make-time-segment time queue) (cons time queue))

(define (segment-time s) (car s))

(define (segment-queue s) (cdr s))

Мы будем работать с очередями временных отрезков при помощи операций, описанных в разделе 3.3.2.

Сам по себе план действий является одномерной таблицей временных отрезков. От таблиц, описанных в разделе 3.3.3, он отличается тем, что сегменты отсортированы в порядке возрастания времени. В дополнение к этому мы храним текущее время (current time) (т. е. время последнего исполненного действия) в голове плана. Свежесозданный план не содержит временных отрезков, а его текущее время равно 0:28

(define (make-agenda) (list 0))

(define (current-time agenda) (car agenda))

(define (set-current-time! agenda time) (set-car! agenda time))

(define (segments agenda) (cdr agenda))

(define (set-segments! agenda segments) (set-cdr! agenda segments))

(define (first-segment agenda) (car (segments agenda)))

(define (rest-segments agenda) (cdr (segments agenda)))

28 Подобно таблицам из раздела 3.3.3, план действий - это список с заголовком, но, поскольку в заголовке хранится время, не нужно дополнительного заголовка-пустышки (вроде символа *table*, которым мы пользовались в таблицах).


План пуст, если в нем нет ни одного временного отрезка:

(define (empty-agenda? agenda) (null? (segments agenda)))

Для того, чтобы добавить в план новое действие, прежде всего мы проверяем, не пуст ли он. Если пуст, мы создаем для действия новый отрезок и вставляем его в план. Иначе мы просматриваем план, глядя на времена отрезков. Если мы находим отрезок с назначенным временем, мы добавляем действие к соответствующей очереди. Если же мы обнаруживаем время, большее, чем назначенное, мы вставляем новый отрезок перед текущим. Если мы доходим до конца плана, мы вставляем новый отрезок в конец.

(define (add-to-agenda! time action agenda) (define (belongs-before? segments) (or (null? segments)

(< time (segment-time (car segments))))) (define (make-new-time-segment time action) (let ((q (make-queue))) (insert-queue! q action) (make-time-segment time q))) (define (add-to-segments! segments)

(if (= (segment-time (car segments)) time)

(insert-queue! (segment-queue (car segments)) action)

(let ((rest (cdr segments))) (if (belongs-before? rest) (set-cdr! segments

(cons (make-new-time-segment time action) (cdr segments))) (add-to-segments! rest))))) (let ((segments (segments agenda))) (if (belongs-before? segments) (set-segments! agenda

(cons (make-new-time-segment time action) segments)) (add-to-segments! segments))))

Процедура, которая убирает из плана первый элемент, уничтожает элемент в начале очереди первого отрезка времени. Если в результате отрезок становится пустым, мы изымаем его из списка отрезков:29

(define (remove-first-agenda-item! agenda)

(let ((q (segment-queue (first-segment agenda)))) (delete-queue! q) (if (empty-queue? q)

(set-segments! agenda (rest-segments agenda)))))

29Обратите внимание, что в этой процедуре выражение if не имеет {альтернативы). Такие «односторонние предложения if» используются, когда требуется решить, нужно ли какое-то действие, а не выбрать одно из двух выражений. Если предикат ложен, а {альтернатива) отсутствует, значение предложения if не определено.


Первый элемент плана находится в начале очереди в первом временном отрезке. Каждый раз, когда мы обращаемся к такому элементу, мы обновляем

30

текущее время:30

(define (first-agenda-item agenda) (if (empty-agenda? agenda)

(error "План пуст - FIRST-AGENDA-ITEM") (let ((first-seg (first-segment agenda)))

(set-current-time! agenda (segment-time first-seg)) (front-queue (segment-queue first-seg)))))

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

Процедуры, предназначенные к выполнению в каждом временном отрезке, хранятся в виде очереди. Таким образом, процедуры для каждого отрезка вызываются в том же порядке, в котором они были добавлены к плану (первый пришел, первый ушел). Объясните, почему требуется использовать именно такой порядок. В частности, проследите поведение И-элемента, входы которого меняются с 0 на 1 и с 1 на 0 одновременно и скажите, как отличалось бы поведение, если бы мы хранили процедуры отрезка в обыкновенном списке, добавляя и убирая их только с головы (последний пришел, первый ушел).

3.3.5 Распространение ограничений

Традиционно компьютерные программы организованы как однонаправленные вычисления, выполняющие вычисления над указанными аргументами и получающие указанные значения. С другой стороны, часто системы приходится моделировать в виде отношений между величинами. Например, математическая модель механической структуры может включать информацию, что деформация d металлического стержня связана уравнением dAE = FL с приложенной к нему силой F, его длиной L, поперечным сечением A и модулем упругости E. Такое уравнение не является однонаправленным. Имея любые четыре величины, мы можем вычислить пятую. Однако при переводе уравнения на традиционный компьютерный язык нам придется выбрать величину, которая вычисляется на основе остальных четырех, так что процедура для вычисления площади A не может быть использована для вычисления деформации d, хотя вычисление A и d основаны на одном и том же уравнении.31

В этом разделе мы набросаем эскиз языка, который позволит нам работать в терминах самих отношений. Минимальными составляющими этого языка будут служить элементарные ограничения (primitive constraints), которые говорят, что между величинами существуют определенные связи. Например, (adder a b c) означает, что величины a, b и c должны быть связаны уравнением

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

31 Распространение ограничений появилось в системе SKETCHPAD Айвена Сазерленда (Sutherland 1963), невероятно опередившей свое время. Изящная система распространения ограничений, основанная на языке Smalltalk, была разработана Аланом Борнингом (Borning 1977) в исследовательском центре компании Xerox в Пало Альто. Сассман, Столлман и Стил применили распространение ограничений к анализу электрических цепей (Sussman and Stallman 1975; Sussman and Steele 1980). TK!Solver (Konopasek and Jayaraman 1984) представляет собой богатую среду моделирования, основанную на ограничениях.



[стр.Начало] [стр.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]