"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


Reply via email to