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


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




[142]

Процедуры stream-append-delayed и interleave-delayed подобны stream-append и interleave (раздел 3.5.3), но только они принимают задержанный аргумент (как процедура integral из раздела 3.5.4). В некоторых случаях это откладывает зацикливание (см. упражнение 4.71).

(define (stream-append-delayed si delayed-s2) (if (stream-null? si) (force delayed-s2) (cons-stream (stream-car si)

(stream-append-delayed (stream-cdr si) delayed-s2))))

(define (interleave-delayed si delayed-s2) (if (stream-null? si) (force delayed-s2) (cons-stream (stream-car si)

(interleave-delayed (force delayed-s2)

(delay (stream-cdr si))))))

Процедура stream-flatmap, которая многократно используется в интерпретаторе, чтобы применить процедуру ко всем элементам потока кадров и соединить получающиеся потоки кадров, является потоковым аналогом процедуры flatmap для обычных списков, введенной в разделе 2.2.3. Однако, в отличие от обычного flatmap, потоки мы собираем с помощью чередующего процесса, а не просто сцепляем их (см. упражнения 4.72 и 4.73).

(define (stream-flatmap proc s)

(flatten-stream (stream-map proc s)))

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

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

Кроме того, интерпретатор пользуется следующей простой процедурой для порождения потока, который состоит из одного элемента:

(define (singleton-stream x)

(cons-stream x the-empty-stream))

4.4.4.7 Процедуры, определяющие синтаксис запросов

Процедуры type и contents, используемые в qeval (раздел 4.4.4.2), указывают, что особая форма определяется символом в ее car. Это те же процедуры, что type-tag и contents из раздела 2.4.2, с точностью до сообщения об ошибке.

(define (type exp) (if (pair? exp) (car exp)

(error "Неизвестное выражение TYPE" exp)))


(define (contents exp) (if (pair? exp) (cdr exp)

(error "Неизвестное выражение CONTENTS" exp)))

Следующие процедуры, вызываемые из query-driver-loop (раздел 4.4.4.1), указывают, что утверждения и правила добавляются в базу данных при помощи выражений вида (assert! (правило-или-утверждение)):

(define (assertion-to-be-added? exp) (eq? (type exp) assert!))

(define (add-assertion-body exp) (car (contents exp)))

Вот синтаксические определения для особых форм and, or, not и lisp-value (раздел 4.4.4.2):

(define (empty-conjunction? exps) (null? exps)) (define (first-conjunct exps) (car exps)) (define (rest-conjuncts exps) (cdr exps))

(define (empty-disjunction? exps) (null? exps)) (define (first-disjunct exps) (car exps)) (define (rest-disjuncts exps) (cdr exps))

(define (negated-query exps) (car exps))

(define (predicate exps) (car exps)) (define (args exps) (cdr exps))

Следующие три процедуры определяют синтаксис правил:

(define (rule? statement)

(tagged-list? statement rule))

(define (conclusion rule) (cadr rule))

(define (rule-body rule)

(if (null? (cddr rule))

(always-true) (caddr rule)))

Query-driver-loop (раздел 4.4.4.1) вызывает query-syntax-process,

чтобы преобразовать переменные образца в выражении, имеющие форму ?sym-bol, к внутреннему формату (? symbol) . Это означает, что образец вроде (должность ?x ?y) на самом деле представляется внутри системы как (должность (? x) (? y)). Это повышает эффективность обработки запросов, потому что позволяет системе проверять, является ли выражение переменной, путем проверки car (не является ли car символом ?), вместо того, чтобы извлекать из символа буквы. Преобразование синтаксиса осуществляется следующей процедурой: °

81 Большинство Лисп-систем позволяет пользователю изменять обыкновенную процедуру read и осуществлять такие преобразования путем определения макросимволов ввода (reader macro


(define (query-syntax-process exp)

(map-over-symbols expand-question-mark exp))

(define (map-over-symbols proc exp) (cond ((pair? exp)

(cons (map-over-symbols proc (car exp))

(map-over-symbols proc (cdr exp)))) ((symbol? exp) (proc exp)) (else exp)))

(define (expand-question-mark symbol) (let ((chars (symbol->string symbol))) (if (string=? (substring chars 0 1) "?")

(list ?

(string->symbol (substring chars i (string-length chars)))) symbol)))

После того, как переменные таким образом преобразованы, переменные в образцах - это списки, начинающиеся с ?, а константные символы (которые требуется распознавать для индексирования базы данных, раздел 4.4.4.5) - это просто символы.

(define (var? exp)

(tagged-list? exp ?))

(define (constant-symbol? exp) (symbol? exp))

Во время применения правил при помощи следующих процедур порождаются уникальные переменные (раздел 4.4.4.4). Уникальным идентификатором правила служит число, которое увеличивается при каждом применении правила:

(define rule-counter 0)

(define (new-rule-application-id)

(set! rule-counter (+ 1 rule-counter)) rule-counter)

(define (make-new-variable var rule-application-id) (cons ? (cons rule-application-id (cdr var))))

Когда query-driver-loop конкретизирует запрос для печати ответа, она преобразует все несвязанные переменные запроса обратно к печатной форме при помощи

(define (contract-question-mark variable) (string->symbol

characters). Закавыченные выражения уже обрабатываются таким образом: процедура чтения автоматически переводит expression в (quote expression), прежде чем выражение видит интерпретатор. Можно было бы устроить преобразование ?expression в (? expression) таким же образом; однако ради большей ясности мы здесь представили процедуру преобразования явно.

Expand-question-mark и contract-question-mark используют несколько процедур, имя которых содержит string. Это примитивы языка Scheme.



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