[NAME]
ALL.dao.routine.closure

[TITLE]
匿名函数和函数闭包

[DESCRIPTION]

道语言里函数是基本类型。因此它们可在运行时创建并跟其他对象一样使用。 运行时创建的函数是匿名
函数或函数闭包。

创建匿名函数或函数闭包的语法跟普通函数几乎等同,只有以下几点比较特殊: 
  1. 无函数名;
  2. 它可以使用外部函数的局部变量; 
如果一个被创建的函数需要访问外部局部变量,那么这个函数将以函数闭包的形式 创建,否则以匿名函
数的方式创建。

下面是个简单的例子: 
     
   1  var rout = routine( name: string, value = 0 ){
   2      io.writeln( name, value )
   3      return name.size() + value
   4  }
   5  rout( "abc", 123 )
     
这里与普通函数定义的唯一区别是没有函数名。

在上面例中的,被创建的函数没访问外层函数的局部变量,因此它被创建为普通的匿名函数。 这里将介绍
另一例子,这个例子中被创建的函数将访问其外层函数的局部变量: 
     
   1  routine MakeClosure( start: int )
   2  {
   3      return routine( offset: int ){
   4          return start + offset
   5      }
   6  }
   7  var rout = MakeClosure( 100 );
   8  rout( 123 )
     
这例中创建的函数访问了外层函数"MakeClosure()"的"start"局部变量, 那么这个被创建的函数将以函
数闭包的形式创建。 当一个函数闭包被创建时,它所访问的外层局部变量将被存在被创建的函数中。 对
于基本类型的局部变量,它们的值将被拷贝,而其它类型的变量,则仅被保存引用。 一旦函数闭包被创建
,它们将不再需要它的创建环境就可使用。

匿名函数和函数闭包之间的主要区别在于是否有对外层函数局部变量的访问。 这个区别导致了它们的运
行时的创建方式比较不一样: 函数闭包总是以新函数对象创建;而匿名函数则有可能返回同一个函数对
象。 例如下面的匿名函数总返回同一个函数对象: 
     
   1  routine MakeRoutine()
   2  {
   3      return routine( value: double ){
   4          return value * value
   5      }
   6  }
   7  io.writeln( MakeRoutine(), MakeRoutine() )
     
要这种情况发生,匿名函数不但不能访问外层函数的局部变量,也不能有静态变量。 如果有静态变量,它
将跟函数闭包一样以新的函数对象创建。 例如下面的匿名函数创建每次都会生成一个不同的函数对象。
     
   1  routine MakeRoutine()
   2  {
   3      return routine( value: double ){
   4          static dummy = 123
   5          return value * value
   6      }
   7  }
   8  io.writeln( MakeRoutine(), MakeRoutine() )