CONCEPT
functions
DESCRIPTION
Functions are named blocks of code which are be called with
a number of argument values, and which return a result value
to the caller.
Functions are defined in an object and are also known as
"local funs" or short "lfuns".
DEFINING A FUNCTION
A function definition takes the form
<modifiers> <type> name ( <arguments> ) {
statements...
}
The parts in detail:
- <modifiers> can be any one of "static", "private", "public"
and "protected" (see modifiers(LPC)), optionally combined
with "varargs" (see varargs(LPC)) and/or "nomask".
If not specified, the function behaves as if it was
specified as "public", but this visibility can be restricted
in derived object through non-public inheritance.
- <type> is the type of the result returned by the function.
If specified as "void", the function is compiled to return
the value 0 under all circumstances. If not specified, the
type is assumed to be "mixed", furthermore typechecking is
disabled for this function.
- name is the name of the function, e.g. "short", or "Nice_Try",
under which it is made known.
- <arguments> is a list of variable definitions in the
normal '<type> <name>' style, separated by comma.
Examples: () : no argument taken
(int a) : takes on integer argument
(mixed a, object *b): takes two arguments, one
arbitrary type, one array of objects.
- { statements... } defines the code for this function. This
is a normal block (see block(LPC)) and as such can define
its own local variables.
DECLARING A FUNCTION
A function declaration makes the name and type of a function known
to the compiler with the assertion that the code for this function
will be provided "elsewhere".
The form is:
<modifiers> <type> name ( <arguments> );
Typical uses are:
- to declare in advance functions which are called before they
can be defined; for example if the create() function of an object
calls other functions which are defined after the create().
- to declare functions which will be provided by an inheriting
object.
Calling a declared but undefined function results in a runtime error.
CALLING A FUNCTION
Functions in other objects are called with the call_other() efun,
which can be shortened to '->':
ob->fun(a, b, c)
call_other(ob, "fun", a, b, c)
Note: See the entry H_DEFAULT_METHOD in hooks(C) for a modification
of this behaviour.
Functions in the same object are called just by writing their name,
followed by the arguments in parenthesis:
short()
compute(a)
do_that(a, "foo")
Array function arguments can be 'flattened' with the '...' operator.
For example:
mixed * m = ({ "foo", "bar" });
fun(m..., 1);
will be executed as:
fun("foo", "bar", 1);
If the number of values passed to the function does not match the
number of expected arguments (and if type checking is not enabled), the
driver will perform the necessary adaption at call time: excess
values are ignored, missing values are substituted by the number 0.
The values passed to the called function are massaged by the driver
to match the argument list
FUNCTIONS AND INHERITANCE
A "public" or "protected" (== "static") function defined in one
object is also visible in all inheriting objects. The exception from
this rule is when an inheriting child redefines ("overloads") the
inherited function with its own. When compiling with type checking,
the argument list of the redefined function has to match the
original one.
When a function is called, the driver looks for the function first
in the object called, and if not found there, then in the inherited
objects.
To explicitely call an inherited function (useful when a redefining
functions wants to use the original one), the "::" operator is used:
::create()
::compute(a)
The named function is searched only in the inherited objects, and
the first found is used.
If the function is inherited from several objects and a specific
one is to be called, the "::" can be extended to contain the
partial or full name of the inherited object:
inherit "/obj/cooker";
inherit "/obj/container";
tainer::create()
container::create()
"tainer"::create()
"container"::create()
"obj/container"::create()
"/obj/container"::create()
all call the create() in the container inherit. Note that the
name given to the :: operator is matched against the ends of
the inherited names.
One special form of this call is
efun::find_object()
which bypasses any redefinition of an efun (here find_object())
and directly calls the efun itself. This is only possible for
efun-redefinitions which do not use the "nomask" modifier.
Additionally, a call to a function inherited from several objects
can be instructed to call _all_ inherited functions through the
use of the wildcards "*" (match any number of arbitrary characters)
and "?" (match one arbitrary character):
inherit "/obj/cooker";
inherit "/obj/container";
"*"::create()
"co*"::create()
"*er"::create()
all call both inherited create()s. The function called this way
must not take arguments, and the single results from all calls are
combined into one array used as final result. If there is no such
function inherited at all, the statement will just return
an empty array.
SEE ALSO
types(LPC), modifiers(LPC), varargs(LPC), references(LPC),
call_other(E), simul_efun(C), call_out(E)
|