This question is similar in scope to: In R6RS Scheme, is there a way to get the current environment for use with eval? but I'd like to take it a step further and ask how you'd remedy something like this.
My issue is further confounded in that in my case '(+ x y)
is an arbitrary unevaluated lambda statement. Unevaluated because it may contain calls to variables that are part of the let (and since Scheme doesn't have faith that the procedure will be called in an environment containing those variables when the current one does not, it fires off an undefined identifier error). So the question becomes: how can I restructure my code, such that this scoping nightmare is no longer an issue? I'd like to still be able to use the environment variables from the let whenever the lambda is called.
I'm using Pretty Big
The intent is to create classes in Scheme. My approach so far is pretty big (no pun intended) but looks like:
(define (dispatch msg methods args)
(if (null? methods) (display "Method signature not found.")
(let (
(m-name (caar methods))
(m-args (cadar methods))
(m-body (caddar methods)))
(if (and (eq? msg (caar methods)) (eq? (length args) (length (cadar methods))))
`(lambda ,m-args ,m-body)
(dispatch msg (cdr methods) args)))))
(define (build-lets c-def)
(let (
(i-vars (cadr c-def))
(meths (caddr c-def)))
(eval `(append ',i-vars (list (list 'methods '',meths))))))
(define (new c-def . args)
(apply (eval `(lambda ,(map cadr (cadr c-def))
(let* ,(build-lets c-def)
(lambda (msg . args)
(letrec ((meth (dispatch msg methods args)))
(apply meth args))))))
args))
Where c-def is a class def of the form (say for a point)
'(();Name of parent
((yvalue y) (xvalue x)) ;Instance variables: (i-var constructor-arg)
((getx () xvalue) ;Methods, ((name args body) ...)
(setx (x) (set! xvalue x)))))