[NAME]
ALL.dao.routine.section

[TITLE]
代码块方法

[DESCRIPTION]

代码块方法是一种特殊的函数或方法。对这种函数的调用需要附加一个代码块。 这个代码块相当于该函
数调用的一个隐式额外参数。当这样的函数调用被执行时, 该函数将恰当地执行该代码块,并可能利用该
代码块执行的结果。 并且这种代码块本身也类似一个函数,可以有参数,也可以有返回值。

其他语言里与道语言代码块方法最接近的是Ruby里的代码块方法。 不过在Ruby里,代码块方法的调用所
附加的代码块被编译为函数闭包, 该闭包以隐式的额外参数传递给被调用的代码块方法。 道语言里代码
块方法的代码块确实是个代码块,它存在于调用代码块方法的函数中。 也就是说,运行时没有产生函数闭
包,而是直接在调用者的函数中定位并被执行。 这种代码块的优势是没有创建函数闭包的额外开销。

代码块方法是相对于其他语言里的函数式方法的一个更好的替代品。 它使得它的使用更直观自然。例如
,它避免了在函数调用的参数里 写庞大的匿名函数或闭包,很大程度上增加了代码的可读性。

要定义一个代码块方法,用户需要定义两套参数和返回值: 一套为方法的普通参数和返回值;另一套为代
码块的参数和返回值。 
     
   1  routine meth_name( meth_params ) [sect_params => sect_return] => meth_return
   2  {
   3      ...
   4  }
     
这里的参数列表sect_params表示什么类型的参数该代码块方法将传递给 它的代码块;而返回值类型
sect_return则表示代码块应该返回什么类型的结果值。

代码块方法的调用如下: 
     
   1  returned = meth_name( meth_params ) {
   2      code_block
   3  }
     
如果一个代码块方法不含普通的参数,那么它的调用可简单地变成: 
     
   1  returned = meth_name {
   2      code_block
   3  }
     
缺省情况下,代码块可通过预先隐式定义的参数XY 接受代码块方法传递进的参数值。用户可以显式声
明更有意义的参数: 
     
   1  returned = meth_name { [index, item]
   2      code_block
   3  }
     


作为一个例子,列表类型有个可用来排序的代码块方法,它的原型如下: 
     
   1  sort( self :list<@T>, k=0 ) [X :@T, Y :@T => int] => list<@T>
     
这里代码块的参数XY被用来传递列表的两元素值, 以便有代码块作比较。此代码块将依据代码块比较
元素的结果作排序。 因此该sort()方法可按如下方式使用: 
     
   1  var numlist = { 11, 44, 21, 32, 56, 67, 25 }
   2  
   3  # 按升序排序:
   4  numlist.sort { X < Y }
   5  
   6  # 按降序排序,直到最大的三个值被排好:
   7  numlist.sort( 3 ) { X > Y }
   8  # 现在numlist的前三个元素即最大的三个元素;
   9  
  10  var tuplist = { ( 2, 'ghi' ), ( 1, 'def' ), ( 2, 'abc' ), ( 1, 'abc' ) }
  11  tuplist.sort {
  12      # 先按元组的第一个元素排序:
  13      if( X[0] != Y[0] ) return X[0] < Y[0];
  14      # 再按第二个元素排序:
  15      return X[1] < Y[1];
  16  }
     


在用户定义的代码块方法里,yield语句可用来执行该方法被调用时所 附加的代码块。yield的参数将被
传递给代码块,而代码块的返回值 则以yield的返回值返回。 下面是一个简单的用户定义代码块方法例
子: 
     
   1  # 一个可带代码块调用的函数。
   2  # 代码块可接受一个整数为参数,并返回一个字符串。
   3  routine Test() [X :int => string] => string
   4  {
   5      io.writeln( 'In functional method!' );
   6      var s = yield( 123 ); # 执行代码块;
   7      io.writeln( 'Yielded value:', s );
   8      return s;
   9  }
  10  
  11  Test {
  12      io.writeln( 'In code section:', X );
  13      return 'abc';
  14  }