emacs-devel
[Top][All Lists]
Advanced

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

Re: eval-after-load not harmful after all (Was: Re: Why js-2mode?)


From: Stephen J. Turnbull
Subject: Re: eval-after-load not harmful after all (Was: Re: Why js-2mode?)
Date: Tue, 11 Aug 2009 23:37:16 +0900

Daniel Colascione writes:

 > You haven't actually addressed the reason for using e-a-l and provided  
 > alternatives, nor have you provided any concrete examples of the harm  
 > e-a-l might cause.

I haven't had to debug such a case in four or five years, and I'd like
to keep setting a new record every morning, just by getting out of
bed.

As a matter of principle, I don't like constructs that change the
behavior of code in a way that that code doesn't anticipate.
Specifically, in order to catch eval-after-load in the act, you need
to know which library invoked it.  Otherwise, by the time you observe
a bug, the behavior has been changed and the entry has been purged
from after-load-alist.  defadvice, by contrast, leaves a trace of its
behavior in the docstring of an adviced function.

 > You've just put "necessary" in scare quotes without even
 > considering the idea that it might actually *be* necessary.

Thanks for playing, but you have failed to read my mind.  In fact, I
quite obviously, though implicitly, have acknowledged the *need* for
the feature by not calling for its removal, indeed, giving a case
where I think it's harmless and useful.

On the other hand, we have yet to see a convincing example of "need"
here.  I don't think your hs-whatever-it-was example does the trick,
Carsten's was definitively exploded by Dan Nicolaescu IIRC.

 > If packages M needs to work with optional package Q, then there are  
 > two approaches: either M can use eval-after-load to customize Q, or Q  
 > can include a list of every possible M with which it can be used. You  
 > might decry the former, but I don't think the latter is any more  
 > maintainable. 

Ah, but we're talking about the core, where there *definitely* is a
third approach: have the two library maintainers negotiate a suitably
general hook in Q that M can use to customize it.  In many, perhaps
most, cases that hook already exists.  Eg, for standardly-defined
modes you can typically do

    (if (featurep 'foo)
        (bar-customize-foo)
      (add-hook 'foo-mode-hook #'bar-customize-foo))

where #'bar-customize-foo is idempotent.  Eg, by wrapping the active
code in

    (unless (get 'bar-customize-foo 'customization-installed-p)
      (bar-customize-foo-internal)
      (put 'bar-customize-foo 'customization-installed-p t))

(`add-one-shot-hook' suffers from the same kind of disabilities that
`eval-after-load' does.)

So there's your alternative.  I don't guarantee that pattern is 100%
general, but between that and use of other, more specific hooks
(existing ones as in Carsten's example, or newly-designed ones), you
can probably restrict cases in the core to very nearly zero.

I think the onus is on those who wish to use eval-after-load in the
core, or even to document "appropriate uses" outside the core, to
define what those appropriate uses might be.  Note that the approach
of coooperatively defining hooks is theoretically available outside
the core, too, although coordination is more expensive then.





reply via email to

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