3

There is an eval-when-compile macro but, AFAICT, no eval-when-not-compiling or load-time-only, that would be very convenient for me now. Do you know any generic workaround?

Why do I need this: I have a package with (eval-when-compile (load "other-package")) and, in this other package, some initialisation code that is for load time only. That the code is for load time only is understood implicitly when the other-package itself is compiled, but not when it is loaded as part of compiling something else.

2
  • 2
    When you compile the package, you load other-package, therefore it is load time for other-package. You could try checking if byte compilation is in progress like cl--compiling-file does perhaps.
    – npostavs
    Dec 3, 2017 at 12:32
  • 2
    An alternative to calling cl--compiling-file is to inspect the value of (bound-and-true-p byte-compile-current-file), which is only set during byte-compilation.
    – Basil
    Dec 3, 2017 at 21:39

2 Answers 2

4

EDIT:

The comment of npostavs is true. When you load "other-package" during byte compilation the test result on byte-compilation in "other-package" is negative.

You need to remember in the original package that you are byte-compiling. You can do that by let-binding:

A minimal example:

Content of the original package:

(eval-when-compile
  (let ((other-package-loading-for-compilation t))
    (load "other-package")))

Content of "other-package":

(unless (bound-and-true-p other-package-loading-for-compilation)
  (message "For initialization only"))

OLD Answer:

I assume that you have already compiled other-package. In that case

(cl-eval-when (load) ...)

in other-package works.

The doc-string of cl-eval-when:

(cl-eval-when (WHEN...) BODY...)

Control when BODY is evaluated.

If ‘compile’ is in WHEN, BODY is evaluated when compiled at top-level.

If ‘load’ is in WHEN, BODY is evaluated when loaded after top-level compile.

If ‘eval’ is in WHEN, BODY is evaluated when interpreted or at non-top-level.

From my perspective the load case description is a bit misleading. It means that BODY is evaluated when the byte-compiled library is loaded -- not only directly after byte-compilation.

You can also combine the cases. If you want BODY to be evaluated also when the source file is loaded you can use

(cl-eval-when (eval load) ...)

5
  • @phils Thanks for the correction of my lapse.
    – Tobias
    Dec 3, 2017 at 22:25
  • In my tests, this makes no difference to the problem described by phs.
    – Stefan
    Dec 4, 2017 at 13:30
  • @Stefan I am afraid I didn't understand the OP's question in full. Now I edited my answer to address the OP's problem. Since some folks found the answer to be useful I keep the old content.
    – Tobias
    Dec 4, 2017 at 13:50
  • thanks for the update. Note that in your updated solution, the (eval-when (load eval) is just redundant (a top-level expression of the form (unless ...) will not be evaluated by the compiler anyway). Also you might like to use bound-and-true-p to make sure the var is actually bound to a non-nil value.
    – Stefan
    Dec 4, 2017 at 13:54
  • @Stefan I first thought of just using (let (other-package-loading-for-compilation) (load "other-package")) but now I changed to your version with bound-and-true-p. It is more clear. Okay, the doc says the other forms are batched together and the compiled code will be executed when the file is read. Therefore, the eval-when is redundant. Thanks for the info.
    – Tobias
    Dec 4, 2017 at 14:08
3

I don't really have a solution for that problem, sadly. If you have control of other-package, the recommended way to solve those problems is to move the load-time only code into a function, because loading a package should always be "harmless" (Emacs occasionally loads Elisp files without a very strong reason, e.g. just to find out if a particular function is defined in it).

I.e. in other-package you change

(some-undesirable-load-time-code)

into

;;;###autoload
(defun other-package-initialize ()
  (some-undesirable-load-time-code))

and then the users of other-package will need to change

(require 'other-package)

into

(other-package-initialize)

when they want the initialization rather than just loading the file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.