[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 } 缺省情况下,代码块可通过预先隐式定义的参数X和Y 接受代码块方法传递进的参数值。用户可以显式声 明更有意义的参数: 1 returned = meth_name { [index, item] 2 code_block 3 } 作为一个例子,列表类型有个可用来排序的代码块方法,它的原型如下: 1 sort( self :list<@T>, k=0 ) [X :@T, Y :@T => int] => list<@T> 这里代码块的参数X和Y被用来传递列表的两元素值, 以便有代码块作比较。此代码块将依据代码块比较 元素的结果作排序。 因此该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 }