CONCEPT inline closures SYNTAX function ( ) : { } (: ; , ... , :) DESCRIPTION Inline closures are a way to program closures which are compiled at the time an object is loaded, but can access values from their enclosing function at runtime. Example: closure factory (int arg) { return function int (int val) { return val * arg; }; } closure f1 = factory(2); closure f2 = factory(3); funcall(f1, 3) -> will yield 6. funcall(f2, 3) -> will yield 9. The closure here 'inherits' the current value of the local variable 'arg' at the time the closure is created. These values are called the "context" of the closures - they are stored in a special set of variables in the closure. One specific feature of the closure context is that it can be changed from within the closure, and that these changes remain permanent: closure factory (int arg) { return function int (int val) { return val * arg++; }; } closure f = factory(2); funcall(f, 3) -> will yield 6. funcall(f, 3) -> will now yield 9! But changes of the closure context will not reflect on the local variable it was copied from and vice versa. In addition to the implicit context inherited from the defining function, additional context variables can be defined in the closure: closure factory (int arg) { return function int (int val) : int x = 2 * arg { return val * x; }; } closure f = factory(2); funcall(f, 3) -> will yield 12. It is possible to define multiple context variables with and without initialisation: closure factory (int arg) { return function int (int val) : int y, x = 2 * arg; int z { return val * x; }; } These explicit context variables are useful when the closures needs to keep a state, or to improve performance: mapping m = ...; closure slow (int arg) { return function mixed () { return m[arg]; } } closure fast (int arg) { return function mixed () : mixed val = m[arg] { return val; } } In the above example, the fast() function executes the lookup m[arg] only once when the inline closure is created; the slow() function on the other hand returns a closures which looks up m[arg] every time it is called. A second effect is that the results of the slow closure change when m changes; the result of the fast closure is always the same. In the definition of an inline closure, some elements are optional: defaults to 'mixed' ( ) defaults to '(mixed $1 ... mixed $9)' : no default The special (: :) form is meant for simple expressions (and MudOS compatibility). The form (: ; , ..., :) is the shorthand notation for function { ; return , ..., ; } For example the two statements sort_array(arr, function { return $1 < $2; } ) sort_array(arr, (: $1 < $2 :) ) do the same. The example also demonstrates that both the and the part in this form are optional. NOTES The macro __LPC_INLINE_CLOSURES__ is defined when the inline closures as described here are available. If not defined, the driver implements a more restricted version ('(: :)' syntax only, no context variables) for backwards compatibility. Inline closures are not to be confused with inline functions known from other languages. HISTORY LDMud 3.2.7 implemented the older, restricted form of inline closures. LDMud 3.3.271 implemented the full form of inline closures. LDMud 3.3.275 re-allowed statements in the (: :) form. SEE ALSO closures-abstract(LPC), closures-example(LPC), closure_guide(LPC) closures(LPC)