CCCCHHHHAAAAPPPPTTTTEEEERRRR 8888 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888....1111.... vvvvaaaalllliiiidddd ffffuuuunnnnccccttttiiiioooonnnn oooobbbbjjjjeeeeccccttttssss There are many different objects which can occupy the function field of a symbol object. The following table shows all of the possibilities, how to recognize them and where to look for documentation. 8_____________________________________________________________ informal name object type documentation 8__________________________________________________________________________________________________________________________ interpreted list with _c_a_r 8.2 lambda function _e_q to lambda 8_____________________________________________________________ interpreted list with _c_a_r 8.2 nlambda function _e_q to nlambda 8_____________________________________________________________ interpreted list with _c_a_r 8.2 lexpr function _e_q to lexpr 8_____________________________________________________________ interpreted list with _c_a_r 8.3 macro _e_q to macro 8_____________________________________________________________ compiled binary with discipline 8.2 lambda or lexpr _e_q to lambda function 8_____________________________________________________________ compiled binary with discipline 8.2 nlambda function _e_q to nlambda 8_____________________________________________________________ compiled binary with discipline 8.3 macro _e_q to macro 8_____________________________________________________________ foreign binary with discipline 8.4 subroutine of "subroutine"[] 8_____________________________________________________________ foreign binary with discipline 8.4 function of "function"[] 8_____________________________________________________________ foreign binary with discipline 8.4 integer function of "integer-function"[] 8_____________________________________________________________ foreign binary with discipline 8.4 real function of "real-function"[] 8_____________________________________________________________ array array object 9 8_____________________________________________________________ 7|8|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7| 9 |8|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7| 9 |8|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7| 9 |8|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7| 99 9FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----1111 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----2222 8888....2222.... ffffuuuunnnnccccttttiiiioooonnnnssss 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 func- tions which evaluate their arguments in special ways are also nlambdas (e.g _c_o_n_d, _d_o, _o_r). 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 will be passed. Then the first thing the nlambda function does is map _e_v_a_l over the list of unevaluated arguments it has been passed. This is usually the wrong thing to do as it won't 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 then accesses the arguments using the _a_r_g function. When a function is compiled, _s_p_e_c_i_a_l declarations may be needed to preserve its behavior. An argument is not lambda-bound to the name of the corresponding formal parame- ter unless that formal parameter has been declared _s_p_e_c_i_a_l (see 12.3.2.2). Lambda and lexpr functions both compile into a binary object with a discipline of lambda. However, a compiled lexpr still acts like an interpreted lexpr. 8888....3333.... mmmmaaaaccccrrrroooossss An important features of Lisp is its ability to manipu- late 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 languages into Lisp. For example, there are macro packages which allow one to create records (ala Pascal) and refer to elements of those records ____________________ 9 []Only the first character of the string is significant (i.e "s" is ok for "subroutine") 9 Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----3333 by the key names.[] Another popular use for macros is to create more readable control structures which expand into _c_o_n_d, _o_r and _a_n_d. One such example is the If macro in the jkfmacs.l package. It allows you to write (_I_f (_e_q_u_a_l _n_u_m_b _0) _t_h_e_n (_p_r_i_n_t '_z_e_r_o) (_t_e_r_p_r) _e_l_s_e_i_f (_e_q_u_a_l _n_u_m_b _1) _t_h_e_n (_p_r_i_n_t '_o_n_e) (_t_e_r_p_r) _e_l_s_e (_p_r_i_n_t '|_I _g_i_v_e _u_p|)) which expands to (_c_o_n_d ((_e_q_u_a_l _n_u_m_b _0) (_p_r_i_n_t '_z_e_r_o) (_t_e_r_p_r)) ((_e_q_u_a_l _n_u_m_b _1) (_p_r_i_n_t '_o_n_e) (_t_e_r_p_r)) (_t (_p_r_i_n_t '|_I _g_i_v_e _u_p|))) 8888....3333....1111.... mmmmaaaaccccrrrroooo ffffoooorrrrmmmmssss A macro is a function which accepts a Lisp expression as input and returns another Lisp expression. The action the macro takes is called macro expansion. Here is a simple example: -> (_d_e_f _f_i_r_s_t (_m_a_c_r_o (_x) (_c_o_n_s '_c_a_r (_c_d_r _x)))) first -> (_f_i_r_s_t '(_a _b _c)) a -> (_a_p_p_l_y '_f_i_r_s_t '(_f_i_r_s_t '(_a _b _c))) (car '(a b c)) The first input line defines a macro called _f_i_r_s_t. Notice that the macro has one formal parameter, _x. On the second input line, we ask the interpreter to evaluate (_f_i_r_s_t '(_a _b _c)). _E_v_a_l sees that _f_i_r_s_t has a function definition of type macro so it evaluates _f_i_r_s_t's definition passing to _f_i_r_s_t as an argument the form _e_v_a_l itself was trying to evaluate: (_f_i_r_s_t '(_a _b _c)). The _f_i_r_s_t macro chops off the car of the argument with _c_d_r, cons' a _c_a_r at the beginning of the list and returns (_c_a_r '(_a _b _c)). Now _e_v_a_l evaluates that, and the value is _a which is returned as the value of (_f_i_r_s_t '(_a _b _c)). Thus whenever _e_v_a_l tries to evaluate a list whose car has a macro definition it ends up doing (at least) two operations, one is a call to the macro ____________________ 9 []A record definition macro package especially suited for FRANZ LISP is in the planning stages at Berkeley. At this time the Maclisp _s_t_r_u_c_t package can be used. 9 Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----4444 to let it macro expand the form, and the other is the evaluation of the result of the macro. The result of the macro may be yet another call to a macro, so _e_v_a_l 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 _a_p_p_l_y as shown on the third input line above. 8888....3333....2222.... ddddeeeeffffmmmmaaaaccccrrrroooo The macro _d_e_f_m_a_c_r_o makes it easier to define macros because it allows you to name the arguments to the macro call. For example, suppose we find ourselves often writing code like (_s_e_t_q _s_t_a_c_k (_c_o_n_s _n_e_w_e_l_t _s_t_a_c_k). We could define a macro named _p_u_s_h to do this for us. One way to define it is: -> (_d_e_f _p_u_s_h (_m_a_c_r_o (_x) (_l_i_s_t '_s_e_t_q (_c_a_d_d_r _x) (_l_i_s_t '_c_o_n_s (_c_a_d_r _x) (_c_a_d_d_r _x))))) push then (_p_u_s_h _n_e_w_e_l_t _s_t_a_c_k) will expand to the form mentioned above. The same macro written using defmacro would be: -> (_d_e_f_m_a_c_r_o _p_u_s_h (_v_a_l_u_e _s_t_a_c_k) (_l_i_s_t '_s_e_t_q _s_t_a_c_k (_l_i_s_t '_c_o_n_s _v_a_l_u_e _s_t_a_c_k)) push Defmacro allows you to name the arguments of the macro call, and makes the macro definition look more like a function definition. 8888....3333....3333.... tttthhhheeee bbbbaaaacccckkkkqqqquuuuooootttteeee cccchhhhaaaarrrraaaacccctttteeeerrrr mmmmaaaaccccrrrroooo The default syntax for FRANZ LISP has four characters with associated character macros. One is semicolon for com- ments. Two others are the backquote and comma which are used by the backquote character macro. 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 fixed (quoted). This makes it very use- ful for creating macro definitions. In the simplest case, a backquote acts just like a single quote: ->`(_a _b _c _d _e) (a b c d e) 9 9 Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----5555 If a comma precedes an element of a backquoted list then that element is evaluated and its value is put in the list. ->(_s_e_t_q _d '(_x _y _z)) (x y z) ->`(_a _b _c ,_d _e) (a b c (x y z) e) 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 _a_p_p_e_n_d. ->`(_a _b _c ,@_d _e) (a b c x y z e) Once a list begins with a backquote, the commas may appear anywhere in the list as this example shows: ->`(_a _b (_c _d ,(_c_d_r _d)) (_e _f (_g _h ,@(_c_d_d_r _d) ,@_d))) (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 mac- ros using all the power at our disposal, defmacro and the backquote macro. ->(_d_e_f_m_a_c_r_o _f_i_r_s_t (_l_i_s_t) `(_c_a_r ,_l_i_s_t)) first ->(_d_e_f_m_a_c_r_o _p_u_s_h (_v_a_l_u_e _s_t_a_c_k) `(_s_e_t_q ,_s_t_a_c_k (_c_o_n_s ,_v_a_l_u_e ,_s_t_a_c_k))) stack 8888....3333....4444.... sssshhhhaaaarrrrpppp ssssiiiiggggnnnn cccchhhhaaaarrrraaaacccctttteeeerrrr mmmmaaaaccccrrrroooo 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. 8888....3333....4444....1111.... ccccoooonnnnddddiiiittttiiiioooonnnnaaaallll iiiinnnncccclllluuuussssiiiioooonnnn If you plan to run one source file in more than one environ- ment then you may want to some pieces of code to be included or not included depending on the environment. The C language uses "#ifdef" and "#ifndef" for this purpose, and lisp uses "#+" and "#-". The environment that the sharp sign macro checks is the (_s_t_a_t_u_s _f_e_a_t_u_r_e_s) list which is initialized Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----6666 when the Lisp system is built and which may be altered by (_s_s_t_a_t_u_s _f_e_a_t_u_r_e _f_o_o) and (_s_s_t_a_t_u_s _n_o_f_e_a_t_u_r_e _b_a_r) The form of conditional inclusion is _#_+_w_h_e_n _w_h_a_t where _w_h_e_n is either a symbol or an expression involving symbols and the functions _a_n_d, _o_r, and _n_o_t. The meaning is that _w_h_a_t will only be read in if _w_h_e_n is true. A symbol in _w_h_e_n is true only if it appears in the (_s_t_a_t_u_s _f_e_a_t_u_r_e_s) list. ____________________________________________________ ; 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 ; are different. ; -> (_d_e_f_u_n _h_o_w_o_l_d (_n_a_m_e) (_t_e_r_p_r) (_l_o_a_d #+(_o_r _u_c_b _u_c_s_d) "/_u_s_r/_l_i_b/_l_i_s_p/_a_g_e_s._l" #+_c_m_u "/_u_s_r/_l_i_s_p/_d_o_c/_a_g_e_s._l") (_p_a_t_o_m "_H_e _i_s ") (_p_r_i_n_t (_c_d_r (_a_s_s_o_c _n_a_m_e _a_g_e_f_i_l_e))) (_p_a_t_o_m "_y_e_a_r_s _o_l_d") (_t_e_r_p_r)) ____________________________________________________ The form _#_-_w_h_e_n _w_h_a_t is equivalent to _#_+_(_n_o_t _w_h_e_n_) _w_h_a_t 8888....3333....4444....2222.... ffffiiiixxxxnnnnuuuummmm cccchhhhaaaarrrraaaacccctttteeeerrrr eeeeqqqquuuuiiiivvvvaaaalllleeeennnnttttssss When working with fixnum equivalents of characters it is often hard to remember the number corresponding to a charac- ter. The form _#_/_c is equivalent to the fixnum representation of character c. 9 9 Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----7777 ____________________________________________________ ; a function which returns t if the user types y else it returns nil. ; -> (_d_e_f_u_n _y_e_s_o_r_n_o _n_i_l (_p_r_o_g_n (_a_n_s) (_s_e_t_q _a_n_s (_t_y_i)) (_c_o_n_d ((_e_q_u_a_l _a_n_s #/_y) _t) (_t _n_i_l)))) ____________________________________________________ 8888....3333....4444....3333.... rrrreeeeaaaadddd ttttiiiimmmmeeee eeeevvvvaaaalllluuuuaaaattttiiiioooonnnn 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 is referenced. The form _#_._e_x_p_r_e_s_s_i_o_n 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. ; -> (_d_e_f_u_n _t_e_s_t_i_t (_n_u_m) (_c_o_n_d ((_z_e_r_o_p (_b_o_o_l_e _1 _n_u_m #.(+ (_l_s_h _1 _1) (_l_s_h _1 _3) (_l_s_h _1 _1_2)))) _n_i_l) (_t _t))) ____________________________________________________ 8888....4444.... ffffoooorrrreeeeiiiiggggnnnn ssssuuuubbbbrrrroooouuuuttttiiiinnnneeeessss aaaannnndddd ffffuuuunnnnccccttttiiiioooonnnnssss FRANZ LISP has the ability to dynamically load object files produced by other compilers and then call functions defined in those files. These functions are called _f_o_r_e_i_g_n functions. There are four types of foreign functions and they are characterized by the type of result they return: 9 9 Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----8888 subroutine This does not return anything. The lisp system always returns t after calling a subroutine. function This returns whatever the function returns. This must be a valid lisp object or it may cause the lisp system to fail. integer-function This returns an integer which the lisp system makes into a fixnum and returns. real-function This returns a double precision real number which the lisp system makes into a flonum and returns. A foreign function is accessed through a binary object just like a compiled lisp function. The difference is that the discipline field for a binary object of a foreign function is a string whose first character is either s for a subrou- tine, f for a function, i for an integer-function or r for a real-function. Two functions are provided for the setting up of foreign functions. _C_f_a_s_l loads an object file into the lisp system and sets up one foreign function binary object. If there is more than one function in an object file, _g_e_t_a_d_d_r_e_s_s can be used to set up further foreign func- tion objects. Foreign functions are called just like other func- tions, e.g (_f_u_n_n_a_m_e _a_r_g_1 _a_r_g_2). When one is called, the arguments are evaluated and then examined. List, hunk and symbol arguments are passed unchanged to the foreign func- tion. Fixnum and flonum arguments are copied into a tem- porary 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 an array object is an argument 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 function). 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). The method a foreign function uses to access the argu- ments 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 For- tran. 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. Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----9999 The first (cfoo in C, pfoo in Pascal) is given four argu- ments, a fixnum, a flonum-block array, a hunk of at least two fixnums and a list of at least two fixnums. To demon- strate 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 lisp _m_e_m_q function (except it won't work for fixnums whereas the lisp _m_e_m_q will work for small fixnums). In the script, typed input is in bbbboooolllldddd, computer output is in roman and comments are in _i_t_a_l_i_c. ____________________________________________________________ _T_h_e_s_e _a_r_e _t_h_e _C _c_o_d_e_d _f_u_n_c_t_i_o_n_s % ccccaaaatttt cccchhhh8888aaaauuuuxxxxcccc....cccc /* demonstration of c coded foreign integer-function */ /* the following will be used to extract fixnums out of a list of fixnums */ struct listoffixnumscell { struct listoffixnumscell *cdr; int *fixnum; }; struct listcell { struct listcell *cdr; int car; }; cfoo(a,b,c,d) int *a; double b[]; int *c[]; struct listoffixnumscell *d; { printf("a: %d, b[0]: %f, b[1]: %f0, *a, b[0], b[1]); printf(" c (first): %d c (second): %d0, *c[0],*c[1]); printf(" ( %d %d ... ) ", *(d->fixnum), *(d->cdr->fixnum)); b[1] = 3.1415926; return(3); } struct listcell * cmemq(element,list) int element; struct listcell *list; { for( ; list && element != list->car ; list = list->cdr); return(list); } Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----11110000 _T_h_e_s_e _a_r_e _t_h_e _P_a_s_c_a_l _c_o_d_e_d _f_u_n_c_t_i_o_n_s % ccccaaaatttt cccchhhh8888aaaauuuuxxxxpppp....pppp type pinteger = ^integer; realarray = array[0..10] of real; pintarray = array[0..10] of pinteger; listoffixnumscell = record cdr : ^listoffixnumscell; fixnum : pinteger; end; plistcell = ^listcell; listcell = record cdr : plistcell; car : integer; end; function pfoo ( var a : integer ; var b : realarray; var c : pintarray; var d : listoffixnumscell) : integer; begin 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^, ' ...) '); b[1] := 3.1415926; pfoo := 3 end ; { 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; begin while (list <> nil) and (list^.car <> a) do list := list^.cdr; pmemq := list; end ; _T_h_e _f_i_l_e_s _a_r_e _c_o_m_p_i_l_e_d % cccccccc ----cccc cccchhhh8888aaaauuuuxxxxcccc....cccc 1.0u 1.2s 0:15 14% 30+39k 33+20io 147pf+0w % ppppcccc ----cccc cccchhhh8888aaaauuuuxxxxpppp....pppp 3.0u 1.7s 0:37 12% 27+32k 53+32io 143pf+0w % lllliiiisssspppp Franz Lisp, Opus 33b _F_i_r_s_t _t_h_e _f_i_l_e_s _a_r_e _l_o_a_d_e_d _a_n_d _w_e _s_e_t _u_p _o_n_e _f_o_r_e_i_g_n _f_u_n_c_- _t_i_o_n _b_i_n_a_r_y. _W_e _h_a_v_e _t_w_o _f_u_n_c_t_i_o_n_s _i_n _e_a_c_h _f_i_l_e _s_o _w_e _m_u_s_t _c_h_o_o_s_e _o_n_e _t_o _t_e_l_l _c_f_a_s_l _a_b_o_u_t. _T_h_e _c_h_o_i_c_e _i_s _a_r_b_i_t_r_a_r_y. -> ((((ccccffffaaaassssllll ''''cccchhhh8888aaaauuuuxxxxcccc....oooo ''''____ccccffffoooooooo ''''ccccffffoooooooo """"iiiinnnntttteeeeggggeeeerrrr----ffffuuuunnnnccccttttiiiioooonnnn"""")))) Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----11111111 /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxc.o -e _cfoo -o /tmp/Li7055.0 -lc #63000-"integer-function" -> ((((ccccffffaaaassssllll ''''cccchhhh8888aaaauuuuxxxxpppp....oooo ''''____ppppffffoooooooo ''''ppppffffoooooooo """"iiiinnnntttteeeeggggeeeerrrr----ffffuuuunnnnccccttttiiiioooonnnn"""" """"----llllppppcccc"""")))) /usr/lib/lisp/nld -N -A /tmp/Li7055.0 -T 63200 ch8auxp.o -e _pfoo -o /tmp/Li7055.1 -lpc -lc #63200-"integer-function" _H_e_r_e _w_e _s_e_t _u_p _t_h_e _o_t_h_e_r _f_o_r_e_i_g_n _f_u_n_c_t_i_o_n _b_i_n_a_r_y _o_b_j_e_c_t_s -> ((((ggggeeeettttaaaaddddddddrrrreeeessssssss ''''____ccccmmmmeeeemmmmqqqq ''''ccccmmmmeeeemmmmqqqq """"ffffuuuunnnnccccttttiiiioooonnnn"""" ''''____ppppmmmmeeeemmmmqqqq ''''ppppmmmmeeeemmmmqqqq """"ffffuuuunnnnccccttttiiiioooonnnn"""")))) #6306c-"function" _W_e _w_a_n_t _t_o _c_r_e_a_t_e _a_n_d _i_n_i_t_i_a_l_i_z_e _a_n _a_r_r_a_y _t_o _p_a_s_s _t_o _t_h_e _c_f_o_o _f_u_n_c_t_i_o_n. _I_n _t_h_i_s _c_a_s_e _w_e _c_r_e_a_t_e _a_n _u_n_n_a_m_e_d _a_r_r_a_y _a_n_d _s_t_o_r_e _i_t _i_n _t_h_e _v_a_l_u_e _c_e_l_l _o_f _t_e_s_t_a_r_r. _W_h_e_n _w_e _c_r_e_a_t_e _a_n _a_r_r_a_y _t_o _p_a_s_s _t_o _t_h_e _P_a_s_c_a_l _p_r_o_g_r_a_m _w_e _w_i_l_l _u_s_e _a _n_a_m_e_d _a_r_r_a_y _j_u_s_t _t_o _d_e_m_o_n_s_t_r_a_t_e _t_h_e _d_i_f_f_e_r_e_n_t _w_a_y _t_h_a_t _n_a_m_e_d _a_n_d _u_n_n_a_m_e_d _a_r_r_a_y_s _a_r_e _c_r_e_a_t_e_d _a_n_d _a_c_c_e_s_s_e_d. -> ((((sssseeeettttqqqq tttteeeessssttttaaaarrrrrrrr ((((aaaarrrrrrrraaaayyyy nnnniiiillll fffflllloooonnnnuuuummmm----bbbblllloooocccckkkk 2222)))))))) array[2] -> ((((ssssttttoooorrrreeee ((((ffffuuuunnnnccccaaaallllllll tttteeeessssttttaaaarrrrrrrr 0000)))) 1111....222233334444)))) 1.234 -> ((((ssssttttoooorrrreeee ((((ffffuuuunnnnccccaaaallllllll tttteeeessssttttaaaarrrrrrrr 1111)))) 5555....666677778888)))) 5.678 -> ((((ccccffffoooooooo 333388885555 tttteeeessssttttaaaarrrrrrrr ((((hhhhuuuunnnnkkkk 11110000 11111111 11113333 11114444)))) ''''((((11115555 11116666 11117777)))))))) a: 385, b[0]: 1.234000, b[1]: 5.678000 c (first): 10 c (second): 11 ( 15 16 ... ) 3 _N_o_t_e _t_h_a_t _c_f_o_o _h_a_s _r_e_t_u_r_n_e_d _3 _a_s _i_t _s_h_o_u_l_d. _I_t _a_l_s_o _h_a_d _t_h_e _s_i_d_e _e_f_f_e_c_t _o_f _c_h_a_n_g_i_n_g _t_h_e _s_e_c_o_n_d _v_a_l_u_e _o_f _t_h_e _a_r_r_a_y _t_o _3._1_4_1_5_9_2_6 _w_h_i_c_h _c_h_e_c_k _n_e_x_t. -> ((((ffffuuuunnnnccccaaaallllllll tttteeeessssttttaaaarrrrrrrr 1111)))) 3.1415926 _I_n _p_r_e_p_a_r_a_t_i_o_n _f_o_r _c_a_l_l_i_n_g _p_f_o_o _w_e _c_r_e_a_t_e _a_n _a_r_r_a_y. -> ((((aaaarrrrrrrraaaayyyy tttteeeesssstttt fffflllloooonnnnuuuummmm----bbbblllloooocccckkkk 2222)))) array[2] -> ((((ssssttttoooorrrreeee ((((tttteeeesssstttt 0000)))) 1111....222233334444)))) 1.234 -> ((((ssssttttoooorrrreeee ((((tttteeeesssstttt 1111)))) 5555....666677778888)))) 5.678 -> ((((ppppffffoooooooo 333388885555 ((((ggggeeeettttdddd ''''tttteeeesssstttt)))) ((((hhhhuuuunnnnkkkk 11110000 11111111 11113333 11114444)))) ''''((((11115555 11116666 11117777)))))))) a: 385 b[0]: 1.23400000000000E+00 b[1]: 5.67800000000000E+00 c (first): 10 c (second): 11 ( 15 16 ...) 3 -> ((((tttteeeesssstttt 1111)))) 3.1415926 _N_o_w _t_o _t_e_s_t _o_u_t _t_h_e _m_e_m_q'_s -> ((((ccccmmmmeeeemmmmqqqq ''''aaaa ''''((((bbbb cccc aaaa dddd eeee ffff)))))))) (_a _d _e _f) -> ((((ppppmmmmeeeemmmmqqqq ''''eeee ''''((((aaaa dddd ffff gggg aaaa xxxx)))))))) _n_i_l ____________________________________________________________ Printed: March 23, 1982 FFFFuuuunnnnccccttttiiiioooonnnnssss aaaannnndddd MMMMaaaaccccrrrroooossss 8888----11112222 The Fortran example will be much shorter since in For- tran you can't follow pointers as you can in other languages. The Fortran function ffoo is given three argu- ments: 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 by lisp and printed. 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 an underscore. ____________________________________________________________ % ccccaaaatttt cccchhhh8888aaaauuuuxxxxffff....ffff double precision function ffoo(a,b,c) integer a,b(10) double precision c print 2,a,b(1),b(2),c 2 format(' a=',i4,', b(1)=',i5,', b(2)=',i5,' c=',f6.4) b(1) = 22 ffoo = 1.23456 return end % ffff77777777 ----cccc cccchhhh8888aaaauuuuxxxxffff....ffff ch8auxf.f: ffoo: 0.9u 1.8s 0:12 22% 20+22k 54+48io 158pf+0w % lllliiiisssspppp Franz Lisp, Opus 33b -> ((((ccccffffaaaassssllll ''''cccchhhh8888aaaauuuuxxxxffff....oooo ''''____ffffffffoooooooo____ ''''ffffffffoooooooo """"rrrreeeeaaaallll----ffffuuuunnnnccccttttiiiioooonnnn"""" """"----llllFFFF77777777 ----llllIIII77777777"""")))) /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxf.o -e _ffoo_ -o /tmp/Li11066.0 -lF77 -lI77 -lc #6307c-"real-function" -> ((((aaaarrrrrrrraaaayyyy tttteeeesssstttt ffffiiiixxxxnnnnuuuummmm----bbbblllloooocccckkkk 2222)))) array[2] -> ((((ssssttttoooorrrreeee ((((tttteeeesssstttt 0000)))) 11110000)))) 10 -> ((((ssssttttoooorrrreeee ((((tttteeeesssstttt 1111)))) 11111111)))) 11 -> ((((ffffffffoooooooo 333388885555 ((((ggggeeeettttdddd ''''tttteeeesssstttt)))) 5555....666677778888)))) a= 385, b(1)= 10, b(2)= 11 c=5.6780 1.234559893608093 -> ((((tttteeeesssstttt 0000)))) 22 ____________________________________________________________ 9 9 Printed: March 23, 1982