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.