.\" Copyright (c) 1980 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\" @(#)ch8.n 6.2 (Berkeley) 5/14/86
." $Header: ch8.n,v 1.4 83/07/27 15:12:22 layer Exp $
.Lc Functions,\ Fclosures,\ and\ Macros 8
.sh 2 valid\ function\ objects \n(ch 1
There are many different objects which can occupy the function field of
Table 8.1, on the following page,
shows all of the possibilities, how to recognize them,
and where to look for documentation.
informal name object type documentation
interpreted list with \fIcar\fP 8.2
lambda function \fIeq\fP to lambda
interpreted list with \fIcar\fP 8.2
nlambda function \fIeq\fP to nlambda
interpreted list with \fIcar\fP 8.2
lexpr function \fIeq\fP to lexpr
interpreted list with \fIcar\fP 8.3
fclosure vector with \fIvprop\fP 8.4
compiled binary with discipline 8.2
lambda or lexpr \fIeq\fP to lambda
compiled binary with discipline 8.2
nlambda function \fIeq\fP to nlambda
compiled binary with discipline 8.3
foreign binary with discipline 8.5
subroutine of \*(lqsubroutine\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
function of \*(lqfunction\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
integer function of \*(lqinteger-function\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
real function of \*(lqreal-function\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
C function of \*(lqc-function\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
double function of \*(lqdouble-c-function\*(rq\*[\(dg\*]
foreign binary with discipline 8.5
structure function of \*(lqvector-c-function\*(rq\*[\(dg\*]
\*[\(dg\*]Only the first character of the string is significant (i.e \*(lqs\*(rq
is ok for \*(lqsubroutine\*(rq)
The basic Lisp function is the lambda function.
When a lambda function is called, the actual arguments are
evaluated from left to right and are lambda-bound to the
formal parameters of the lambda function.
An nlambda function is usually used for functions which are invoked
by the user at top level.
Some built-in functions which evaluate their arguments in special ways are
also nlambdas (e.g \fIcond\fP, \fIdo\fP, \fIor\fP).
When an nlambda function is called, the list of unevaluated arguments
is lambda bound to the single formal parameter of the nlambda function.
Some programmers will use an nlambda function
when they are not sure how many arguments
Then, the first thing the nlambda function does is map \fIeval\fP over
the list of unevaluated arguments it has been passed.
This is usually the wrong thing to do, as it will not work compiled if
any of the arguments are local variables.
The solution is to use a lexpr.
When a lexpr function is called, the arguments
are evaluated and a fixnum whose value is
the number of arguments is lambda-bound to the single
formal parameter of the lexpr function.
The lexpr can then access the arguments using the \fIarg\fP function.
When a function is compiled,
declarations may be needed to
An argument is not lambda-bound to the name of
the corresponding formal parameter
unless that formal parameter has been declared
Lambda and lexpr functions both compile into a binary object with
However, a compiled lexpr still acts like an interpreted lexpr.
An important feature of Lisp
is its ability to manipulate programs as data.
As a result of this, most Lisp implementations
have very powerful macro facilities.
The Lisp language's macro facility
can be used to incorporate popular features of the other
For example, there are macro packages
which allow one to create records (ala Pascal)
and refer to elements of those records by the field names.
package imported from Maclisp does this.
Another popular use for macros is to create more readable control
structures which expand into
One such example is the If macro.
(If (equal numb 0) then (print 'zero) (terpr)
\ elseif (equal numb 1) then (print 'one) (terpr)
\ else (print '|I give up|))
\ \ \ \ ((equal numb 0) (print 'zero) (terpr))
\ \ \ \ ((equal numb 1) (print 'one) (terpr))
\ \ \ \ (t (print '|I give up|)))
A macro is a function which accepts a Lisp expression as input and returns
The action the macro takes is called macro expansion.
Here is a simple example:
\-> \fI(def first (macro (x) (cons 'car (cdr x))))\fP
\-> \fI(first '(a b c))\fP
\-> \fI(apply 'first '(first '(a b c)))\fP
The first input line defines a macro called
Notice that the macro has one formal parameter, \fIx\fP.
On the second input line, we ask the interpreter to evaluate
\fI(first\ '(a\ b\ c))\fP.
has a function definition of type macro, so it evaluates
evaluate: \fI(first\ '(a\ b\ c))\fP.
macro chops off the car of the argument with
at the beginning of the list and returns \fI(car\ '(a\ b\ c))\fP,
is returned as the value of \fI(first\ '(a\ b\ c))\fP.
tries to evaluate a list whose car has a macro definition
it ends up doing (at least) two operations, the first of which
to let it macro expand the form, and the other is the evaluation of the
The result of the macro may be yet another call to a macro, so
may have to do even more evaluations until it can finally determine
the value of an expression.
One way to see how a macro will expand is to use
as shown on the third input line above.
makes it easier to define macros because it allows you to name the arguments
For example, suppose we find ourselves often writing code like
\fI(setq\ stack\ (cons\ newelt\ stack)\fP.
We could define a macro named \fIpush\fP to do this for us.
\h'|\nAu'(macro (x) (list 'setq (caddr x) (list 'cons (cadr x) (caddr x)))))\fP
then \fI(push\ newelt\ stack)\fP will expand to the form mentioned above.
The same macro written using defmacro would be:
\->\fI\kA (defmacro push (value stack)
\h'|\nAu'(list 'setq ,stack (list 'cons ,value ,stack)))\fP
Defmacro allows you to name the arguments of the macro call, and makes the
macro definition look more like a function definition.
.sh +0 the\ backquote\ character\ macro
has four characters with associated character macros.
One is semicolon for comments.
Two others are the backquote and comma which are
used by the backquote character
The fourth is the sharp sign macro described in the next section.
The backquote macro is used to create lists where many of the elements are
This makes it very useful for creating macro definitions.
In the simplest case, a backquote acts just like a single quote:
If a comma precedes an element of a backquoted list then that element is
evaluated and its value is put in the list.
\->\fI(setq d '(x y z))\fP
If a comma followed by an at sign precedes an element in a backquoted list,
then that element is evaluated and spliced into the list with
Once a list begins with a backquote, the commas may appear anywhere in the
list as this example shows:
\->\fI`(a b (c d ,(cdr d)) (e f (g h ,@(cddr d) ,@d)))\fP
(a b (c d (y z)) (e f (g h z x y z)))
It is also possible and sometimes even useful to use the
backquote macro within itself.
As a final demonstration of the backquote macro, we shall define the
first and push macros using all the power at our disposal: defmacro
\->\fI(defmacro first (list) `(car ,list))\fP
\->\fI(defmacro push (value stack) `(setq ,stack (cons ,value ,stack)))\fP
.sh +0 sharp\ sign\ character\ macro
The sharp sign macro can perform a number of
different functions at read time.
The character directly following the sharp sign determines which function
will be done, and following Lisp s-expressions may serve as arguments.
.sh +1 conditional\ inclusion
If you plan to run one source file in more than one environment then
you may want to some pieces of code to be included or not included
depending on the environment.
The C language uses \*(lq#ifdef\*(lq and \*(lq#ifndef\*(rq for this
purpose, and Lisp uses \*(lq#+\*(rq and \*(lq#\-\*(rq.
The environment that the sharp sign macro checks is the
\fI(status\ features)\fP list which is initialized when the Lisp
system is built and which may be altered by
\fI(sstatus\ feature\ foo)\fP and \fI(sstatus\ nofeature\ bar)\fP
The form of conditional inclusion is
.tl ''\fI#+when what\fP''
is either a symbol or an expression involving symbols and the functions
is true only if it appears in the
; suppose we want to write a program which references a file
; and which can run at ucb, ucsd and cmu where the file naming conventions
\-> \fI(de\kAfun howold (name)
\h'|\nCu'\kB(load #\kA+(or ucb ucsd) "/usr/lib/lisp/ages.l"
\h'|\nAu'#+cmu "/usr/lisp/doc/ages.l")
\h'|\nBu'\kA(patom " is ")
\h'|\nAu'\kB(print (cdr (assoc name agefile)))
\h'|\nBu'\kA(patom "years old")
.tl ''\fI#\-when what\fP''
.tl ''\fI#+(not when) what\fP''
.sh +0 fixnum\ character\ equivalents
When working with fixnum equivalents of characters, it is often hard to
remember the number corresponding to a character.
is equivalent to the fixnum representation of character c.
; a function which returns t if the user types y else it returns nil.
\-> \fI(de\kBfun yesorno nil
\h'|\nAu'\kB(setq ans (tyi))
\h'|\nBu'(cond \kA((equal ans #/y) t)
.sh +0 read\ time\ evaluation
Occasionally you want to express a constant as a Lisp expression, yet you
don't want to pay the penalty of evaluating this expression each time it
.tl ''\fI#.expression\fP''
evaluates the expression at read time and returns its value.
; a function to test if any of bits 1 3 or 12 are set in a fixnum.
\-> \fI(de\kCfun testit (num)
\h'|\nCu'(cond \kA(\kB(zerop (boole 1 num #.(+ (lsh 1 1) (lsh 1 3) (lsh 1 12))))
Fclosures are a type of functional object.
The purpose is to remember the values of some variables
between invocations of the functional object and to protect this
data from being inadvertently overwritten by other Lisp functions.
Fortran programs usually exhibit this behavior for their variables.
(In fact, some versions of Fortran would require the
variables to be in COMMON).
Thus it is easy to write a linear congruent random number generator
in Fortran, merely by keeping the seed as a variable in the function.
It is much more risky to do so in Lisp, since any special variable you
picked, might be used by some other function.
Fclosures are an attempt to provide most of the same functionality as
closures in Lisp Machine Lisp, to users of
Fclosures are related to closures in this way:
(fclosure '(a b) 'foo) <==>
(let ((a a) (b b)) (closure '(a b) 'foo))
\->\fB(defun code (me count)
(cond ((greaterp count 1) (funcall me me (sub1 count))))
(print (list 'out x)))\fP
\->\fB(defun tester (object count)
(funcall object object count) (terpri))\fP
\->\fB(setq z (fclosure '(x) 'code))\fP
(in 0)(in 1)(in 2)(out 3)(out 3)(out 3)
The function \fIfclosure\fP creates a new object
that we will call an fclosure,
(although it is actually a vector).
The fclosure contains a functional object, and a set of symbols and
values for the symbols. In the above example, the fclosure functional
object is the function code.
The set of symbols and values just contains the symbol `x' and
zero, the value of `x' when the fclosure was created.
When an fclosure is funcall'ed:
The Lisp system lambda binds the symbols in the fclosure to their values in the fclosure.
It continues the funcall on the functional object of the fclosure.
Finally, it un-lambda binds the symbols in the fclosure and at the
same time stores the current values of the symbols in the fclosure.
Notice that the fclosure is saving the value of the symbol `x'.
Each time a fclosure is created, new space is allocated for saving
the values of the symbols. Thus if we execute fclosure again, over
the same function, we can have two independent counters:
\-> \fB(setq zz (fclosure '(x) 'code))\fP
(in 0)(in 1)(out 2)(out 2)
(in 2)(in 3)(out 4)(out 4)
(in 3)(in 4)(in 5)(out 6)(out 6)(out 6)
Here are some quick some summaries of functions dealing with closures.
They are more formally defined in \(sc2.8.4.
To recap, fclosures are made by
\fI(fclosure 'l_vars 'g_funcobj)\fP.
l_vars is a list of symbols (not containing nil),
g_funcobj is any object that can be funcalled.
(Objects which can be funcalled, include compiled Lisp functions,
lambda expressions, symbols, foreign functions, etc.)
In general, if you want a compiled function to be closed over a
variable, you must declare the variable to be special within the function.
Another example would be:
(fclosure '(a b) #'(lambda (x) (plus x a)))
Here, the #' construction will make the compiler compile the lambda expression.
There are times when you want to share variables between fclosures.
This can be done if the fclosures are created at the same time using
The function \fIfclosure-alist\fP returns an assoc list giving
the symbols and values in the fclosure. The predicate
\fIfclosurep\fP returns t iff its argument is a fclosure.
Other functions imported from Lisp Machine Lisp are
Lastly, the function \fIfclosure-function\fP returns the function argument.
.sh 3 internal\ structure
Currently, closures are implemented as vectors, with property being the
symbol fclosure. The functional object is the first entry.
The remaining entries are structures which point to the symbols
and values for the closure, (with a reference count to determine
if a recursive closure is active).
.sh 2 foreign\ subroutines\ and\ functions
has the ability to dynamically load object files produced by other compilers
and to call functions defined in those files.
These functions are called
*This topic is also discussed in Report PAM-124 of the Center for
Pure and Applied Mathematics, UCB, entitled ``Parlez-Vous Franz?
An Informal Introduction to Interfacing Foreign Functions to Franz LISP'',
There are seven types of foreign functions.
They are characterized by
the type of result they return, and by differences in the interpretation
They come from two families: a group suited for languages which pass
arguments by reference (e.g. Fortran), and a group suited for languages
which pass arguments by value (e.g. C).
There are four types in the first group:
This does not return anything.
always returns t after calling a subroutine.
This returns whatever the function returns.
This must be a valid Lisp object or it may cause the Lisp system to fail.
.ip \fBinteger-function\fP
This returns an integer which the Lisp system makes into a fixnum and returns.
This returns a double precision real number which the Lisp
system makes into a flonum and returns.
There are three types in the second group:
This is like an integer function, except for its different interpretation
.ip \fBdouble-c-function\fP
This is like a real-function.
.ip \fBvector-c-function\fP
This is for C functions which return a structure.
The first argument to such functions must be a vector (of type vectori),
into which the result is stored.
becomes the first argument to the C function, and so on
A foreign function is accessed through a binary object just like a
The difference is that the discipline field of a binary object
for a foreign function is a string
whose first character is given in the following table:
Two functions are provided for setting-up foreign functions.
loads an object file into the Lisp system and sets up one foreign
If there are more than one function in an object file,
can be used to set up additional foreign function objects.
Foreign functions are called just like other functions, e.g
\fI(funname\ arg1\ arg2)\fP.
When a function in the Fortran group is called,
the arguments are evaluated and then examined.
List, hunk and symbol arguments are passed unchanged to
Fixnum and flonum arguments are copied into a temporary location and
a pointer to the value is passed (this is because Fortran uses call
by reference and it is dangerous to modify the contents of a fixnum
or flonum which something else might point to).
If the argument is an array object,
the data field of the array object is
passed to the foreign function
(This is the easiest way to send large
amounts of data to and receive large amounts of data from a foreign
If a binary object is an argument, the entry field of that object is
passed to the foreign function (the entry field is the address of a function,
so this amounts to passing a function as an argument).
When a function in the C group is called,
fixnum and flownum arguments are passed by value.
For almost all other arguments,
the address is merely provided to the C routine.
The only exception arises when you want to invoke a C routine
which expects a ``structure'' argument. Recall that a (rarely used)
feature of the C language is the ability to pass structures by value.
This copies the structure onto the stack. Since the Franz's nearest
equivalent to a C structure is a vector, we provide an escape clause
to copy the contents of an immediate-type vector by value. If the
property field of a vectori argument, is the symbol
\*(lqvalue-structure-argument\*(rq,
then the binary data of this immediate-type vector is copied
into the argument list of the C routine.
The method a foreign function uses to access the arguments provided
by Lisp is dependent on the language of the foreign function.
The following scripts demonstrate how how Lisp can interact with three
languages: C, Pascal and Fortran.
C and Pascal have pointer types and the first script shows how to use
pointers to extract information from Lisp objects.
There are two functions defined for each language.
The first (cfoo in C, pfoo in Pascal) is given four arguments, a
fixnum, a flonum-block array, a hunk of at least two
To demonstrate that the values were passed, each ?foo function prints
its arguments (or parts of them).
The ?foo function then modifies the second element of
the flonum-block array and returns a 3 to Lisp.
The second function (cmemq in C, pmemq in Pascal) acts just like the
function (except it won't work for fixnums whereas the lisp
will work for small fixnums).
In the script, typed input is in
computer output is in roman
\fIThese are the C coded functions \fP
/* demonstration of c coded foreign integer-function */
/* the following will be used to extract fixnums out of a list of fixnums */
{ struct listoffixnumscell *cdr;
struct listoffixnumscell *d;
printf("a: %d, b[0]: %f, b[1]: %f\n", *a, b[0], b[1]);
printf(" c (first): %d c (second): %d\n",
printf(" ( %d %d ... )\n ", *(d->fixnum), *(d->cdr->fixnum));
for( ; list && element != list->car ; list = list->cdr);
\fIThese are the Pascal coded functions \fP
type pinteger = ^integer;
realarray = array[0..10] of real;
pintarray = array[0..10] of pinteger;
listoffixnumscell = record
cdr : ^listoffixnumscell;
function pfoo ( var a : integer ;
var d : listoffixnumscell) : integer;
writeln(' a:',a, ' b[0]:', b[0], ' b[1]:', b[1]);
writeln(' c (first):', c[0]^,' c (second):', c[1]^);
writeln(' ( ', d.fixnum^, d.cdr^.fixnum^, ' ...) ');
{ the function pmemq looks for the Lisp pointer given as the first argument
in the list pointed to by the second argument.
Note that we declare " a : integer " instead of " var a : integer " since
we are interested in the pointer value instead of what it points to (which
could be any Lisp object)
function pmemq( a : integer; list : plistcell) : plistcell;
while (list <> nil) and (list^.car <> a) do list := list^.cdr;
\fIThe files are compiled\fP
1.0u 1.2s 0:15 14% 30+39k 33+20io 147pf+0w
3.0u 1.7s 0:37 12% 27+32k 53+32io 143pf+0w
First the files are loaded and we set up one foreign function binary.
We have two functions in each file so we must choose one to tell cfasl about.
\->\fB (cfasl 'ch8auxc.o '_cfoo 'cfoo "integer-function")\fP
/usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxc.o -e _cfoo -o /tmp/Li7055.0 -lc
#63000-"integer-function"
\->\fB (cfasl 'ch8auxp.o '_pfoo 'pfoo "integer-function" "-lpc")\fP
/usr/lib/lisp/nld -N -A /tmp/Li7055.0 -T 63200 ch8auxp.o -e _pfoo -o /tmp/Li7055.1 -lpc -lc
#63200-"integer-function"
Here we set up the other foreign function binary objects
\->\fB (getaddress '_cmemq 'cmemq "function" '_pmemq 'pmemq "function")\fP
We want to create and initialize an array to pass to the cfoo function.
In this case we create an unnamed array and store it in the value cell of
When we create an array to pass to the Pascal program we will use a named
array just to demonstrate the different way that named and unnamed arrays
are created and accessed.
\->\fB (setq testarr (array nil flonum-block 2))\fP
\->\fB (store (funcall testarr 0) 1.234)\fP
\->\fB (store (funcall testarr 1) 5.678)\fP
\->\fB (cfoo 385 testarr (hunk 10 11 13 14) '(15 16 17))\fP
a: 385, b[0]: 1.234000, b[1]: 5.678000
c (first): 10 c (second): 11
Note that cfoo has returned 3 as it should.
It also had the side effect of changing the second value of the array to
3.1415926 which check next.
\->\fB (funcall testarr 1)\fP
In preparation for calling pfoo we create an array.
\->\fB (array test flonum-block 2)\fP
\->\fB (store (test 0) 1.234)\fP
\->\fB (store (test 1) 5.678)\fP
\->\fB (pfoo 385 (getd 'test) (hunk 10 11 13 14) '(15 16 17))\fP
a: 385 b[0]: 1.23400000000000E+00 b[1]: 5.67800000000000E+00
c (first): 10 c (second): 11
\fI Now to test out the memq's
\-> \fB(cmemq 'a '(b c a d e f))\fP
\-> \fB(pmemq 'e '(a d f g a x))\fP
The Fortran example will be much shorter since in Fortran
you can't follow pointers
as you can in other languages.
The Fortran function ffoo is given three arguments: a fixnum, a
fixnum-block array and a flonum.
These arguments are printed out to verify that they made it and
then the first value of the array is modified.
The function returns a double precision value which is converted to a flonum
Note that the entry point corresponding to the Fortran function ffoo is
_ffoo_ as opposed to the C and Pascal convention of preceding the name with
double precision function ffoo(a,b,c)
2 format(' a=',i4,', b(1)=',i5,', b(2)=',i5,' c=',f6.4)
0.9u 1.8s 0:12 22% 20+22k 54+48io 158pf+0w
\-> \fB(cfasl 'ch8auxf.o '_ffoo_ 'ffoo "real-function" "-lF77 -lI77")\fP
/usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxf.o -e _ffoo_
-o /tmp/Li11066.0 -lF77 -lI77 -lc
\-> \fB(array test fixnum-block 2)\fP
\->\fB (store (test 0) 10)\fP
\-> \fB(store (test 1) 11)\fP
\-> \fB(ffoo 385 (getd 'test) 5.678)\fP
a= 385, b(1)= 10, b(2)= 11 c=5.6780