with-slots

Das Macro with-slots erwartet drei Argumente. Nur das erste Argument wird nicht ausgewertet. Das erste Argument ist eine Liste von Namen von Instanzvariablen. Das zweite Argument ist eine Instanz. Das dritte Argument ist ein Ausdruck, der innerhalb einer Umgebung ausgewertet wird, in der die Namen der Instanzvariablen ihrem Wert in der Instanz zugeordnet sind. Werden diese Werte geändert, werden die Änderungen in die Instanz übernommen:

> (defclass thing ())
> (setq something (allocate-instance thing))
> (assignq something x 1)
> (assignq something y 2)
> (with-slots (x y) something (list x y))
(1 2)
> (with-slots (x y) something (setq x 2))
2
> (slot-value something (quote x))
2

Eine Variante von with-slots ist with-slots-read-only. Bei der Variante werden geänderte Werte nicht zurück in die Instanz übernommen.

Das Macro with-slots basiert im Wesentlichen auf let, slot-value und assignq:

(setq with-slots
  (mlambda args
    (let
      ((slots (first args))
       (instance (second args)))
      (list
        let
        (map-with
          (lambda (slot)
            (list
              slot
              (list
                slot-value
                instance
                (list quote slot))))
          slots)
        (cons
          prog1
          (cons
            (third args)
            (map-with
              (lambda (slot)
                (list
                  or
                  (list
                    equal?
                    slot
                    (list
                      slot-value
                      instance
                      (list quote slot)))
                  (list
                    assignq
                    (second args)
                    slot
                    slot)))
              slots)))))))