Exercise3-7 <---> Exercise3-9

Exercise 3.8

When we defined the evaluation model in section 1.1.13, we said that the first step in evaluating an expression is to evaluate its subexpressions. But we never specified the order in which the subexpressions should be evaluated (e.g. left to right or right to left). When we introduce assignment, the order in which the arguments to a procedure are evaluated can make a difference to the result. Define a simple procedure f such that evaluating (+ (f 0) (f 1)) will return 0 if the arguments to + are evaluated from left to right but will return 1 if the arguments are evaluated from right to left.


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


Scheme solution:

(define (one-behind start)
   ;; Returns a function that returns the previous argument
   ;; it was called with. Initially returns start.
   (let ((old start)
         (new start))
     (lambda (x)
       (set! old new)
       (set! new x)
       old)))

(define f (one-behind 0))

Yet another rather verbose solution:

(define f

  (let ((calls 0)) ;; state variable

    ;; helper function
    (define (helper res)
      (set! calls (+ calls 1))
      (if (zero? (remainder calls 2)) ;; reset counter after 2 calls
        (set! calls 0))
      res)

    ;; f's body
    (lambda (n)
      (if (zero? calls)  ;; return argument
        (helper n)       ;;   for the first call
        (helper 0)))))   ;;   and zero otherwise

;; (sum arg1 arg2) is the same as (+ arg1 arg2),
;; but arguments evaluation order is opposite to 
;; (+ ...).
;;
;; so the testing code is
;;   (+ (f 0) (f 1))
;;   (sum (f 0) (f 1))
(define-syntax sum
  (syntax-rules ()
    ((sum a b) (+ b a))))

Other solutions goes here (use "#!code haskell", "#!code ocaml", etc. for syntax highlighting)


Haskell solution:

(define (f n)
   (let ((already-called #f))
      (if (not already-called)
         (begin (set! already-called #t) n) 0))) 

Exercise3-7 <---> Exercise3-9


Comments

#!code haskell

(define (f n)

  • (let ((already-called #f))
    • (if (not already-called)
      • (begin (set! already-called #t) n) 0)))
Posted by host172 at 2009-02-03 07:10:43 X

:) :)) :( ;) :\ |) X-( B) Markup

Exercise3-8 (last edited 2009-09-10 01:52:16 by GlenKaukola)