Next: Event handlers Up: Values, Types, and Constants Previous: Files Contents Index

#
Functions

You declare a Bro `function` type using:

> `function (` argument `)` [ ``:` type` ]

where argument is a (possibly empty) comma-separated list of arguments, and the final ```:` type'' declares the return type of the function. It is optional; if missing, then the function does not return a value.

Each argument is declared using:

> param-name `:` type

So, for example:

        function(a: addr, p: port): string

corresponds to a function that takes two parameters, `a` of type `addr` and `p` of type `port`, and returns a value of type `string`.

You could furthermore declare:

        global generate_id: function(a: addr, p: port): string;

to define `generate_id` as a variable of this type. Note that the declaration does not define the body of the function, and, indeed, `generate_id` could have different function bodies at different times, by assigning different function values to it.

When defining a function including its body, the syntax is slightly different:

> `function` func-name `(` argument `)` [ ``:` type` ] `{` statement `}`

That is, you introduce func-name, the name of the function, between the keywork `function` and the opening parenthesis of the argument list, and you list the statements of the function within braces at the end.

For the previous example, we could define its body using:

        function generate_id(a: addr, p: port): string
            {
            if ( a in local_servers )
                # Ignore port, they're always the same.
                return fmt("server %s", a);

            if ( p < 1024/tcp )
                # Privileged port, flag it.
                return fmt("%s/priv-%s", a, p);

            # Nothing special - default formatting.
            return fmt("%s/%s", a, p);
            }

We also could have omitted the first definition; a function definition like the one immediately above automatically defines `generate_id` as a function of type `function(a: addr, p: port): string`. Note though that if func-name was indeed already declared, then the argument list much match exactly that of the previous definition. This includes the names of the arguments; Unlike with C, you cannot change the argument names between their first (forward) definition and the full definition of the function.

You can also define functions without using any name. These are referred to as anonymous functions, and are a type of expression.

You can only do two things with functions: call them or assign them. As an example of the latter, suppose we have:

        local id_funcs: table[conn_id] of function(p: port, a: addr): string;

would declare a local variable indexed by a `conn_id` record value to yield a function of the same type as in the previous example. You could then execute:

        id_funcs[c$id] = generate_id

or call whatever function is associated with a given `conn_id`:

        print fmt("id is: %s", id_funcs[c$id](80/tcp, 1.2.3.4));

Next: Event handlers Up: Values, Types, and Constants Previous: Files Contents Index