суббота, 8 января 2011 г.

Exercise-3-08

Упражнение 3.8.
Когда в разделе 1.1.3 мы определяли модель вычислений, мы сказали, что первым шагом при вычислении выражения является вычисление его подвыражений. Однако мы нигде не указали порядок, в котором проходит вычисление подвыражений (слева направо или справа налево). Когда мы вводим присваивание, порядок, в котором вычисляются аргументы процедуры, может повлиять на результат. Определите простую процедуру f, так, чтобы вычисление (+ (f 0) (f 1)) возвращало 0, если аргументы + вычисляются слева направо, и 1, если они вычисляются справа налево.

Вопрос может показаться не существенным, но в таком языке как С++ порядок вызова для такого случая не определен и программа (теоретически) может вести себе по разному от выполнения к выполнении.  После этого упражнения мы должны сделать вывод что писать программы зависящие от описываемого порядко не хорошо) Приступим к выполнению

Определим функцию, которая при нечетных вызовах (первый, третий и тд раз) возвращает параметр, а при четных (второй, четвертый и тд) возвращает 0. Это можно сделать множеством способов. Вот один из них

(define f
  (let ((trigger false))
    (λ (a)
      (set! trigger (not trigger))
       (if trigger a 0))))

Проводим эксперимент
 (+ (f 0) (f 1)) ;0

Как видим, аргументы вычисляются слева направо.
Можно обобщить это наблюдение для большего количества аргументов

(define f
  (let ((counter 0))
    (λ (a)
      (set! counter (+ counter 1))
       counter)))

(define (foo first . rest)
  (cons first rest))

(foo (f 100) (f 100) (f 100) (f 100) (f 100) (f 100) (f 100) (f 100))

где возвращает какой раз ее вызывают

Комментариев нет:

Отправить комментарий