function 指标与其变数型态
-------------------------

    LPC 提供了 function 这种变数型态, 可以用来方便的指向函数.
  也许你会想要把函数传给某些 efun, 例如某些过滤的函数. 函数的
  指标可以用 (: 函数名称 :) 来引用, 配合函数变数则:

	function f = (: local_func :);

    你可以把 f 当成变数传给其它函数, 或者是把它当成函数指标:

	foo(f);				// 当成变数.
	map_array( ({ 1, 2 }), f);	// 当成指标.

    或者, 有一个更强的用法, 在后来的时机里再"求值":

	x = evaluate(f, "hi");

When the last line is run, the function that f points to is called, and "hi"
is passed to it.  This will create the same effect as if you had done:
    执行到上一行的时候, 实际上会呼叫 f 所指的函数去, 并传 "hi" 给它当参数.
  上面的方式跟下面的程式码意义相同:

	x = local_func("hi");

    以函数变数来指向函数的好处是, 你可以改变指标, 让它指向别的函数.
  尤其是配合 evaluate() 时, 在此, 先提醒一下, 如果传给 evaluate() 的
  参数不是函数指标的话, 会传回它的值, 因此下列方式可见函数变数的优点:

	void set_short(mixed x) { short = x; }
	mixed query_short() { return evaluate(short); }

    如上面的宣告, 你可以如下的使用 set_short():
	set_short("Whatever");
	set_short( (: short_func :) ); 

    如此一来, 物件可以自己定义 short_func(), 可增加许多弹性.


各种函数变数或指标
------------------

    最简单的函数指标的使用已经如上所述, 即: (: 函数名称 :), 这种
  方式可以方便的用在同一物件的函数上, 也可以把参数包括进来, 如:

	string foo(string a, string b)
	{
	  return "(" + a "," + b + ")";
	}

	void create()
	{
	  function f = (: foo, "left" :);

	  printf( "%s %s\n", evaluate(f), evaluate(f, "right") );
	}

	==> 结果: (left,0) (left,right)


    第二种用法是 efun 指标, 跟同一物件里的局部函数指标很类似. 例如:
  objects() 会传回所有 mud 载入的物件, 只要该物件满足某函数, 如:

	objects( (: clonep :) )

  因为所有物件都是 "clonep", 也就是, 所有物件 ob->clonep() 都传回非 0 值,
  因此上述例子会传回所有的物件阵列.

    底下再示范一个例子:

	void create()
	{
	  int i;
	  function f = (: write, "Hello, world!\n" :);

	  for (i=0; i<3; i++) { evaluate(f); }
	}

    结果是:
	Hello, world!
	Hello, world!
	Hello, world!

    simul_efun 会跟 efun 一样的效果(否则怎会称为 simul_efun?!).
    而 efun 会跟局部的函数很像, 是因为 efun 是整体性的函数, 因此
  可以想成是跟局部的函数同样地位.

    第三种型式的是 call_other 函数指标. 它很类似于 MudOS 所支援的函数
  指标的用法, 格式是:

	(: 物件, 函数名称 :)

  假如有参数的话, 可以把所有参数组成阵列加在函数名称之后. 例如:

	void create()
	{
	  string *ret;
	  function f = (: this_player(), "query" :);    

	  ret = map( ({ "name", "short", "long" }), f );     
	  write(implode(ret, "\n"));
	}

    上面的程式片断相当于:
	this_player()->query("name");
	this_player()->query("short");
	this_player()->query("long");

    如果要让函数指标直接指向 query("short") 的话, 可以是:

	f = (: this_player(), ({ "query", "short" }) :)

    底下的例子跟上面的一模一样, 供你做参考:

	f = (: call_other, this_player(), "query", "short" :)
	// 透过指向 call_other efun, 来呼叫定义在 this_player() 物件中
	// 的 query("short")

	f = (: this_player()->query("short") :)
	// 这是函数的表示式, 见底下的说明.


The fourth type is the expression function pointer.  It is made using
(: expression :).  Within an expression function pointer, the arguments
to it can be refered to as $1, $2, $3 ..., for example:

evaluate( (: $1 + $2 :), 3, 4)  // returns 7.

This can be very useful for using sort_array, for example:

top_ten = sort_array( player_list, 
	  (: $2->query_level() - $1->query_level :) )[0..9];


The fifth type is an anonymous function:

void create() {
    function f = function(int x) {
        int y;

        switch(x) {
        case 1: y = 3;
        case 2: y = 5;
        }
        return y - 2;
    };

    printf("%i %i %i\n", (*f)(1), (*f)(2), (*f)(3));
}

would print: 1 3 -2

Note that (*f)(...) is the same as evaluate(f, ...) and is retained for
backwards compatibility.  Anything that is legal in a normal function is
legal in an anonymous function.


When are things evaluated?
--------------------------

The rule is that arguments included in the creation of efun, local function,
and simul_efun function pointers are evaluated when the function pointer is
made.  For expression and functional function pointers, nothing is evaluated
until the function pointer is actually used:

(: destruct, this_player() :)  // When it is *evaluated*, it will destruct
                               // whoever "this_player()" was when it 
                               // was *made*
(: destruct(this_player()) :)  // destructs whoever is "this_player()"
                               // when the function is *evaluated*

For this reason, it is illegal to use a local variable in an expression
pointer, since the local variable may no longer exist when the function
pointer is evaluated.  However, there is a way around it:

(: destruct( $(this_player) ) :) // Same as the first example above

$(whatever) means 'evaluate whatever, and hold it's value, inserting it
when the function is evaluated'.  It also can be used to make things more
efficient:

map_array(listeners, 
          (: tell_object($1, $(this_player()->query_name()) + " bows.\n") :) );

only does one call_other, instead of one for every message.  The string
addition could also be done before hand:

map_array(listeners, 
          (: tell_object($1, $(this_player()->query_name() + " bows.\n")) :) );

Notice, in this case we could also do:

map_array(listeners, 
          (: tell_object, this_player()->query_name() + " bows.\n" :) );


