Subject: Re: macros, boxing, closures
From: Erik Naggum <clerik@naggum.no>
Date: 1997/08/31
Newsgroups: comp.lang.lisp
Message-ID: <3082048557306439@naggum.no>


* Gary Livingston
| 1.  What is 'boxing?'

the allocation of a new object that holds a value that cannot be held in a
machine word due to the information required by Lisp to represent the type
of the object.  the term "boxed" itself comes from the way one would store
such a value when pointers themselves could not hold type information.
e.g., suppose you have a value V that you wished to return with type
information.  V itself could be just about any bit pattern and could not
tell anyone what it was.  you would then create a new object that held type
information about V, and then (a copy of) V, and return that object.  since
pointers can often contain type information, you may not need to waste
memory on type information, but you still need to point to the newly
created "box" that holds the value.

| 2.  What are closures?

a function is said to be closed over bindings (variables) that are part of
the lexical scope in which the function is defined.  e.g., in

    (let ((counter 0))
      (defun counter ()
	(incf counter))
      (defun (setf counter) (new-counter)
	(setq counter new-counter)))

the functions `counter' and `setf counter' are closures that have access to
the lexical variable "counter".

however, the important purpose of closures is passing them around:

    (defun foo (x)
      (mapcar (lambda (y) (+ x y)) *some-global*))

we note that the anonymous function uses the variable `x' from its
lexically scope, but is passed to `mapcar' and is expected to work.

likewise, in this series of trivial examples, the function `add' returns a
function that takes one argument and returns the sum of that argument and
the argument to `add':

    (defun add (x)
      (lambda (y) (+ x y)))

such that you can say

    (mapcar (add 5) '(10 20 30))

as Henry Baker once pointed out to me, closures can be used to create a
"structure" concept.

| 3.  Do inlines and macros produce essentially the same code?

no.  macros are functions that are called by the compiler to expand the
macro call form to another form, which is then compiled in its place.
function calls that are inlined cause the function body itself to produce
compiled code in situ.

macros should _never_ be used for optimization.  it's simply the wrong
solution.  if special considerations for inlining or speed is required, a
_compiler-macro_ should be employed in addition to the actual function.

you can cause a macro and an inlined function call to produce the same
code, but they would look very different.

an example would be too elaborate, but see the Common Lisp HyperSpec at
http://www.harlequin.com/books/HyperSpec/Body/mac_define-compiler-macro.html
for some excellent examples.

| This one I will attempt to answer myself by writing two versions of the
| same function, one using inline and the other using macros and comparing
| them.  This trick of looking at the dissassembled code is a new trick for
| me.

my favorite AI Koan from the Jargon File (noting that Tom Knight was one of
the principle designers of the Lisp Machine):

    A novice was trying to fix a broken Lisp machine by turning the power
    off and on.

    Knight, seeing what the student was doing, spoke sternly: "You cannot
    fix a machine by just power-cycling it with no understanding of what is
    going wrong."

    Knight turned the machine off and on.

    The machine worked.

many things "work", most by accident, a few by design.  the task of the
conscientious student is to separate the two from each other, and then only
use those that work by design, unless the design is broken, which it takes
an even more conscientious student to figure out.  so, don't be satisfied
when you find something that works, go on to figure out why and whether it
was by design or accident.

hope this helps.

#\Erik
-- 
404 You're better off without that file.  Trust me.