2.25. 生成器
生成器允许您声明一个行为类似于迭代器的 lambda。
对于所有意图和目的,生成器是传递给 each
或 each_ref
函数的 lambda。
生成器语法类似于 lambda 语法:
generator ::= `generator` < type > $ ( ) block
生成器 lambda 必须没有参数。它始终返回布尔值:
let gen <- generator<int>() <| $ { // gen is iterator<int>
for ( t in range(0,10) ) {
yield t
}
return false // 返回 false 停止迭代
}
generator
表达式的结果类型是一个迭代器 (参阅 Iterators).
生成器通过 yield
表达式输出迭代器值。
与 return 语句类似,允许移动语义 yield <-
return <- generator<TT> () <| $ {
for ( w in src ) {
yield <- invoke(blk,w) // 移动调用结果
}
return false
}
生成器可以输出 ref 类型。他们可以有一个 capture 部分:
unsafe { // 由于通过引用捕获 src 而不安全
var src = [1,2,3,4]
var gen <- generator<int&> capture(ref(src)) () <| $ { // 通过 ref 捕获 src
for ( w in src ) {
yield w // yield of int&
}
return false
}
for ( t in gen ) {
t ++
}
print("src = {src}\n") // will output [[2;3;4;5]]
}
生成器可以具有 Loop 和其他控制结构:
let gen <- generator<int>() <| $ {
var t = 0
while ( t < 100 ) {
if ( t == 10 ) {
break
}
yield t ++
}
return false
}
let gen <- generator<int>() <| $ {
for ( t in range(0,100) ) {
if ( t >= 10 ) {
continue
}
yield t
}
return false
}
生成器可以在其块上有一个 finally
表达式,但 if-then-else 块除外:
let gen <- generator<int>() <| $ {
for ( t in range(0,9) ) {
yield t
} finally {
yield 9
}
return false
}
2.25.1. 实现细节
在以下示例中:
var gen <- generator<int> () <| $ {
for ( x in range(0,10) ) {
if ( (x & 1)==0 ) {
yield x
}
}
return false
}
生成包含所有捕获变量的 lambda:
struct _lambda_thismodule_8_8_1 {
__lambda : function<(__this:_lambda_thismodule_8_8_1;_yield_8:int&):bool const> = @@_::_lambda_thismodule_8_8_1`function
__finalize : function<(__this:_lambda_thismodule_8_8_1? -const):void> = @@_::_lambda_thismodule_8_8_1`finalizer
__yield : int
_loop_at_8 : bool
x : int // captured constant
_pvar_0_at_8 : void?
_source_0_at_8 : iterator<int>
}
生成 lambda 函数:
[GENERATOR]
def _lambda_thismodule_8_8_1`function ( var __this:_lambda_thismodule_8_8_1; var _yield_8:int& ) : bool const {
goto __this.__yield
label 0:
__this._loop_at_8 = true
__this._source_0_at_8 <- __::builtin`each(range(0,10))
memzero(__this.x)
__this._pvar_0_at_8 = reinterpret<void?> addr(__this.x)
__this._loop_at_8 &&= _builtin_iterator_first(__this._source_0_at_8,__this._pvar_0_at_8,__context__)
label 3: /*begin for at line 8*/
if ( !__this._loop_at_8 ) {
goto label 5
}
if ( !((__this.x & 1) == 0) ) {
goto label 2
}
_yield_8 = __this.x
__this.__yield = 1
return /*yield*/ true
label 1: /*yield at line 10*/
label 2: /*end if at line 9*/
label 4: /*continue for at line 8*/
__this._loop_at_8 &&= _builtin_iterator_next(__this._source_0_at_8,__this._pvar_0_at_8,__context__)
goto label 3
label 5: /*end for at line 8*/
_builtin_iterator_close(__this._source_0_at_8,__this._pvar_0_at_8,__context__)
return false
}
控制流语句被 label
+ goto
等价物替换。
生成器总是以 goto __this.yield
开头。
这有效地产生了一个有限状态机,其中 yield
变量保存当前状态索引。
yield
表达式将转换为复制结果和返回值对。
创建一个标签来指定下次在 yield
之后去哪里:
_yield_8 = __this.x // produce next iterator value
__this.__yield = 1 // label to go to next (1)
return /*yield*/ true // return true to indicate, that iterator produced a value
label 1: /*yield at line 10*/ // next label marker (1)
迭代器初始化将替换为 lambda 的创建:
var gen:iterator<int> <- each(new<lambda<(_yield_8:int&):bool const>> default<_lambda_thismodule_8_8_1>)