Subject: Re: Why doesn't Lisp automatically differentiate functions and macros?
From: rpw3@rpw3.org (Rob Warnock)
Date: Thu, 26 Apr 2007 03:30:41 -0500
Newsgroups: comp.lang.lisp
Message-ID: <vrqdnZC2F9is_q3bnZ2dnUVZ_h2pnZ2d@speakeasy.net>
hovik  <hovik.melikyan@gmail.com> wrote:
+---------------
| So, what stops a Lisp machine from figuring automatically which
| function is strictly a run-time function, and which could also
| be used at compile-time?
+---------------

First, there are more "times" in Common Lisp than just "run-time" and
"compile time". At a minimum, you also need to consider "read time"
and "macro expansion time". [And it is probably "macro expansion time"
you are really interested in when comparing compilation & executing.]
See at least the following sections of the CLHC for definitions of
and interactions between the various "times" and the various startup,
evaluation, compilation, and run-time environments.

    http://www.alu.org/HyperSpec/Body/sec_2-2.html
    2.2 Reader Algorithm

    http://www.alu.org/HyperSpec/Body/sec_3-2-1.html
    3.2.1 Compiler Terminology

    http://www.alu.org/HyperSpec/Body/sec_3-2-2-2.html
    3.2.2.2 Minimal Compilation

    http://www.alu.org/HyperSpec/Body/sec_3-2-2-3.html
    3.2.2.3 Semantic Constraints

    http://www.alu.org/HyperSpec/Body/sec_3-1-2-1-2-2.html
    3.1.2.1.2.2 Macro Forms

    http://www.alu.org/HyperSpec/Body/speope_eval-when.html
    Special Operator EVAL-WHEN

Note that because the CLHS forbids macro functions from
modifying their argument forms [see Issue SELF-MODIFYING-CODE
<http://www.alu.org/HyperSpec/Issues/iss301-writeup.html>],
many CL implementations perform at least "Minimal Compilation"
[see CLHS 3.2.2.2, above] even on "interpreted" code, so macros
don't have to be re-expanded over & over again in interpreted
loops [or any other code executed more than once].

+---------------
| In other words, why bother distinguishing macros and
| functions when writing programs if it can be done automatically?
+---------------

It can't.

+---------------
| First, the compiler is supposed to "know" that any system call
| (e.g. I/O, GUI, etc.) has side effects and thus all branches of
| the code that invoke a syscall can be marked as run-time only.
+---------------

Uh... Common Lisp macro functions *can* do system calls at macro
expansion time!! This might be at compile time or even at read time
[assuming *READ-EVAL* is true]. Macros can read & write files,
make database calls across a network, or anything else that a
function can do. What's different about macros is not *what*
they do, but *when* they do it and how the return value from
them is used... namely, as program *source* to be included in
the program being macroexpanded instead of the original macro
form present in the source.

Said another way, macros are programs within your programs that
write part of your programs for you. Or to lift from Sam Steingold's
and Martin Rodgers's sometime signatures, macros let you write
code that writes code that writes code for you.

+---------------
| Second, those languages that have global data can assume both
| reading and writing globals a RT-only operation.
+---------------

Uh... Not necessarily. It is quite possible for Lisp macros to
create/modify global data at compile time.

+---------------
| Of course a deeper analysis can be performed and there is a chance
| that in some situations a global can be used at compile-time too.
+---------------

Sometimes, and sometimes not -- it depends. Again, you really need
to study the various "times" that occur in a Common Lisp program,
including how you can conditionally test for and/or temporarily
change the "time", such as the EVAL-WHEN operator mentioned above.


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607