Annotation of 43BSDTahoe/ucb/lisp/doc/ch8.n, revision 1.1

1.1     ! root        1: .\" Copyright (c) 1980 Regents of the University of California.
        !             2: .\" All rights reserved.  The Berkeley software License Agreement
        !             3: .\" specifies the terms and conditions for redistribution.
        !             4: .\"
        !             5: .\"    @(#)ch8.n       6.2 (Berkeley) 5/14/86
        !             6: .\"
        !             7: ." $Header: ch8.n,v 1.4 83/07/27 15:12:22 layer Exp $
        !             8: .Lc Functions,\ Fclosures,\ and\ Macros 8
        !             9: .sh 2 valid\ function\ objects \n(ch 1
        !            10: .pp
        !            11: There are many different objects which can occupy the function field of 
        !            12: a symbol object.
        !            13: Table 8.1, on the following page,
        !            14: shows all of the possibilities, how to recognize them,
        !            15: and where to look for documentation.
        !            16: .(z
        !            17: .sp 1v
        !            18: .TS
        !            19: box center ;
        !            20: c | c | c .
        !            21: informal name  object type     documentation 
        !            22: =
        !            23: interpreted    list with \fIcar\fP     8.2
        !            24: lambda function        \fIeq\fP to lambda
        !            25: _
        !            26: interpreted    list with \fIcar\fP     8.2
        !            27: nlambda function       \fIeq\fP to nlambda
        !            28: _
        !            29: interpreted    list with \fIcar\fP     8.2
        !            30: lexpr function \fIeq\fP to lexpr
        !            31: _
        !            32: interpreted    list with \fIcar\fP     8.3
        !            33: macro  \fIeq\fP to macro
        !            34: _
        !            35: fclosure       vector with \fIvprop\fP 8.4
        !            36:        \fIeq\fP to fclosure
        !            37: _
        !            38: compiled       binary with discipline  8.2
        !            39: lambda or lexpr        \fIeq\fP to lambda
        !            40: function
        !            41: _
        !            42: compiled       binary with discipline  8.2
        !            43: nlambda function       \fIeq\fP to nlambda
        !            44: _
        !            45: compiled       binary with discipline  8.3
        !            46: macro  \fIeq\fP to macro
        !            47: _
        !            48: foreign        binary with discipline  8.5
        !            49: subroutine     of \*(lqsubroutine\*(rq\*[\(dg\*]
        !            50: _
        !            51: foreign        binary with discipline  8.5
        !            52: function       of \*(lqfunction\*(rq\*[\(dg\*]
        !            53: _
        !            54: foreign        binary with discipline  8.5
        !            55: integer function       of \*(lqinteger-function\*(rq\*[\(dg\*]
        !            56: _
        !            57: foreign        binary with discipline  8.5
        !            58: real function  of \*(lqreal-function\*(rq\*[\(dg\*]
        !            59: _
        !            60: foreign        binary with discipline  8.5
        !            61: C function     of \*(lqc-function\*(rq\*[\(dg\*]
        !            62: _
        !            63: foreign        binary with discipline  8.5
        !            64: double function        of \*(lqdouble-c-function\*(rq\*[\(dg\*]
        !            65: _
        !            66: foreign        binary with discipline  8.5
        !            67: structure function     of \*(lqvector-c-function\*(rq\*[\(dg\*]
        !            68: _
        !            69: array  array object    9
        !            70: .TE
        !            71: .tl ''Table 8.1''
        !            72: .(f
        !            73: \*[\(dg\*]Only the first character of the string is significant (i.e \*(lqs\*(rq
        !            74: is ok for \*(lqsubroutine\*(rq)
        !            75: .)f
        !            76: .)z
        !            77: .br
        !            78: .sh 2 functions
        !            79: .pp
        !            80: The basic Lisp function is the lambda function.
        !            81: When a lambda function is called, the actual arguments are
        !            82: evaluated from left to right and are lambda-bound to the
        !            83: formal parameters of the lambda function.
        !            84: .pp
        !            85: An nlambda function is usually used for functions which are invoked
        !            86: by the user at top level.
        !            87: Some built-in functions which evaluate their arguments in special ways are
        !            88: also nlambdas (e.g \fIcond\fP, \fIdo\fP, \fIor\fP).
        !            89: When an nlambda function is called, the list of unevaluated arguments
        !            90: is lambda bound to the single formal parameter of the nlambda function.
        !            91: .pp
        !            92: Some programmers will use an nlambda function 
        !            93: when they are not sure how many arguments
        !            94: will be passed.
        !            95: Then, the first thing the nlambda function does is map \fIeval\fP over
        !            96: the list of unevaluated arguments it has been passed.
        !            97: This is usually the wrong thing to do, as it will not work compiled if
        !            98: any of the arguments are local variables. 
        !            99: The solution is to use a lexpr.
        !           100: When a lexpr function is called, the arguments
        !           101: are evaluated and a fixnum whose value is
        !           102: the number of arguments is lambda-bound to the single
        !           103: formal parameter of the lexpr function.
        !           104: The lexpr can then access the arguments using the \fIarg\fP function.
        !           105: .pp
        !           106: When a function is compiled,
        !           107: .i special 
        !           108: declarations may be needed to 
        !           109: preserve its behavior.
        !           110: An argument is not lambda-bound to the name of
        !           111: the corresponding formal parameter 
        !           112: unless that formal parameter has been declared 
        !           113: .i special 
        !           114: (see \(sc12.3.2.2).
        !           115: .pp
        !           116: Lambda and lexpr functions both compile into a binary object with
        !           117: a discipline of lambda.
        !           118: However, a compiled lexpr still acts like an interpreted lexpr.
        !           119: .sh 2 macros
        !           120: .pp
        !           121: An important feature of Lisp 
        !           122: is its ability to manipulate programs as data.
        !           123: As a result of this, most Lisp implementations
        !           124: have very powerful macro facilities.
        !           125: The Lisp language's macro facility
        !           126: can be used to incorporate popular features of the other
        !           127: languages into Lisp.
        !           128: For example, there are macro packages 
        !           129: which allow one to create records (ala Pascal) 
        !           130: and refer to elements of those records by the field names.
        !           131: The 
        !           132: .i struct
        !           133: package imported from Maclisp does this.
        !           134: Another popular use for macros is to create more readable control 
        !           135: structures which expand into 
        !           136: .i cond , 
        !           137: .i or 
        !           138: and 
        !           139: .i and .
        !           140: One such example is the If macro.
        !           141: It allows you to write
        !           142: .sp 1v
        !           143: .nf
        !           144: .ft I
        !           145: (If (equal numb 0) then (print 'zero) (terpr)
        !           146: \ elseif (equal numb 1) then (print 'one) (terpr)
        !           147: \ else (print '|I give up|))
        !           148: .ft P
        !           149: .sp 1v
        !           150: which expands to 
        !           151: .sp 1v
        !           152: .ft I
        !           153: (cond 
        !           154: \ \ \ \ ((equal numb 0) (print 'zero) (terpr))
        !           155: \ \ \ \ ((equal numb 1) (print 'one) (terpr))
        !           156: \ \ \ \ (t (print '|I give up|)))
        !           157: .ft P
        !           158: .sp 1v
        !           159: .fi
        !           160: .sh 3  macro\ forms
        !           161: .pp
        !           162: A macro is a function which accepts a Lisp expression as input and returns
        !           163: another Lisp expression.
        !           164: The action the macro takes is called macro expansion.
        !           165: Here is a simple example:
        !           166: .sp 1v
        !           167: .nf
        !           168: \-> \fI(def first (macro (x) (cons 'car (cdr x))))\fP
        !           169: first
        !           170: \-> \fI(first '(a b c))\fP
        !           171: a
        !           172: \-> \fI(apply 'first '(first '(a b c)))\fP
        !           173: (car '(a b c))
        !           174: .fi
        !           175: .sp 1v
        !           176: The first input line defines a macro called 
        !           177: .i first .
        !           178: Notice that the macro has one formal parameter, \fIx\fP.  
        !           179: On the second input line, we ask the interpreter to evaluate
        !           180: \fI(first\ '(a\ b\ c))\fP.
        !           181: .i Eval 
        !           182: sees that 
        !           183: .i first
        !           184: has a function definition of type macro, so it evaluates 
        !           185: .i first 's 
        !           186: definition,
        !           187: passing to 
        !           188: .i first ,
        !           189: as an argument, the form 
        !           190: .i eval 
        !           191: itself
        !           192: was trying to
        !           193: evaluate: \fI(first\ '(a\ b\ c))\fP.
        !           194: The 
        !           195: .i first 
        !           196: macro chops off the car of the argument with
        !           197: .i cdr ,
        !           198: cons' a 
        !           199: .i car
        !           200: at the beginning of the list and returns \fI(car\ '(a\ b\ c))\fP,
        !           201: which
        !           202: .i eval 
        !           203: evaluates.
        !           204: The value
        !           205: .i a
        !           206: is returned as the value of \fI(first\ '(a\ b\ c))\fP.
        !           207: Thus whenever 
        !           208: .i eval
        !           209: tries to evaluate a list whose car has a macro definition
        !           210: it ends up doing (at least) two operations, the first of which
        !           211: is a call to the macro
        !           212: to let it macro expand the form, and the other is the evaluation of the
        !           213: result of the macro.
        !           214: The result of the macro may be yet another call to a macro, so 
        !           215: .i eval
        !           216: may have to do even more evaluations until it can finally determine
        !           217: the  value of an expression.
        !           218: One way to see how a macro will expand is to use
        !           219: .i apply
        !           220: as shown on the third input line above.
        !           221: .sh +0 defmacro
        !           222: .pp
        !           223: The macro 
        !           224: .i defmacro
        !           225: makes it easier to define macros because it allows you to name the arguments
        !           226: to the macro call.
        !           227: For example, suppose we find ourselves often writing code like
        !           228: \fI(setq\ stack\ (cons\ newelt\ stack)\fP.
        !           229: We could define a macro named \fIpush\fP to do this for us.
        !           230: One way to define it is:
        !           231: .nf
        !           232: .sp 1v
        !           233: \-> \fI(de\kAf push 
        !           234: \h'|\nAu'(macro (x) (list 'setq (caddr x) (list 'cons (cadr x) (caddr x)))))\fP
        !           235: push
        !           236: .fi
        !           237: .sp 1v
        !           238: then \fI(push\ newelt\ stack)\fP will expand to the form mentioned above.
        !           239: The same macro written using defmacro would be:
        !           240: .nf
        !           241: .sp 1v
        !           242: \->\fI\kA (defmacro push (value stack)
        !           243:   \h'|\nAu'(list 'setq ,stack (list 'cons ,value ,stack)))\fP
        !           244: push
        !           245: .fi
        !           246: .sp 1v
        !           247: Defmacro allows you to name the arguments of the macro call, and makes the 
        !           248: macro definition look more like a function definition.
        !           249: .sh +0 the\ backquote\ character\ macro
        !           250: .pp
        !           251: The default syntax for 
        !           252: .Fr
        !           253: has four characters with associated character macros.
        !           254: One is semicolon for comments.
        !           255: Two others are the backquote and comma which are
        !           256: used by the backquote character
        !           257: macro.
        !           258: The fourth is the sharp sign macro described in the next section.
        !           259: .pp
        !           260: The backquote macro is used to create lists where many of the elements are
        !           261: fixed (quoted). 
        !           262: This makes it very useful for creating macro definitions.
        !           263: In the simplest case, a backquote acts just like a single quote:
        !           264: .sp 1v
        !           265: .nf
        !           266: \->\fI`(a b c d e)\fP
        !           267: (a b c d e)
        !           268: .fi
        !           269: .sp 1v
        !           270: If a comma precedes an element of a backquoted list then that element is
        !           271: evaluated and its value is put in the list.
        !           272: .sp 1v
        !           273: .nf
        !           274: \->\fI(setq d '(x y z))\fP
        !           275: (x y z)
        !           276: \->\fI`(a b c ,d e)\fP
        !           277: (a b c (x y z) e)
        !           278: .fi
        !           279: .sp 1v
        !           280: If a comma followed by an at sign precedes an element in a backquoted list,
        !           281: then that element is evaluated and spliced into the list with 
        !           282: .i append .
        !           283: .nf
        !           284: .sp 1v
        !           285: \->\fI`(a b c ,@d e)\fP
        !           286: (a b c x y z e)
        !           287: .sp 1v
        !           288: .fi
        !           289: Once a list begins with a backquote, the commas may appear anywhere in the
        !           290: list as this example shows:
        !           291: .nf
        !           292: .sp 1v
        !           293: \->\fI`(a b (c d ,(cdr d)) (e f (g h ,@(cddr d) ,@d)))\fP
        !           294: (a b (c d (y z)) (e f (g h z x y z)))
        !           295: .sp 1v
        !           296: .fi
        !           297: It is also possible and sometimes even useful to use the 
        !           298: backquote macro within itself.
        !           299: As a final demonstration of the backquote macro, we shall define the 
        !           300: first and push macros using all the power at our disposal: defmacro
        !           301: and the backquote macro.
        !           302: .sp 1v
        !           303: .nf
        !           304: \->\fI(defmacro first (list) `(car ,list))\fP
        !           305: first
        !           306: \->\fI(defmacro push (value stack) `(setq ,stack (cons ,value ,stack)))\fP
        !           307: stack
        !           308: .fi
        !           309: .sh +0 sharp\ sign\ character\ macro
        !           310: .pp
        !           311: The sharp sign macro can perform a number of
        !           312: different functions  at read time.
        !           313: The character directly following the sharp sign determines which function
        !           314: will be done, and following Lisp s-expressions may serve as arguments.
        !           315: .sh +1 conditional\ inclusion
        !           316: .lp
        !           317: If you plan to run one source file in more than one environment then 
        !           318: you may want to some pieces of code to be included  or not included
        !           319: depending on the environment.  
        !           320: The C language uses \*(lq#ifdef\*(lq and \*(lq#ifndef\*(rq for this 
        !           321: purpose, and Lisp uses \*(lq#+\*(rq and \*(lq#\-\*(rq.
        !           322: The environment that the sharp sign macro checks is the 
        !           323: \fI(status\ features)\fP list which is initialized when the Lisp
        !           324: system is built  and which may be  altered by 
        !           325: \fI(sstatus\ feature\ foo)\fP and \fI(sstatus\ nofeature\ bar)\fP
        !           326: The form  of conditional inclusion is
        !           327: .br
        !           328: .tl ''\fI#+when what\fP''
        !           329: where 
        !           330: .i when 
        !           331: is either a symbol or an expression involving symbols and the functions
        !           332: .i and ,
        !           333: .i or ,
        !           334: and
        !           335: .i not .
        !           336: The meaning is that 
        !           337: .i what
        !           338: will only be read in if  
        !           339: .i when
        !           340: is true.
        !           341: A symbol in 
        !           342: .i when
        !           343: is true only if it appears in the 
        !           344: .i (status\ features)
        !           345: list.
        !           346: .Eb
        !           347: ; suppose we want to write a program which references a file
        !           348: ; and which can run at ucb, ucsd and cmu where the file naming conventions
        !           349: ; are different.
        !           350: ;
        !           351: \-> \fI(de\kAfun howold (name)
        !           352:    \h'|\nAu'\kC(terpr)
        !           353:    \h'|\nCu'\kB(load #\kA+(or ucb ucsd) "/usr/lib/lisp/ages.l"
        !           354:           \h'|\nAu'#+cmu "/usr/lisp/doc/ages.l")
        !           355:    \h'|\nBu'\kA(patom name)
        !           356:    \h'|\nBu'\kA(patom " is ")
        !           357:    \h'|\nAu'\kB(print (cdr (assoc name agefile)))
        !           358:    \h'|\nBu'\kA(patom "years old")
        !           359:    \h'|\nAu'(terpr))\fP
        !           360: .Ee
        !           361: The form
        !           362: .br
        !           363: .tl ''\fI#\-when what\fP''
        !           364: is equivalent to
        !           365: .br
        !           366: .tl ''\fI#+(not when) what\fP''
        !           367: .sh +0 fixnum\ character\ equivalents
        !           368: .lp
        !           369: When working with fixnum equivalents of characters, it is often hard to
        !           370: remember the number corresponding to a character.
        !           371: The form
        !           372: .br
        !           373: .tl ''\fI#/c\fP''
        !           374: is equivalent to the fixnum representation of character c.
        !           375: .Eb
        !           376: ; a function which returns t if the user types y else it returns nil.
        !           377: ;
        !           378: \-> \fI(de\kBfun yesorno nil
        !           379:    \h'|\nBu'(progn \kA(ans)
        !           380:           \h'|\nAu'\kB(setq ans (tyi))
        !           381:           \h'|\nBu'(cond \kA((equal ans #/y) t)
        !           382:                 \h'|\nAu'(t nil))))\fP
        !           383: .Ee
        !           384: .sh +0 read\ time\ evaluation
        !           385: .lp
        !           386: Occasionally you want to express a constant as a Lisp expression, yet you
        !           387: don't want to pay the penalty of evaluating this expression each time it
        !           388: is referenced.
        !           389: The form
        !           390: .br
        !           391: .tl ''\fI#.expression\fP''
        !           392: evaluates the expression at read time and returns its value.
        !           393: .Eb
        !           394: ; a function to test if any of bits 1 3 or 12 are set in a fixnum.
        !           395: ;
        !           396: \-> \fI(de\kCfun testit (num)
        !           397:    \h'|\nCu'(cond \kA(\kB(zerop (boole 1 num #.(+ (lsh 1 1) (lsh 1 3) (lsh 1 12))))
        !           398:           \h'|\nBu'nil)
        !           399:          \h'|\nAu'(t t)))\fP
        !           400: .Ee
        !           401: .sh 2 fclosures
        !           402: .pp
        !           403: Fclosures are a type of functional object.
        !           404: The purpose is to remember the values of some variables 
        !           405: between invocations of the functional object and to protect this
        !           406: data from being inadvertently overwritten by other Lisp functions.
        !           407: Fortran programs usually exhibit this behavior for their variables.
        !           408: (In fact, some versions of Fortran would require the
        !           409: variables to be in COMMON).
        !           410: Thus it is easy to write a linear congruent random number generator
        !           411: in Fortran, merely by keeping the seed as a variable in the function.
        !           412: It is much more risky to do so in Lisp, since any special variable you
        !           413: picked, might be used by some other function.
        !           414: Fclosures are an attempt to provide most of the same functionality as
        !           415: closures in Lisp Machine Lisp, to users of
        !           416: .Fr .
        !           417: Fclosures are related to closures in this way:
        !           418: .br
        !           419: (fclosure '(a b) 'foo) <==>
        !           420: .br
        !           421:        (let ((a a) (b b)) (closure '(a b) 'foo))
        !           422: .sh 3 an\ example
        !           423: .sp 1v
        !           424: .in 0
        !           425: .nf
        !           426: .sz -2
        !           427: .hl
        !           428: % \fBlisp\fP
        !           429: Franz Lisp, Opus 38.60
        !           430: \->\fB(defun code (me count)
        !           431:   (print (list 'in x))
        !           432:   (setq x (+ 1 x))
        !           433:   (cond ((greaterp count 1) (funcall me me (sub1 count))))
        !           434:   (print (list 'out x)))\fP
        !           435: code
        !           436: \->\fB(defun tester (object count)
        !           437:   (funcall object object count) (terpri))\fP
        !           438: tester
        !           439: \->\fB(setq x 0)\fP
        !           440: 0
        !           441: \->\fB(setq z (fclosure '(x) 'code))\fP
        !           442: fclosure[8]
        !           443: \->\fB (tester z 3)\fP
        !           444: (in 0)(in 1)(in 2)(out 3)(out 3)(out 3)
        !           445: nil
        !           446: \->\fBx\fP
        !           447: 0
        !           448: .hl
        !           449: .fi
        !           450: .sz +2
        !           451: .sp 3v
        !           452: .pp
        !           453: The function \fIfclosure\fP creates a new object
        !           454: that we will call an fclosure,
        !           455: (although it is actually a vector).
        !           456: The fclosure contains a functional object, and a set of symbols and
        !           457: values for the symbols.  In the above example, the fclosure functional
        !           458: object is the function code.
        !           459: The set of symbols and values just contains the symbol `x' and
        !           460: zero, the value of `x' when the fclosure was created.
        !           461: .lp
        !           462: When an fclosure is funcall'ed:
        !           463: .ip 1)
        !           464: The Lisp system lambda binds the symbols in the fclosure to their values in the fclosure.
        !           465: .ip 2)
        !           466: It continues the funcall on the functional object of the fclosure.
        !           467: .ip 3)
        !           468: Finally, it un-lambda binds the symbols in the fclosure and at the
        !           469: same time stores the current values of the symbols in the fclosure.
        !           470: .sp 1v
        !           471: .pp
        !           472: Notice that the fclosure is saving the value of the symbol `x'.
        !           473: Each time a fclosure is created, new space is allocated for saving
        !           474: the values of the symbols. Thus if we execute fclosure again, over
        !           475: the same function, we can have two independent counters:
        !           476: .sp 1v
        !           477: .in 0
        !           478: .nf
        !           479: .sz -2
        !           480: .hl
        !           481: \-> \fB(setq zz (fclosure '(x) 'code))\fP
        !           482: fclosure[1]
        !           483: \-> \fB(tester zz 2)\fP
        !           484: (in 0)(in 1)(out 2)(out 2)
        !           485: \-> \fB(tester zz 2)\fP
        !           486: (in 2)(in 3)(out 4)(out 4)
        !           487: \-> \fB(tester z 3)\fP
        !           488: (in 3)(in 4)(in 5)(out 6)(out 6)(out 6)
        !           489: .hl
        !           490: .fi
        !           491: .sz +2
        !           492: .sp 3v
        !           493: .sh 3 useful\ functions
        !           494: .pp
        !           495: Here are some quick some summaries of functions dealing with closures.
        !           496: They are more formally defined in \(sc2.8.4.
        !           497: To recap, fclosures are made by
        !           498: \fI(fclosure 'l_vars 'g_funcobj)\fP.
        !           499: l_vars is a list of symbols (not containing nil),
        !           500: g_funcobj is any object that can be funcalled.
        !           501: (Objects which can be funcalled, include compiled Lisp functions,
        !           502: lambda expressions, symbols, foreign functions, etc.)
        !           503: In general, if you want a compiled function to be closed over a
        !           504: variable, you must declare the variable to be special within the function.
        !           505: Another example would be:
        !           506: .(l
        !           507:        (fclosure '(a b) #'(lambda (x) (plus x a)))
        !           508: .)l
        !           509: Here, the #' construction will make the compiler compile the lambda expression.
        !           510: .pp
        !           511: There are times when you want to share variables between fclosures.
        !           512: This can be done if the fclosures are created at the same time using
        !           513: \fIfclosure-list\fP.
        !           514: The function \fIfclosure-alist\fP returns an assoc list giving
        !           515: the symbols and values in the fclosure.  The predicate
        !           516: \fIfclosurep\fP returns t iff its argument is a fclosure.
        !           517: Other functions imported from Lisp Machine Lisp are
        !           518: .i symeval-in-fclosure,
        !           519: .i let-fclosed,
        !           520: and
        !           521: .i set-in-fclosure.
        !           522: Lastly, the function \fIfclosure-function\fP returns the function argument.
        !           523: .sh 3 internal\ structure
        !           524: .pp
        !           525: Currently, closures are implemented as vectors, with property being the
        !           526: symbol fclosure.  The functional object is the first entry.
        !           527: The remaining entries are structures which point to the symbols
        !           528: and values for the closure, (with a reference count to determine
        !           529: if a recursive closure is active).
        !           530: .sh 2 foreign\ subroutines\ and\ functions
        !           531: .pp
        !           532: .Fr 
        !           533: has the ability to dynamically load object files produced by other compilers
        !           534: and to call functions defined in those files.
        !           535: These functions are called 
        !           536: .i foreign
        !           537: functions.*
        !           538: .(f
        !           539: *This topic is also discussed in Report PAM-124 of the Center for
        !           540: Pure and Applied Mathematics, UCB, entitled ``Parlez-Vous Franz?
        !           541: An Informal Introduction to Interfacing Foreign Functions to Franz LISP'',
        !           542: by James R. Larus
        !           543: .)f
        !           544: There are seven types of foreign functions.
        !           545: They are characterized by
        !           546: the type of result they return, and by differences in the interpretation
        !           547: of their arguments.
        !           548: They come from two families: a group suited for languages which pass
        !           549: arguments by reference (e.g. Fortran), and a group suited for languages
        !           550: which pass arguments by value (e.g. C).
        !           551: .sp 1v
        !           552: .lp
        !           553: There are four types in the first group:
        !           554: .ip \fBsubroutine\fP
        !           555: This does not return anything. 
        !           556: The Lisp system
        !           557: always returns t after calling a subroutine.
        !           558: .ip \fBfunction\fP
        !           559: This returns whatever the function returns.
        !           560: This must be a valid Lisp object or it may cause the Lisp system to fail.
        !           561: .ip \fBinteger-function\fP
        !           562: This returns an integer which the Lisp system makes into a fixnum and returns.
        !           563: .ip \fBreal-function\fP
        !           564: This returns a double precision real number which the Lisp
        !           565: system makes into a flonum and returns.
        !           566: .sp 1v
        !           567: .lp
        !           568: There are three types in the second group:
        !           569: .ip \fBc-function\fP
        !           570: This is like an integer function, except for its different interpretation
        !           571: of arguments.
        !           572: .ip \fBdouble-c-function\fP
        !           573: This is like a real-function.
        !           574: .ip \fBvector-c-function\fP
        !           575: This is for C functions which return a structure.
        !           576: The first argument to such functions must be a vector (of type vectori),
        !           577: into which the result is stored.
        !           578: The second Lisp argument
        !           579: becomes the first argument to the C function, and so on
        !           580: .lp
        !           581: A foreign function is accessed through a binary object just like a 
        !           582: compiled Lisp function.
        !           583: The difference is that the discipline field of a binary object
        !           584: for a foreign function is a string 
        !           585: whose first character is given in the following table:
        !           586: .(b
        !           587: .TS
        !           588: box center ;
        !           589: c | c .
        !           590: letter type
        !           591: =
        !           592: s      subroutine
        !           593: _
        !           594: f      function
        !           595: _
        !           596: i      integer-function
        !           597: _
        !           598: r      real-function.
        !           599: _
        !           600: c      c-function
        !           601: _
        !           602: v      vector-c-function
        !           603: _
        !           604: d      double-c-function
        !           605: _
        !           606: .TE
        !           607: .)b
        !           608: Two functions are provided for setting-up foreign functions.
        !           609: .i Cfasl
        !           610: loads an object file into the Lisp system and sets up one foreign
        !           611: function binary object.
        !           612: If there are more than one function in an object file, 
        !           613: .i getaddress
        !           614: can be used to set up additional foreign function objects.
        !           615: .pp
        !           616: Foreign  functions are called just like other functions, e.g 
        !           617: \fI(funname\ arg1\ arg2)\fP.
        !           618: When a function in the Fortran group is called,
        !           619: the arguments are evaluated and then examined.
        !           620: List, hunk and symbol arguments are passed unchanged to 
        !           621: the foreign function.
        !           622: Fixnum and flonum arguments are copied into a temporary location and
        !           623: a pointer to the value is passed (this is because Fortran uses call
        !           624: by reference and it is dangerous to modify the contents of a fixnum
        !           625: or flonum which something else might point to).
        !           626: If the argument is an array object,
        !           627: the data field of the array object is
        !           628: passed to the foreign function
        !           629: (This is the easiest way to send large
        !           630: amounts of data to and receive large amounts of data from a foreign
        !           631: function).
        !           632: If a binary object is an argument, the entry field of that object is
        !           633: passed to the foreign function (the entry field is the address of a function,
        !           634: so this amounts to passing a function as an argument).
        !           635: .pp
        !           636: When a function in the C group is called,
        !           637: fixnum and flownum arguments are passed by value.
        !           638: For almost all other arguments,
        !           639: the address is merely provided to the C routine.
        !           640: The only exception arises when you want to invoke a C routine
        !           641: which expects a ``structure'' argument.  Recall that a (rarely used)
        !           642: feature of the C language is the ability to pass structures by value.
        !           643: This copies the structure onto the stack.  Since the Franz's nearest
        !           644: equivalent to a C structure is a vector, we provide an escape clause
        !           645: to copy the contents of an immediate-type vector by value.  If the
        !           646: property field of a vectori argument, is the symbol
        !           647: \*(lqvalue-structure-argument\*(rq,
        !           648: then the binary data of this immediate-type vector is copied
        !           649: into the argument list of the C routine.
        !           650: .pp
        !           651: The method a foreign function uses to access the arguments provided 
        !           652: by Lisp is dependent on the language of the foreign function.
        !           653: The following scripts demonstrate how how Lisp can interact with three
        !           654: languages: C, Pascal and Fortran.
        !           655: C and Pascal have pointer types and the first script shows how to use
        !           656: pointers to extract information from Lisp objects.
        !           657: There are two functions defined for each language.
        !           658: The first (cfoo in C, pfoo in Pascal) is given four arguments, a 
        !           659: fixnum, a flonum-block array, a hunk of at least two
        !           660: fixnums and a list of 
        !           661: at least two fixnums.
        !           662: To demonstrate that the values were passed, each ?foo function prints
        !           663: its arguments (or parts of them).
        !           664: The ?foo function then modifies the second element of 
        !           665: the flonum-block array and returns a 3 to Lisp.
        !           666: The second function (cmemq in C, pmemq in Pascal) acts just like the
        !           667: Lisp
        !           668: .i memq
        !           669: function (except it won't work for fixnums whereas the lisp 
        !           670: .i memq
        !           671: will work for small fixnums).
        !           672: In the script, typed input is in 
        !           673: .b bold ,
        !           674: computer output is in roman
        !           675: and comments are in
        !           676: .i italic.
        !           677: .in 0
        !           678: .nf
        !           679: .sp 2v
        !           680: .sz -2
        !           681: .hl
        !           682: \fIThese are the C coded functions  \fP
        !           683: % \fBcat ch8auxc.c\fP
        !           684: /* demonstration of c coded foreign integer-function */
        !           685: 
        !           686: /* the following will be used to extract fixnums out of a list of fixnums */
        !           687: struct listoffixnumscell
        !           688: {    struct listoffixnumscell *cdr;
        !           689:      int *fixnum;
        !           690: };
        !           691: 
        !           692: struct listcell
        !           693: {      struct listcell *cdr;
        !           694:        int car;
        !           695: };
        !           696: 
        !           697: cfoo(a,b,c,d)
        !           698: int *a;
        !           699: double b[];
        !           700: int *c[];
        !           701: struct listoffixnumscell *d;
        !           702: {
        !           703:     printf("a: %d, b[0]: %f, b[1]: %f\n", *a, b[0], b[1]);
        !           704:     printf(" c (first): %d   c (second): %d\n",
        !           705:               *c[0],*c[1]);
        !           706:     printf(" ( %d %d ... )\n ", *(d->fixnum), *(d->cdr->fixnum));
        !           707:     b[1] = 3.1415926;
        !           708:     return(3);
        !           709: }
        !           710: 
        !           711: struct listcell *
        !           712: cmemq(element,list)
        !           713: int element;
        !           714: struct listcell *list;
        !           715: {   
        !           716:    for( ; list && element != list->car ;  list = list->cdr);
        !           717:    return(list);
        !           718: }
        !           719: .sp 2v
        !           720: \fIThese are the Pascal coded functions \fP
        !           721: % \fBcat ch8auxp.p\fP
        !           722: type   pinteger = ^integer;
        !           723:        realarray = array[0..10] of real;
        !           724:        pintarray = array[0..10] of pinteger;
        !           725:        listoffixnumscell = record  
        !           726:                                cdr  : ^listoffixnumscell;
        !           727:                                fixnum : pinteger;
        !           728:                            end;
        !           729:        plistcell = ^listcell;
        !           730:        listcell = record
        !           731:                      cdr : plistcell;
        !           732:                      car : integer;
        !           733:                   end;
        !           734: 
        !           735: function pfoo ( var a : integer ; 
        !           736:                var b : realarray;
        !           737:                var c : pintarray;
        !           738:                var d : listoffixnumscell) : integer;
        !           739: begin
        !           740:    writeln(' a:',a, ' b[0]:', b[0], ' b[1]:', b[1]);
        !           741:    writeln(' c (first):', c[0]^,' c (second):', c[1]^);
        !           742:    writeln(' ( ', d.fixnum^, d.cdr^.fixnum^, ' ...) ');
        !           743:    b[1] := 3.1415926;
        !           744:    pfoo := 3
        !           745: end ;
        !           746: 
        !           747: { the function pmemq looks for the Lisp pointer given as the first argument
        !           748:   in the list pointed to by the second argument.
        !           749:   Note that we declare " a : integer " instead of " var a : integer " since
        !           750:   we are interested in the pointer value instead of what it points to (which
        !           751:   could be any Lisp object)
        !           752: }
        !           753: function pmemq( a : integer; list : plistcell) : plistcell;
        !           754: begin
        !           755:  while (list <> nil) and (list^.car <> a) do list := list^.cdr;
        !           756:  pmemq := list;
        !           757: end ;
        !           758: .sp 2v
        !           759: \fIThe files are compiled\fP
        !           760: % \fBcc -c ch8auxc.c\fP
        !           761: 1.0u 1.2s 0:15 14% 30+39k 33+20io 147pf+0w
        !           762: % \fBpc -c ch8auxp.p\fP
        !           763: 3.0u 1.7s 0:37 12% 27+32k 53+32io 143pf+0w
        !           764: .sp 2v
        !           765: % \fBlisp\fP
        !           766: Franz Lisp, Opus 38.60
        !           767: .ft I
        !           768: .fi
        !           769: First the files are loaded and we set up one foreign function binary.
        !           770: We have two functions in each file so we must choose one to tell cfasl about.
        !           771: The choice is arbitrary.
        !           772: .ft P
        !           773: .br 
        !           774: .nf
        !           775: \->\fB (cfasl 'ch8auxc.o '_cfoo 'cfoo "integer-function")\fP
        !           776: /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxc.o -e _cfoo -o /tmp/Li7055.0  -lc
        !           777: #63000-"integer-function"
        !           778: \->\fB (cfasl 'ch8auxp.o '_pfoo 'pfoo "integer-function" "-lpc")\fP
        !           779: /usr/lib/lisp/nld -N -A /tmp/Li7055.0 -T 63200 ch8auxp.o -e _pfoo -o /tmp/Li7055.1 -lpc -lc
        !           780: #63200-"integer-function"
        !           781: .ft I
        !           782: Here we set up the other foreign function binary objects
        !           783: .ft P
        !           784: \->\fB (getaddress '_cmemq 'cmemq "function" '_pmemq 'pmemq "function")\fP
        !           785: #6306c-"function"
        !           786: .ft I
        !           787: .fi
        !           788: We want to create and initialize an array to pass to the cfoo function.
        !           789: In this case we create an unnamed array and store it in the value cell of
        !           790: testarr. 
        !           791: When we create an array to pass to the Pascal program we will use a named
        !           792: array just to demonstrate the different way that named and unnamed arrays
        !           793: are created and accessed.
        !           794: .br
        !           795: .nf
        !           796: .ft P
        !           797: \->\fB (setq testarr (array nil flonum-block 2))\fP
        !           798: array[2]
        !           799: \->\fB (store (funcall testarr 0) 1.234)\fP
        !           800: 1.234
        !           801: \->\fB (store (funcall testarr 1) 5.678)\fP
        !           802: 5.678
        !           803: \->\fB (cfoo 385 testarr (hunk 10 11 13 14) '(15 16 17))\fP
        !           804: a: 385, b[0]: 1.234000, b[1]: 5.678000
        !           805:  c (first): 10   c (second): 11
        !           806:  ( 15 16 ... )
        !           807:  3
        !           808: .ft I
        !           809: .fi
        !           810: Note that cfoo has returned 3 as it should.
        !           811: It also had the side effect of changing the second value of the array to
        !           812: 3.1415926  which check next.
        !           813: .br
        !           814: .nf
        !           815: .ft P
        !           816: \->\fB (funcall testarr 1)\fP
        !           817: 3.1415926
        !           818: .sp 2v
        !           819: .fi
        !           820: .ft I
        !           821: In preparation for calling pfoo we create an array.
        !           822: .ft P
        !           823: .nf
        !           824: \->\fB (array test flonum-block 2)\fP
        !           825: array[2]
        !           826: \->\fB (store (test 0) 1.234)\fP
        !           827: 1.234
        !           828: \->\fB (store (test 1) 5.678)\fP
        !           829: 5.678
        !           830: \->\fB (pfoo 385 (getd 'test) (hunk 10 11 13 14) '(15 16 17))\fP
        !           831:  a:       385 b[0]:  1.23400000000000E+00 b[1]:  5.67800000000000E+00
        !           832:  c (first):        10 c (second):        11
        !           833:  (         15        16 ...) 
        !           834: 3
        !           835: \->\fB (test 1)\fP
        !           836: 3.1415926
        !           837: .sp 1v
        !           838: \fI Now to test out the memq's
        !           839: \-> \fB(cmemq 'a '(b c a d e f))\fP
        !           840: (a d e f)
        !           841: \-> \fB(pmemq 'e '(a d f g a x))\fP
        !           842: nil
        !           843: .hl
        !           844: .fi
        !           845: .sz +2
        !           846: .sp 3v
        !           847: .pp
        !           848: The Fortran example will be much shorter since in Fortran 
        !           849: you can't follow pointers
        !           850: as you can in other languages.
        !           851: The Fortran function ffoo is given three arguments: a fixnum, a 
        !           852: fixnum-block array and a flonum.
        !           853: These arguments are printed out to verify that they made it and
        !           854: then the first value of the array is modified.
        !           855: The function returns a double precision value which is converted to a flonum
        !           856: by lisp and printed.
        !           857: Note that the entry point corresponding to the Fortran function ffoo is
        !           858: _ffoo_ as opposed to the C and Pascal convention of preceding the name with
        !           859: an underscore.
        !           860: .sp 1v
        !           861: .in 0
        !           862: .nf
        !           863: .sz -2
        !           864: .hl
        !           865: 
        !           866: % \fBcat ch8auxf.f\fP
        !           867:        double precision function ffoo(a,b,c)
        !           868:        integer a,b(10)
        !           869:        double precision c
        !           870:        print 2,a,b(1),b(2),c
        !           871: 2      format(' a=',i4,', b(1)=',i5,', b(2)=',i5,' c=',f6.4)
        !           872:        b(1) = 22
        !           873:        ffoo = 1.23456
        !           874:        return
        !           875:        end
        !           876: % \fBf77 -c ch8auxf.f\fP
        !           877: ch8auxf.f:
        !           878:    ffoo:
        !           879: 0.9u 1.8s 0:12 22% 20+22k 54+48io 158pf+0w
        !           880: % \fBlisp\fP
        !           881: Franz Lisp, Opus 38.60
        !           882: \-> \fB(cfasl 'ch8auxf.o '_ffoo_ 'ffoo "real-function" "-lF77 -lI77")\fP
        !           883: /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxf.o -e _ffoo_ 
        !           884: -o /tmp/Li11066.0 -lF77 -lI77 -lc
        !           885: #6307c-"real-function"
        !           886: .sp 1v
        !           887: \-> \fB(array test fixnum-block 2)\fP
        !           888: array[2]
        !           889: \->\fB (store (test 0) 10)\fP
        !           890: 10
        !           891: \-> \fB(store (test 1) 11)\fP
        !           892: 11
        !           893: \-> \fB(ffoo 385 (getd 'test) 5.678)\fP
        !           894:  a= 385, b(1)=   10, b(2)=   11 c=5.6780
        !           895: 1.234559893608093
        !           896: \-> \fB(test 0)\fP
        !           897: 22
        !           898: 
        !           899: .hl

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.