Search code examples
common-lisplexical-scope

Rebinding a Subset of Lexical Variables


Given a set of lexical variables, is it feasible to rebind a subset of them depending on circumstances at runtime. My first idea was to use #'set something like:

(let (A B C D E)
  (declare (ignorable A B C D E))
  (mapc #'set '(b e) (list 1 2))  ;(list 1 2) stands for a function call to get values
  ...)

but this only works for special variables (and is depreciated). I have come up with a solution that does work (by building a setf expression), but am reluctant to show it as it is so complex and inefficient. Is there a straightforward solution?

(ps: I appreciate this problem is perverse, but presently don't see a way to refactor around it.)


Solution

  • Maybe something like this: a CASE maps from a sym to the setter code.

    (let (a b c d e)
      (flet ((set-var (sym value)
               (macrolet ((sym-case (&rest syms)
                            `(case sym
                               ,@(mapcar (lambda (sym)
                                           `(,sym (setf ,sym value)))
                                         syms))))
                 (sym-case a b c d e))))
        (mapc #'set-var '(b e) '(1 2))
        (list a b c d e)))
    

    Result: (NIL 1 NIL NIL 2)