{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}