1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
|
/**
\page doc_script_func_decl Function declaration
Global functions provide the mean to implement routines that should operate on some input and produce a result.
The functions themselves do not keep any memory, though they can update global variables, or memory passed by
reference.
The function is always declared together with the function body. There is no need to declare function prototypes,
as the function is globally visible regardless where it has been declared.
<pre>
// A simple function declaration
int AFunction(int a, int b)
{
// Implement the function logic here
return a + b;
}
</pre>
The type of the return value should be specified before the name of the function. If the function doesn't return anything
the type should be defined as 'void'. After the function name, the list of parameters is specified between parenthesis.
Each parameter is defined by its type and name.
\page doc_script_func_ref Parameter references
The parameters and return value can be of any type that can also be used for variable declarations. In addition, it is also
possible to make a function take a value by reference, i.e. rather than a copy of the original value, the parameter will refer
to the value.
Parameter references are used mainly for two purposes; a means of providing additional output from the function, or as a more performatic
way of passing values.
In AngelScript it is necessary to specify the intention of the parameter reference, i.e. if it is meant as input, output, or both.
This is necessary in order for the compiler to prepare the reference in a way that it cannot be invalidated due to some action during
the processing of the function.
Input references are written as &in. As the reference is meant as input only, the actual value it refers to normally is a copy of the
original so the function doesn't accidentally modify the original value. These are not commonly used, as they provide little benefit
over passing arguments by value. Only in some circumstances can the performance be improved, especially if the parameter is declared as
const too.
Output references are written as &out. These references are meant to allow the function to return additional values. When going in to
the function, the reference will point to an uninitialized value. After the function returns, the value assigned by the function will be
copied to the destination determined by the caller.
When the reference is meant as both input and output, it is declared as &inout, or just &. In this case the reference will point to the
actual value. Only \ref doc_datatypes_obj "reference types", i.e. that can have handles to them, are allowed to be passed as inout references. This is because
in order to guarantee that the reference will stay valid during the entire execution of the function, the value must be located in the
memory heap.
<pre>
void Function(const int &in a, int &out b, Object &c)
{
// Assigning an output value to the output reference
b = a;
// The object is an inout reference and refers to the real object
c.DoSomething();
}
</pre>
\page doc_script_func_retref Return references
A function can also return references, which will allow the caller to modify the value pointed to
by the reference. To declare a function that return a reference include the & symbol between the
return type and name of the function. Add const before the type if the reference should be read only,
i.e. it shouldn't be possible to modify the value it points to.
<pre>
int property;
int &Function()
{
// Return a reference to the property
return property;
}
void main()
{
// Modify the value pointed to by the returned reference
Function() = 1;
}
</pre>
Due to the need to guarantee that the reference is valid even after the function returns to the
caller there exist certain restrictions. You don't need to try to remember these restrictions as
the compiler will give an error if you they are violated, but if you do encounter a compile
error when returning a reference it will be good to understand why it is happening so that
you can determine how to avoid it.
\section doc_script_retref_global References to global variables are allowed
As a global variable is in the global scope, the lifetime of the variable is longer than the
scope of the function. A function can thus return a reference to a global variable, or even member
of an object reached through a global variable.
\section doc_script_refref_member References to class members are allowed
A class method can return a reference to a class property of the same object, because the caller
is required to hold a reference to the object it is known that the member will exist even after the
method returns.
The class method is also allowed to return reference to global variables, just like any other function.
\section doc_script_retref_local Can't return reference to local variables
Because local variables must be freed when the function exits, it is not allowed to return
a reference to them. The same is also true for any parameters that the function received. The
parameters are also cleaned up when the function exits, so they too cannot be returned by
reference.
\section doc_script_retref_deferred Can't use expressions with deferred parameters
For some function calls with arguments, there may be a necessary processing of the arguments
after the function call returned, e.g. to clean up the input object, or to assign the output
parameters. If the function that was called is returning a reference, then that reference cannot
in turn be returned again, as it may be invalidated by the deferred evaluation of the arguments.
\section doc_script_refref_cleanup Can't use expressions that rely on local objects
All local objects must be cleaned up before a function exits. For functions that return references
this clean-up happens before the return expression is evaluated, otherwise the cleanup of the
local objects may accidentally invalidate the reference. For this reason it is not possible
to use expressions that rely on local objects to evaluate the reference that should be returned.
Primitive values can be used though, as these do not require cleanup upon exit.
\page doc_script_func_overload Function overloading
Function overloading happens when more than one function with the same name is declared with
different parameters. This is a useful feature when an operation needs to be able to work with
different types of input, yet produce similar result.
The compiler is able to resolve which function to call by matching the type of each argument
expression to the function parameter, and eliminating the functions where there is no possible
conversion available. The compiler will do this for each argument from first to last. When all
arguments have been evaluated only one function should be the best match, otherwise the compiler
will give an error about the impossibility to determine the correct function to call.
The type of conversion that needs to be performed on the argument to get to the type of the
parameter determines how well a function matches. The following list gives the order of how one
type of conversion compares to another.
- no conversion needed
- conversion to const
- size of primitive changes
- integer type to float type and vice versa
- reference cast
- object to primitive conversion
- conversion to object
- variable argument type
Observe that it is not possible to create overloads where the only difference is the return
type. This is because the return type is not part of the selection criteria that the compiler
uses to determine which function to call, the return type is just the result of the called
function.
<pre>
void Function(int a, float b, string c) {}
void Function(string a, int b, float c) {}
void Function(float a, string b, int c) {}
void main()
{
Function(1, 2.5f, 'a'); // Will call the first overload
Function('a', 1, 2.5f); // Will call the second overload
Function(2.5f, 'a', 1); // Will call the third overload
}
</pre>
\page doc_script_func_defarg Default arguments
Sometimes implementing different functions for each overload is unnecessary when the difference can
be provided with a default value to a parameter. This is where default arguments come in handy.
By defining default arguments in the declaration of the function, the script doesn't have to provide
these values specifically when calling the function as the compiler will automatically fill in the
default arguments.
<pre>
void Function(int a, int b = 1, string c = "")
{
// Inside the function the arguments work normally
}
void main()
{
// Default arguments doesn't have to be informed
// The following three calls produce the exact same result
Function(0);
Function(0,1);
Function(0,1,"");
}
</pre>
When defining a default argument to one of the parameters, all subsequent parameters must have a
default argument too.
The default argument expression can include references to variables or call functions, but only if
the variables or functions are visible in the global scope.
<pre>
int myvar = 42;
void Function(int a, int b = myvar) {}
void main()
{
int myvar = 1;
Function(1); // This will use the global myvar and not the local myvar
}
</pre>
The special 'void' expression can be used as default argument to make an optional output parameter.
<pre>
void func(int &out output = void) { output = 42; }
</pre>
\page doc_script_anonfunc Anonymous functions
Anonymous functions, or lambdas as they are sometimes called, are functions that are
declared locally for use with \ref doc_datatypes_funcptr "function handles".
The following is a quick demonstration on how to use anonymous functions.
<pre>
funcdef bool CMP(int first, int second);
void main()
{
int valueA = 1, valueB = 2;
bool result1 = func(valueA, valueB, function(a,b){ return a == b; });
bool result2 = func(valueA, valueB, function(a,b){ return a != b; });
}
bool func(int a, int b, CMP \@f)
{
return f(a,b);
}
</pre>
The anonymous function takes on the signature of the function handle it is assigned to,
so the type of the arguments and the return type doesn't have to be explicitly declared.
It is not yet possible for anonymous functions to access variables declared in the same
scope as the function, i.e. they cannot be used as closures.
If there are multiple matching uses for the anonymous function it will be necessary to
explicitly inform the parameter types, so the ambiguity can be resolved.
<pre>
funcdef void A(int);
funcdef void B(float);
void func(A@) {}
void func(B@) {}
void main()
{
// Explicitly specify the type to tell the compiler that A is wanted
func(function(int a) {});
}
</pre>
*/
|