Работа с последовательностями в ленивом интерпретаторе

Пабло Э. Фект, бывший программист на языке C, беспокоится, что ленивый интерпретатор не вынуждает выражения в последовательности, и оттого некоторые побочные эффекты могут никогда не произойти. Поскольку ни у одного выражения в последовательности, помимо конечного, значение не используется (выражение стоит там только ради своего эффекта, например, чтобы присвоить значение переменной или что-нибудь напечатать), у значения такого выражения не может впоследствии быть применения, для которого его потребуется вынудить (например, в качестве аргумента элементарной процедуры). Поэтому П.Э. Фект считает, что при выполнении последовательности нужно все выражения, кроме последнего, вынуждать. Он предлагает изменить eval-sequence из раздела 4.1.1 так, чтобы она использовала actual-value вместо eval :

(define (eval-sequence exps env)
  (cond ((last-exp? exps) (eval (first-exp exps) env))
        (else (actual-value (first-exp exps) env)
              (eval-sequence (rest-exps exps) env))))

а. Бен Битобор считает, что Пабло неправ. Он показывает ему процедуру for-each из упражнения 2.23 — важный пример последовательности с побочными эффектами:

(define (for-each proc items)
  (if (null? items)
      'done
      (begin (proc (car items))
             (for-each proc (cdr items)))))

Он утверждает, что интерпретатор из текста (с исходным eval-sequence ) правильно работает с этой процедурой:

;;; L-Eval input:
(for-each (lambda (x) (newline) (display x))
          (list 57 321 88))
57
321
88
;;; L-Eval value:
done

Объясните, почему Бен прав насчет поведения for-each .

б. Пабло соглашается с Беном по поводу примера с for-each , но говорит, что, предлагая изменить eval-sequence , он имел в виду другой тип программ. Он определяет в ленивом интерпретаторе следующие две процедуры:

(define (p1 x)
  (set! x (cons x '(2)))
  x)

(define (p2 x)
  (define (p e)
    e
    x)
  (p (set! x (cons x '(2)))))

Какие значения вернут (p1 1) и (p2 1) с исходной eval-sequence ? Каковы будут значения с изменением, которое предлагает Пабло?

в. Пабло указывает также, что изменение eval-sequence , которое он предлагает, не влияет на поведение примера из части a. Объясните, почему это так.

г. Как, по-Вашему, нужно работать с последовательностями в ленивом интерпретаторе? Что Вам нравится больше: подход Пабло, подход, приведенный в тексте, или что-нибудь третье?


Комментарии отсутствуют.

Необходима авторизация

Вы должны авторизоваться для создания комментария.

Вход