emacs-devel
[Top][All Lists]
Advanced

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

Re: table.el


From: Stefan Monnier
Subject: Re: table.el
Date: Sun, 02 Dec 2001 16:16:40 -0500

> > You might want to define this idiom as a macro `with-wrapper-hook'
> I like the naming `with-wrapper-hook' since the manipulation of the
> object is done through `add-hook' and `remove-hook'.

That was the intention.

> > and you might even want to extend it to handle the local/global
> > behavior of normal hooks (i.e. if you encounter a `t' in a buffer-local
> > hook, it stands for its global value).
> 
> Could you elaborate on this?  Probably I have not used this feature
> before.

        ELISP> (defvar foo-hook nil)
        foo-hook
        ELISP> (add-hook 'foo-hook 'bar nil t)
        (bar t)
        ELISP> (default-value 'foo-hook)
        nil
        ELISP> (add-hook 'foo-hook 'baz)
        (baz)
        ELISP> foo-hook
        (bar t)
        ELISP> (default-value 'foo-hook)
        (baz)
        ELISP> 

if you (run-hooks 'foo-hook) it will run both `bar' and `baz'.

> > But I'd still advocate for passing not just the arguments but the
> > function itself so that the same wrapper-hook can be used for
> > several functions.  This is obviously a bit more difficult to do
> > since the macro doesn't know from where it's being called.
> 
> I think it is a good idea.  How about the following definition?  The
> argument to backtrace-frame depends on run-time environment.  1 is
> good when it is byte-compiled.

I think this is too brittle since it only works with byte-compilation.
Also I'm not sure what to think about inhibit-wrapper-hook: there is no
such thing for `run-hooks', so wy should it be needed for wrapper-hooks ?

How about

        (defmacro with-wrapper-hook (wrapper-form &rest body)
          (let ((wrapper-var (car wrapper-form))
                (fun-sym (make-symbol "wrapped-fun")))
            `(let ((,fun-sym
                   ;; Make the body into a function so we can pass it
                   ;; to the wrapper-hook.
                   (lambda ,(cdr wrapper-form)
                     (if ,wrapper-var
                         (let ((,wrapper-var ,wrapper-var))
                           ;; Hooks can also contain a non-list.
                           (unless (consp ,wrapper-var)
                             (setq ,wrapper-var (list ,wrapper-var)))
                           ;; Local/global special handling.
                           (when (and (local-variable-p ',wrapper-var)
                                      (eq t (car ,wrapper-var)))
                             (setq ,wrapper-var
                                   (append (default-value ',wrapper-var)
                                           (cdr ,wrapper-var))))
                           ;; Call the first wrapper, with function and args.
                           (funcall (pop ,wrapper-var)
                                    ,fun-sym ,@(cdr wrapper-form)))
                       ,@body))))
               (funcall ,fun-sym ,@(cdr wrapper-form)))))

I wish we could move some of the nastiest details into a function,
ideally into `run-hook-with-args'.

The problem with the above macro is that

        (let ((a 1))
          (with-wrapper-hook (foo-hook a)
            (setq a 2))
          a)

will return 1.

> (defmacro with-wrapper-hook (wrapper-form &rest body)
>   "Invoke wrappers in WRAPPERS-VAR if present, otherwise execute forms in 
> BODY.

I'd rather use WRAPPER-HOOK than WRAPPER-VAR since a hook is not
the same as a variable.


        Stefan




reply via email to

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