Решение упражнения 2.57 из SICP
Как требуется в условии упражнения, будем менять только конструкторы и селекторы для суммы и произведения так, чтобы сделать возможной работу с произвольным числом слагаемых и множителей. Начнем с суммы.
Мы будем представлять сумму как список из символа + и последующего произвольного количества слагаемых.
Селектор addend вообще не меняется:
(define (addend s) (cadr s))
Селектор augend будет возвращать либо одно последнее слагаемое, если слагаемых было всего два, либо сумму всех слагаемых, начиная со второго:
(define (make-sum-list seq) (if (null? (cdr seq)) (car seq) (cons '+ seq)))
(define (augend s) (make-sum-list (cddr s)))
Процедура make-sum-list вынесена специально, так как она нам еще понадобится.
При построении суммы с помощью make-sum мы будем делить все слагаемые на две группы: числа (константы), которые будen сразу суммироваться в число const, и выражения (с переменные значениями), которые будут накапливаться в списке vars. Затем в зависимости от результирующих значений мы будем их комбинировать для получения окончательного результата. Определение выглядит так:
(define (make-sum . seq) (let ((vars (filter non-number? seq)) (const (accumulate + 0 (filter number? seq)))) (cond ((null? vars) const) ((= 0 const) (make-sum-list vars)) (else (make-sum-list (cons const vars))))))
Абсолютно аналогичные построения можно проделать и для произведения:
(define (multiplier p) (cadr p))
(define (make-product-list seq) (if (null? (cdr seq)) (car seq) (cons '* seq)))
(define (multiplicand p) (make-product-list (cddr s)))
(define (make-product . seq) (let ((vars (filter non-number? seq)) (const (accumulate * 1 (filter number? seq)))) (cond ((null? vars) const) ((= 0 const) 0) ((= 1 const) (make-product-list vars)) (else (make-product-list (cons const vars))))))
Попробуем вычислить производную из условия упражнения:
> (deriv '(* x y (+ x 3)) 'x) (+ (* x y) (* y (+ x 3)))
Результат ожидаемый.
Comments
Comment from qMax
Date: January 25, 2009, 4:06 am
логика работы вcтроенных операторов + и * подсказывает, что
(make-sum-list ‘()) => 0
(make-prod-list ‘()) => 1
Write a comment