I'm currently writing metacircular evaluator in Scheme, following the SICP book's steps.
In the exercise I am asked to implement letrec
, which I do in the following way:
(define (letrec->let exp)
(define (make-unassigned var)
(list var '*unassigned*))
(define (make-assign binding)
(list 'set! (letrec-binding-var binding)
(letrec-binding-val binding)))
(let ((orig-bindings (letrec-bindings exp)))
(make-let
(map make-unassigned
(map letrec-binding-var orig-bindings))
(sequence->exp
(append
(map make-assign orig-bindings)
(letrec-body exp))))))
However, when I evaluate the expression as follows, it goes into infinite loop:
(letrec
((a (lambda () 1)))
(+ 1 (a)))
Do I miss anything?
I checked result transformation result of
(let ((x 1)) x)
and got:((lambda (x) (x)) 1)
instead of:
((lambda (x) x) 1)
obviously problem is in
let
body processing. If I were you, I would use utility function:By the way: I would say, that your
letrec
implementation is not very correct. Your transformation returns:It much more resembles
letrec*
which evaluates expressions for variable bindings in left-ro-right order (Scheme itself doesn't specify arguments evaluation order):The more correct code would be: