{Begin SubSec Function Definition} {title Function Definition} {Text {Tag FunctionDefinition} Function definitions are stored in a "function definition cell"{index *PRIMARY* function definition cell} associated with each litatom. This cell is directly accessible via the two functions {fn PUTD} and {fn GETD}, but it is usually easier to define functions with {fn DEFINEQ} ({PageRef Fn DEFINEQ}). {FnDef {FnName GETD} {FnArgs FN} {Text Returns the function definition of {arg FN}. Returns {lisp NIL} if {arg FN} is not a litatom, or has no definition. {Tag EQPCompiledCode} {fn GETD} of a compiled function constructs a pointer to the definition, with the result that two successive calls do not necessarily produce {fn EQ} results. {fn EQP} or {fn EQUAL} must be used to compare compiled definitions. }} {note Removed FGETD from documentation! FGETD FN Faster version of {fn GETD}. Interpreted, generates an error, {lisp BAD ARGUMENT - FGETD},{index BAD ARGUMENT - FGETD Error} if {arg FN} is not a litatom. {fn FGETD} is intended primarily to check whether a function {it has} a definition, rather than to obtain the definition. Therefore, in Interlisp-10, {fn FGETD} of a {lisp SUBR} returns just the address of the function definition, not the dotted pair returned by {fn GETD}, thereby saving the {fn CONS}. } {FnDef {FnName PUTD} {FnArgs FN DEF {anonarg}} {Text Puts {arg DEF} into {arg FN}'s function cell, and returns {arg DEF}. Generates an error, {lisp ARG NOT LITATOM,} if {arg FN} is not a litatom. Generates an error, {lisp ILLEGAL ARG}, if {arg DEF} is a string, number, or a litatom other than {lisp NIL}.{index ILLEGAL ARG Error}{index ARG NOT LITATOM Error} }} {note: removed these guys too {FnDef {FnName PUTDQ} {FnArgs FN DEF} {Type NLAMBDA} {Text Nlambda version of {fn PUTD}; both arguments are unevaluated. Returns {arg FN}. }} {FnDef {FnName PUTDQ?} {FnArgs FN DEF} {Type NLAMBDA} {Text If {arg FN} is not defined, same as {fn PUTDQ}. Otherwise, does nothing and returns {lisp NIL}. }} end removal} {FnDef {FnName MOVD} {FnArgs FROM TO COPYFLG} {Text Moves the definition of {arg FROM} to {arg TO}, i.e., redefines {arg TO}. If {arg COPYFLG}={lisp T}, a {fn COPY} of the definition of {arg FROM} is used. {arg COPYFLG}={lisp T} is only meaningful for {lisp EXPR}s, although {fn MOVD} works for compiled functions and {lisp SUBR}s as well. {fn MOVD} returns {arg TO}. See {fn COPYDEF} on {PageRef COPYDEF} for a higher-level function which only moves {lisp EXPR}s, but works also for variables, records, etc. }} {FnDef {FnName MOVD?} {FnArgs FROM TO COPYFLG} {Text If {arg TO} is not defined, same as {lisp (MOVD {arg FROM} {arg TO} {arg COPYFLG})}. Otherwise, does nothing and returns {lisp NIL}. }} {FnDef {FnName DEFINEQ} {FnArgs X{SUB 1} X{SUB 2} {ellipsis} X{SUB N}} {Type NOSPREAD NLAMBDA} {Text {fn DEFINEQ} is the function normally used for defining functions. It takes an indefinite number of arguments which are not evaluated. Each {arg X{SUB i}} must be a list defining one function, of the form {lisp ({arg NAME} {arg DEFINITION})}. For example: {lispcode (DEFINEQ (DOUBLE (LAMBDA (X) (IPLUS X X))) )} The above expression will define the function {lisp DOUBLE} with the {lisp EXPR} definition {lisp (LAMBDA (X) (IPLUS X X))}. {arg X{SUB i}} may also have the form {lisp ({arg NAME} {arg ARGS} . {arg DEF-BODY})}, in which case an appropriate Lambda {lisp EXPR} will be constructed. Therefore, the above expression is exactly the same as: {lispcode (DEFINEQ (DOUBLE (X) (IPLUS X X)) )} Note that this alternate form can only be used for Lambda functions. The first form must be used to define an Nlambda function. {fn DEFINEQ} returns a list of the names of the functions defined. }} {FnDef {FnName DEFINE} {FnArgs X {anonarg}} {Text Lambda-spread version of {fn DEFINEQ}. Each element of the list {arg X} is itself a list either of the form {lisp ({arg NAME} {arg DEFINITION})} or {lisp ({arg NAME} {arg ARGS} . {arg DEF-BODY})}. {fn DEFINE} will generate an error, {lisp INCORRECT DEFINING FORM},{index INCORRECT DEFINING FORM Error} on encountering an atom where a defining list is expected. }} Note: {fn DEFINE} and {fn DEFINEQ} will operate correctly if the function is already defined and {index BROKEN Prop}{prop BROKEN}, {index ADVISED Prop}{prop ADVISED}, or {index BROKEN-IN Prop}{prop BROKEN-IN}. For expressions involving type-in only, if the time stamp facility{index time stamps} is enabled ({PageRef Tag TimeStamps}), both {fn DEFINE} and {fn DEFINEQ} will stamp the definition with the user's initials and date. {VarDef {Name DFNFLG} {Text {var DFNFLG} is a global variable that effects the operation of {fn DEFINE} (and {fn DEFINEQ}, which calls {fn DEFINE}). If {var DFNFLG}={lisp NIL}, an attempt to {it redefine} a function {arg FN} will cause {fn DEFINE} to print the message {lisp ({arg FN} REDEFINED)} and to save the old definition of {arg FN} using {fn SAVEDEF} before redefining it, except if the old and new definitions are the same (i.e. {fn EQUAL}), the effect is simply a no-op. If {var DFNFLG}={lisp T}, the function is simply redefined. If {var DFNFLG}={lisp PROP}{index *PRIMARY* PROP Litatom} or {lisp ALLPROP},{index *PRIMARY* ALLPROP Litatom} the new definition is stored on the property list under the property {lisp EXPR}.{index *PRIMARY* EXPR Prop} {lisp ALLPROP} affects the operation of {fn RPAQQ} and {fn RPAQ} ({PageRef Fn RPAQ}). {var DFNFLG} is initially {lisp NIL}. {indexX {Name redefined} {Type (printed by system)} {Text {lisp ({arg FN} redefined)} } } {var DFNFLG} is reset by {fn LOAD} ({PageRef Fn LOAD}) to enable various ways of handling the defining of functions and setting of variables when loading a file. For most applications, the user will not reset {var DFNFLG} directly. }} {Begin Note} Date: 16 JAN 1982 1438-PST From: MASINTER.PA Subject: FOO unsaved I went in to fix the system so that, if FOO had an EXPR property and no definition, and you got a u.d.f. FOO, it would unsave FOO's definition even if DFNFLG were PROP. Previously, it would not unsave the definition, but would load in the definition from a file. This has had the side effect that functions will get unsaved even when they are being dwimified, as happens when you do a MAKEFILE. Note that this only matters for DFNFLG=PROP and for functions which are not otherwise defined. I am not sure it is worth fixing, since the behavior is harmless. {End Note} {note do normal users use SAVEDEF and UNSAVEDEF?? Should we document these shorter versions here????} {FnDef {FnName SAVEDEF} {FnArgs FN} {Text Saves the definition of {arg FN} on its property list under the property {index EXPR Prop}{prop EXPR}, {index *PRIMARY* CODE Prop}{prop CODE}, or {index SUBR Prop}{prop SUBR} depending on its {index FNTYP FN}{fn FNTYP}. Returns the property name used. If {index GETD FN}{lisp (GETD {arg FN})} is non-{lisp NIL}, but {lisp (FNTYP {arg FN})}={lisp NIL}, {fn SAVEDEF} saves the definition on the property name {index LIST Prop}{lisp LIST}. This situation can arise when a function is redefined which was originally defined with {index LAMBDA Litatom}{lisp LAMBDA} misspelled or omitted. If {arg FN} is a list, {fn SAVEDEF} operates on each function in the list, and returns a list of the individual values. }} {FnDef {FnName UNSAVEDEF} {FnArgs FN PROP} {Text Restores the definition of {arg FN} from its property list under property {arg PROP} (see {fn SAVEDEF} above). Returns {arg PROP}. If nothing is saved under {arg PROP}, and {arg FN} is defined, returns {lisp ({arg PROP} NOT FOUND)}, otherwise generates an error, {lisp NOT A FUNCTION}.{index NOT A FUNCTION Error} {indexX {Name NOT FOUND} {Type (value of UNSAVEDEF)} {Text {lisp ({arg PROP} NOT FOUND)} } } If {arg PROP} is not given, i.e., {lisp NIL}, {fn UNSAVEDEF} looks under the properties {index EXPR Prop}{lisp EXPR}, {index CODE Prop}{lisp CODE}, and {index SUBR Prop}{lisp SUBR}, in that order. The value of {fn UNSAVEDEF} is the property name, or if nothing is found and {arg FN} is a function, the value is {lisp (NOTHING FOUND)}; otherwise generates an error, {lisp NOT A FUNCTION}.{index NOT A FUNCTION Error} {indexX {Name NOTHING FOUND} {Type (value of UNSAVEDEF)} {Text {lisp (NOTHING FOUND)} } } If {index DFNFLG Var}{var DFNFLG}={lisp NIL}, the current definition of {arg FN}, if any, is saved using {index SAVEDEF FN}{fn SAVEDEF}. Thus one can use {fn UNSAVEDEF} to switch back and forth between two definitions of the same function, keeping one on its property list and the other in the function definition cell. If {arg FN} is a list, {index UNSAVEDEF FN}{fn UNSAVEDEF} operates on each function of the list, and its value is a list of the individual values. }} Both {fn SAVEDEF} and {fn UNSAVEDEF} are redefined in more general terms (see {PageRef Fn SAVEDEF}) to operate on typed definitions of which a function definition is but one example. Thus, their actual argument lists in Interlisp are different than given here. However, when their extra arguments are defaulted to {lisp NIL}, they operate as described above. }{End SubSec Function Definition}