"Maciek Godek" <[EMAIL PROTECTED]> writes: > Hi, > I've been trying to write a function or macro that > would work like this: > > (let ((a 0)(b 0)) > (set-pair! '(a . b) '(1 . 2)) > (cons a b)) ; => (1 . 2) > > I eventually wrote: > > (define (set-pair! pair values) > (let ( (e (the-environment)) (a (car pair)) (d (cdr pair)) ) > (local-eval > `(begin > (set! ,a ,(car values)) > (set! ,d ,(cdr values))) > e))) > > but it seems to work only for symbols defined in > global scope. Does anyone know how to implement > this form properly?
You should use a macro instead... something like: (define-macro (mset! . forms) `(begin ,@(let mset-loop ((unprocessed-forms forms) (processed-forms '())) (cond ((null? unprocessed-forms) (reverse! processed-forms)) (else (mset-loop (cddr unprocessed-forms) (cons `(set! ,(car unprocessed-forms) ,(cadr unprocessed-forms)) processed-forms))))))) (let ((a 0) (b 0)) (mset! a 1 b 2) ; => (begin (set! a 1) (set! b 2)) (cons a b)) ; => (1 . 2) The syntax for mset! is the same as Common Lisp's setf[0]. You can easily adjust it to take the form (mset! (variables) (values)) if you really wanted. The macro version will interact properly with the local environment, and still work whenever local-eval is removed. Whenever you think you need local-eval you probably need a macro. Destructively modifying environments at runtime is heavily discouraged, and more or less deprecated (Guile acros and macros are deprecated in favor of mmacros for a reason--runtime modification of lexical environments is incompatible with a properly phase-separated compiler). [0] http://www.lispworks.com/documentation/HyperSpec/Body/m_setf_.htm -- Danielle: well road signs were pissing me off Danielle: I took one of them out, but the other haven't followed as planned