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