emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why is FUNC in cl-callf not allowed to be an expression?


From: Michael Heerdegen
Subject: Re: Why is FUNC in cl-callf not allowed to be an expression?
Date: Wed, 15 May 2019 18:38:51 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Stefan Monnier <address@hidden> writes:

> > (defmacro gv-with-place (place f)
> >   (declare (indent 1))
> >   (gv-letplace (getter setter) place
> >     (let ((v (make-symbol "v")))
> >       `(funcall ,f ,getter (lambda (,v) ,(funcall setter v))))))
>
> We could at least avoid the overall `funcall`:
>
>     (defmacro gv-with-place (val setfun place &rest body)
>       (declare (indent 3))
>       (gv-letplace (getter setter) place
>         `(let ((,val ,getter)
>                (,setfun (lambda (v) ,(funcall setter 'v))))
>            ,@body)))

Yes, or maybe even

(defmacro gv-with-place (val-sym setfun-sym place &rest body)
  (declare (indent 3))
  (gv-letplace (getter setter) place
    (let ((v (make-symbol "v")))
      `(cl-flet ((,setfun-sym (lambda (,v) ,(funcall setter v))))
         (let ((,val-sym ,getter))
           ,@body)))))

Example:

  (let ((l '(2 3 4)))
    (gv-with-place p set (cdr l)
      (unless (memq 1 p)
        (set (cons 1 p))))
    l)

  ==> (2 1 3 4)

> Along the same lines maybe we could provide a (gv-ref VAL SETFUN)
> pcase-macro, so you could do
>
>     (pcase-let (((gv-ref val setter) (gv-ref PLACE)))
>       (unless (member X val) (funcall setter (cons X val))))
>
> Even better would be if we could do
>
>     (pcase-let (((gv-ref p) (gv-ref PLACE)))
>       (unless (member X p) (setf p (cons X p))))
>
> but it seems this would require non-trivial changes to pcase (since
> basically `p` should not be bound there with a `let` but with
> a `cl-symbol-macrolet`).

I tried to implement more or less that as a normal macro:

(defun gv-ad-hoc-place (val _setter)
  (declare (compiler-macro (lambda (_) val))
           (gv-expander funcall))
  val)

(defmacro gv-do-place (place-sym place &rest body)
  (declare (indent 2))
  (gv-letplace (getter setter) place
    `(let ((val ,getter))
       (cl-symbol-macrolet ((,place-sym (gv-ad-hoc-place val ,setter)))
         ,@body))))

Example:
  (let ((l '(2 3 4)))
    (gv-do-place p (cdr l)
      (unless (memq 1 p)
        (setf p (cons 1 p))))
    l)

  ==> (2 1 3 4)

Note that `gv-synthetic-place' can't be used here because in setf it
would just expand to (setq val ...) with val being the let-bound symbol
in the implementation, instead of something setf'ing the PLACE.

> Still, I think the `gv-modify` discussed earlier hits a sweeter spot.

Is it still your favorite?


Michael.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]