user797257
user797257

Reputation:

Add new variable designator for setf?

I think this is possible in Common Lisp (through overloading setf), but not sure about Emacs Lisp.

What I want to do would be something like:

(setf (local variable) value)

where the form (local ...) would call some code I've written and return the symbol to use for setting its value slot.

EDIT: From looking at gv.el it seems like advising gv-get would do the job, but maybe there's a better procedure for it?

EDIT2: Tried the suggestion from Stefan, close, but not good :(

(gv-define-setter local (value varname &optional buffer)
  `(with-current-buffer (or ,buffer (current-buffer))
     (setq ,varname ,value)))

which expands to:

(let* ((v bar))
 (with-current-buffer (or nil (current-buffer))
  (setq v 42)))

Obviously, not what I wanted. I was trying to do it with advising as mentioned above and with gv-define-expander, but there's just too much quoting going on, and I can't find a way to loose the let part of the expression with the redundant substitution.

EDIT3:

OK, unless I messed something seriously in the scope or the evaluation sequence of the value the variable will be set to, this seems to work:

(gv-define-expander local
  (lambda (do &rest args)
    (let ((varname (first args))
          (buffer (or (second args) '(current-buffer)))
          (value (funcall do nil #'identity)))
      `(with-current-buffer ,buffer
         (setq ,varname ,value)))))

Upvotes: 1

Views: 299

Answers (1)

Stefan
Stefan

Reputation: 28531

There's gv-define-expander, gv-define-setter, and gv-define-simple-setter (in order of growing simplicity of use).

You might want to try the 100% guaranteed untested code (note how I pass the with-current-buffer+setq to do rather than calling do with dummy arguments, so that this things has a chance to work when used with push).

(gv-define-expander local
  (lambda (do &rest varname &optional buffer)
    (macroexp-let2 nil b buffer
      (funcall do `(buffer-local-value ',varname ,b)
               (lambda (value)
                `(with-current-buffer ,b
                   (setq ,varname ,value)))))))

Upvotes: 1

Related Questions