CONCEPT
	closures example

DESCRIPTION
	These are a small discussed examples of the usage of
	(lambda-)closures. For technical details see the closures(LPC)
	doc. For hints when to use which type of closure, see the end
	of this doc.


	Many Muds use 'details' to add more flavour. 'Details' are
	items which can be looked at, but are not implemented as own
	objects, but instead simulated by the environment.
	Lets assume that the function

	  AddDetail(string keyword, string|closure desc)

	adds the detail 'keyword' to the room, which, when look at,
	returns the string 'desc' resp. the result of the execution of
	closure 'desc' as the detail description to the player.

	Now imagine that one wants to equip a room with magic runes,
	which read as 'Hello <playername>!\n" when looked at.
	Obviously

	  AddDetail("runes", sprintf( "Hello %s!\n"
	                            , this_player()->QueryName()));

	is not sufficient, as the 'this_player()' is executed to early
	and just once.

	The solution is to use closures. First, the solution using
	lfun-closures:

	  private string _detail_runes () {
	    return sprintf("Hello %s!\n", this_player()->QueryName());
	  }
	    ...
	  AddDetail("runes", #'_detail_runes);

        or with an inline closure:

          AddDetail("runes"
                   , (: sprintf("Hello %s!\n", this_player()->QueryName()) :)
                   );


	Simple? Here is the same code, this time as lambda-closure:

	  AddDetail( "runes"
	           , lambda(0
	             , ({#'sprintf, "Hello %s!\n"
	                          , ({#'call_other, ({#'this_player})
	                                          , "QueryName" })
	               })
	           ));

	Why the extra ({ }) around '#'this_player'? #'this_player
	alone is just a symbol, symbolizing the efun this_player(),
	but call_other() needs an object as first argument. Therefore,
	the #'this_player has to be interpreted as function to
	evaluate, which is enforced by enclosing it in ({ }). The same
	reason also dictates the enclosing of the whole #'call_other
	expression into ({ }).
	Note also the missing #'return: it is not needed. The result
	of a lambda-closure is the last value computed.

	
	Another example: Task is to reduce the HP of every living in a
	room by 10, unless the result would be negative.
	Selecting all livings in a room is simply

	  filter_array(all_inventory(room), #'living)

	The tricky part is to reduce the HP. Again, first the
	lfun-closure solution:

	  private _reduce_hp (object liv) {
	    int hp;
	    hp = liv->QueryHP();
	    if (hp > 10)
	      liv->SetHP(hp-10);
	  }
	    ...

	  map_array( filter_array(all_inventory(room), #'living)
	           , #'_reduce_hp)

        or as an inline closure:

          map_array( filter_array(all_inventory(room), #'living)
                   , (: int hp;
                        hp = liv->QueryHP();
                        if (hp > 10)
                          liv->SetHP(hp - 10);
                      :) );

	Both filter_array() and map_array() pass the actual array item
	being filtered/mapped as first argument to the closure.

	Now, the lambda-closure solution:

	  map_array( filter_array(all_inventory(room), #'living)
	  , lambda( ({ 'liv })
	    , ({'#, , ({#'=, 'hp, ({#'call_other, 'liv, "QueryHP" }) })
	            , ({#'?, ({#'>, 'hp, 10 })
	                   , ({#'call_other, 'liv, "SetHP"
	                                   , ({#'-, 'hp, 10 })
	                     })
	              })
	      })
	    ) // of lambda()
	  );
	
	It is worthy to point out how local variables like 'hp' are
	declared in a lambda-closure: not at all. They are just used
	by writing their symbol 'hp . Same applies to the closures
	parameter 'liv .
	The lambda-closure solution is not recommended for three
	reasons: it is complicated, does not use the powers of
	lambda(), and the lambda() is recompiled every time this
	statement is executed!

	
	So far, lambda-closures seem to be just complicated, and in
	fact: they are. Their powers lie elsewhere.

	Imagine a computation, like for skill resolution, which
	involves two object properties multiplied with factors and
	then added.
	The straightforward solution would be a function like:

	  int Compute (object obj, string stat1, int factor1
	                         , string stat2, int factor2)
	  {
	    return   call_other(obj, "Query"+stat1) * factor1
	           + call_other(obj, "Query"+stat2) * factor2;
	  }

	Each call to Compute() involves several operations (computing
	the function names and resolving the call_other()s) which in
	fact need to be done just once. Using lambda-closures, one can
	construct and compile a piece of code which behaves like a
	Compute() tailored for a specific stat/factor combination:

	  closure ConstructCompute (object obj, string stat1, int factor1
	                                      , string stat2, int factor2)
	  {
	    mixed code;

	    // Construct the first multiplication.
	    // The symbol_function() creates a symbol for the
	    // lfun 'Query<stat1>', speeding up later calls.
	    // Note again the extra ({ }) around the created symbol.

	    code = ({#'*, ({ symbol_function("Query"+stat1, obj) })
	                , factor1 });

	    // Construct the second multiplication, and the addition
	    // of both terms.

	    code = ({#'+, code
	                , ({#'*, ({ symbol_function("Query"+stat2, obj) })
	                       , factor2 })
                   });

	    // Compile the code and return the generated closure.
	    return lambda(0, code);
	  }

	Once the closure is compiled,

	  str_dex_fun = ConstructCompute(obj, "Str", 10, "Dex", 90);

	it can be used with a simple 'funcall(str_dex_fun)'.


DESCRIPTION -- When to use which closure?
	First, a closure is only then useful if it needn't to live any
	longer than the object defining it. Reason: when the defining
	object gets destructed, the closure will vanish, too.
	
        Efun-, lfun- and inline closures should be used where useful, as they
        mostly do the job and are easy to read. The disadvantage of lfun- and
        inline closures is that they make a replace_program() impossible
        - but since such objects tend to not being replaceable at all, this is
        no real loss.

	Lambda closures are needed if the actions of the closure are
	heavily depending on some data available only at runtime, like
	the actual inventory of a certain player.
	If you use lfun-closures and find yourself shoving around
	runtime data in arguments or (gasp!) global variables, it is
	time to think about using a lambda-closure, compiling the
	value hard into it.
	The disadvantages of lambda closures are clear: they are damn
	hard to read, and each lambda() statement cost extra time to
	compile the closure.


SEE ALSO
	closures(LPC), closure_guide(LPC), closures-abstract(LPC)
