{Begin SubSec Defining Functions} {title Defining Functions} {Text {index *PRIMARY* Defining functions} {index Function definitions} {Tag FunctionDefinition} {index *PRIMARY* Function definition cells} Function definitions are stored in a "function definition cell" associated with each litatom. This cell is directly accessible via the two functions {fn PUTD} and {fn GETD} ({PageRef Fn PUTD}), but it is usually easier to define functions with {fn DEFINEQ}: {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 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 expr definition 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 {index time stamps}time stamp facility is enabled ({PageRef Term Time Stamps}), both {fn DEFINE} and {fn DEFINEQ} will stamp the definition with the user's initials and date. {VarDef {Name UNSAFE.TO.MODIFY.FNS} {Text Value is a list of functions that should not be redefined, because doing so may cause unusual bugs (or crash the system!). If the user tries to modify a function on this list (using {fn DEFINEQ}, {fn TRACE}, etc), the system will print "{lisp Warning: {arg XXX} may be safe to modify -- continue?}" If the users types "Yes", the function is modified, otherwise an error occurs. This provides a measure of safety for novices who may accidently redefine important system functions. Users can add their own functions onto this list. {index *PRIMARY* Backslash functions} {index *PRIMARY* \ functions} Note: By convention, all functions starting with the character backslash ("\") are system internal functions, which should never be redefined or modified by the user. Backslash functions are not on {var UNSAFE.TO.MODIFY.FNS}, so trying to redefine them will not cause a warning. }} {VarDef {Name DFNFLG} {Text {var DFNFLG} is a global variable that effects the operation of {fn DEFINEQ} and {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} ({PageRef Fn SAVEDEF}) before redefining it (except if the old and new definitions are {fn EQUAL}, inwhich case 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 {index *PRIMARY* EXPR Prop}{lisp EXPR}. {lisp ALLPROP} also 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. Note: The compiler does NOT respect the value of {var DFNFLG} when it redefines functions to their compiled definitions (see {PageRef (Compiler Question) REDEFINE?}). Therefore, if you set {var DFNFLG} to {lisp PROP} to completely avoid inadvertantly redefining something in your running system, you {it must} use compile mode {lisp F}, not {lisp ST}. }} Note: The functions {fn SAVEDEF} and {fn UNSAVEDEF} ({PageRef Fn SAVEDEF}) can be useful for "saving" and restoring function definitions from property lists. {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. }} {Begin Note FGETD} Removed FGETD from documentation! FGETD FN Faster version of GETD. Interpreted, generates an error, BAD ARGUMENT - FGETD, if FN is not a litatom. FGETD is intended primarily to check whether a function has a definition, rather than to obtain the definition. Therefore, in Interlisp-10, FGETD of a SUBR returns just the address of the function definition, not the dotted pair returned by GETD, thereby saving the CONS. {End Note FGETD} {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} }} {Begin Note} removed these guys too (PUTDQ FN DEF) Nlambda version of PUTD; both arguments are unevaluated. Returns FN. (PUTDQ? FN DEF) If FN is not defined, same as PUTDQ. Otherwise, does nothing and returns NIL. {End Note} {FnDef {FnName MOVD} {FnArgs FROM TO COPYFLG {anonarg}} {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 expr definitions, although {fn MOVD} works for compiled functions as well. {fn MOVD} returns {arg TO}. {fn COPYDEF} ({PageRef Fn COPYDEF}) is a higher-level function that only moves expr definitions, but works also for variables, records, etc. }} {FnDef {FnName MOVD?} {FnArgs FROM TO COPYFLG {anonarg}} {Text If {arg TO} is not defined, same as {lisp (MOVD {arg FROM} {arg TO} {arg COPYFLG})}. Otherwise, does nothing and returns {lisp NIL}. }} }{End SubSec Defining Functions}