help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: Why (eval-when-compile (require 'foo)) does not bind functions durin


From: Pascal J. Bourguignon
Subject: Re: Why (eval-when-compile (require 'foo)) does not bind functions during compilation?
Date: Sun, 30 Aug 2015 09:23:11 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Marcin Borkowski <mbork@mbork.pl> writes:

> As in the subject.  The manual says that it does define macros from the
> library “foo”, but not functions.  Why is that so?  I would think that
> the above form actually evaluates the (require 'foo) part during
> compilation, so in particular it should evaluate all the defuns there –
> but both experiments and manual confirm that I’m wrong.  Where is my
> mental model incorrect?

Your mental model should be that compilation is reading data and
producing data, and there's no reason for that process to modify the
compiler.

A compiler is a machine like that:

            +--------------------------------+
            |  source      --->      object  |
            | language              language |
            +---------+            +---------+
                      |            |
                      |            |
                      |            |
                      |  machine   |
                      |  language  |
                      +------------+
                      +------------+
                       \ machine  /
                        \language/
                         \      /  <-- machine
                          \    /
                           \  /
                            \/


It takes a program written in the source language:

            +-----------+
            | program 1 |
            |           |
            |           |
            |           |
            |  source   |
            | language  |
            +-----------+
            +--------------------------------+
            |  source      --->      object  |
            | language              language |
            +---------+            +---------+
                      |            |
                      |            |
                      |            |
                      |  machine   |
                      |  language  |
                      +------------+
                      +------------+
                       \ machine  /
                        \language/
                         \      /  <-- machine
                          \    /
                           \  /
                            \/


And produce an equivalent program in object language:

            +-----------+        +-----------+
            | program 1 |        | program 1 |
            |           |        |           |
            |           |        |           |
            |           |  -->   |           |
            |  source   |        |  object   |
            | language  |        | language  |
            +-----------+        +-----------+
            +--------------------------------+
            |  source      --->      object  |
            | language              language |
            +---------+            +---------+
                      |            |
                      |            |
                      |            |
                      |  machine   |
                      |  language  |
                      +------------+
                      +------------+
                       \ machine  /
                        \language/
                         \      /  <-- machine
                          \    /
                           \  /
                            \/



There's no reason to incorporate this program in object language into
the compiler itself.  For one thing, it's possible the object language
and the machine language to be different, so there would be no use of
merging them.  For another, you could be compiling a function of a new
version of the compiler, and if you merged it with the running compiler,
you could easily break it.

 +------------------------------+     +------------------------------+
 |  source     --->     object  | ->  |  source     --->     object  |
 | language            language |     | language            language |
 +---------+          +---------+     +---------+          +---------+
           |          |                         |          |          
           |          |                         |          |          
           |          |                         |          |          
           |  source  |                         |  object  |          
           | language |                         | language |          
           +----------+                         +----------+          
           +-----------------------------------------------+
           |  source             --->              object  |
           | language                             language |
           +----------------+            +-----------------+
                            |            |
                            |            |
                            |            |
                            |  machine   |
                            |  language  |
                            +------------+
                            +------------+
                             \ machine  /
                              \language/
                               \      /  <-- machine
                                \    /
                                 \  /
                                  \/


Therefore it's a good feature that compiling a function doesn't install
it in the environment used to compile it.

Instead, you should use load to instal compiled functions into the
run-time environment, after compiling:

    (load (byte-compile-file "source.el"))
    (load "source.elc")



Of course, the case of macros is different since they are explicitely
and well delimited compiler hooks.  The compiler has to take them into
account, to be able to further process the source.  And those macros may
need to use to compute their expansion some functions defined in that
source, therefore you should either load those functions before using
the macros, in a separate file, compiling and loading each file in
turn, or using eval-when-compile to define those functions.

Which is exactly the opposite of what you say it does. I don't know what
documentation you're reading, but it's wrong.


----(example.el)----------------------------------------------------------------

(eval-when-compile
 (defun gen-form (x)
   `(progn
      (insert ,(format "%S" x) "\n")
      (insert ,(format "%S" x) "\n")
      ',x)))

(defmacro m (x)
  (gen-form x))

(defun f ()
  (m "life?")
  (m 42))

--------------------------------------------------------------------------------

(byte-compile-file "~/Desktop/example.el")

(gen-form '(+ 30 3))
--> (progn (insert "(+ 30 3)" "
") (insert "(+ 30 3)" "
") (quote (+ 30 3)))

;; The object defined in eval-when-compile are incorporated into the
;; compiler environment.

(f) --> Debugger entered--Lisp error: (void-function f)

;; The others are not (unless they're macros).  The compiler still notes
;; that f will be fbound though.

(load  "~/Desktop/example.elc")

(f)
inserts:
    "life?"
    "life?"
    42
    42
--> 42

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


reply via email to

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