emacs-devel
[Top][All Lists]
Advanced

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

Re: A combination of defmacro, functionp, and quoted lambdas yields diff


From: Clément Pit-Claudel
Subject: Re: A combination of defmacro, functionp, and quoted lambdas yields different results on consecutive evaluations
Date: Wed, 28 Feb 2018 09:32:27 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0

On 2018-02-26 12:31, Stefan Monnier wrote:
>> Is that actually a usable criterion?  Any macro can quote or unquote its
>> argument, right?
> 
> Everything can happen, indeed.  But usually a macro which takes a code
> argument and puts it within a quote is perceived as a problem: e.g. it
> tends to very quickly annoy its users because they can't refer to
> lexically-scoped arguments any more.  Admittedly, for
> with-eval-after-load this is not very problematic because it's unusual
> to have with-eval-after-load elsewhere than at top-level, so making code
> like:
> 
>     (let ((x 1))
>       (with-eval-after-load FOO
>         (message "%S" x)))
> 
> work correctly is not nearly as important as it is for many other macros.

Thanks, this is a good point, which I hadn't considered.
It's not obvious to me, however, which one is more important: make something 
like 

  (with-eval-after-load 'flycheck
    (flycheck-define-checker …))

work, or ensuring that with-eval-after-load can be used to capture lexical 
variables.

One of the issues to consider is that the usual fix of (require)-ing — or 
(require-when-compile)-ing — the package that defines the macro isn't 
satisfactory in this case, since with-eval-after-load is used to run code 
*after* the package is loaded.  And, since eval-when-compile now behaves the 
same way, there doesn't seem to be a user-friendly way at the moment to delay 
the execution a bit of code that includes macros until these macros are 
available.

Btw, autoloading these macros wouldn't fix this, right?

>> For example, the problem that I described about with-eval-after-load
>> also happens with eval-after-load, yet the argument to that is quoted.
> 
> [ I was wondering when someone would notice.  ]
> 
> Indeed, when I introduced `with-eval-after-load` and I also changed
> `eval-after-load` by adding a compiler macro which turns
> 
>      (eval-after-load FOO 'BAR)
> into
>      (eval-after-load FOO `(,(lambda () BAR)))
> 
> so that BAR can be properly eagerly macro-expanded, so the
> byte-compiler can look at BAR and emit warnings about it, 

That makes sense, but it also has high rates of false positives; writing the 
following warns on foo-x:

  (eval-after-load 'foo
    '(setq foo-x 1))

… regardless f whether `foo' defines `foo-x'.

> Here's the kind of thing I had in mind (can't think of any concrete
> example for it, tho, the motivation came from such cases in defadvice
> and interactive forms instead, which had the same problem is keeping
> code quoted thus preventing compilation and eager macroexpansion):
> 
>     (eval-when-compile (require 'cl))
>     (eval-after-load FOO '(flet ...))

I see. Tricky.

> There are a few other places where we "undo" a quote, as in
> 
>     (mapcar '(lambda ...) ...)
> 
> These were all done because it seemed to be beneficial more often than
> it is harmful.  I must admit that I wasn't 100% sure that "unquoting"
> its arg was "more often beneficial", tho the fact that I haven't heard
> anyone even mention this until now seems to argue that even tho it's
> maybe not "more often beneficial" at least not often harmful.

I think we've had that particular issue for a while in Flycheck — it's just 
that we didn't understand it until fairly recently.  It pops up when people put 
stuff in their use-package configuration, in particular.

Clément.



reply via email to

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