(do binds (predicate value) body)
((var-name initialize-value update-expression) ... )
(do ((var-name1 initialize-value1 update-expression1)
(var-name2 initialize-value2 update-expression2))
(predicate value)
body)
(let iter ((var-name1 initialize-value1)
(var-name2 initialize-value2))
(if predicate
value
(begin
body
(iter update-expression1 update-expression2))))
(define (do->named-let exp)
(let ((binds (cadr exp))
(predicate (caaddr exp))
(value (car (cdaddr exp)))
(body (cdddr exp)))
(let ((var-inits (map (lambda (bind) (list (car bind) (cadr bind))) binds))
(updates (map caddr binds))
(iter-name (gensym)))
`(let ,iter-name ,var-inits
(if ,predicate
,value
(begin
,@body
(,iter-name ,@updates)))))))
(define (eval-do exp env)
(eval (do->named-let exp) env))
(put 'eval 'do eval-do)
(do->named-let
'(do ((var-name1 initialize-value1 update-expression1)
(var-name2 initialize-value2 update-expression2))
(predicate value)
body))
(let fib-iter ((a 1)
(b 0)
(count n))
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(do ((a 1 (+ a b)) (b 0 a) (count 5 (- count 1)))
((= count 0) b))