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)

        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")

        If the number of values passed to the function does not match the
        number of expected arguments (and if type checking is 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)
