.. _generators: ========= 生成器 ========= 生成器允许您声明一个行为类似于迭代器的 lambda。 对于所有意图和目的,生成器是传递给 ``each`` 或 ``each_ref`` 函数的 lambda。 生成器语法类似于 lambda 语法:: generator ::= `generator` < type > $ ( ) block 生成器 lambda 必须没有参数。它始终返回布尔值:: let gen <- generator() <| $ { // gen is iterator for ( t in range(0,10) ) { yield t } return false // 返回 false 停止迭代 } ``generator`` 表达式的结果类型是一个迭代器 (参阅 :ref:`Iterators `). 生成器通过 ``yield`` 表达式输出迭代器值。 与 return 语句类似,允许移动语义 ``yield <-`` :: return <- generator () <| $ { for ( w in src ) { yield <- invoke(blk,w) // 移动调用结果 } return false } 生成器可以输出 ref 类型。他们可以有一个 capture 部分:: unsafe { // 由于通过引用捕获 src 而不安全 var src = [1,2,3,4] var gen <- generator 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() <| $ { var t = 0 while ( t < 100 ) { if ( t == 10 ) { break } yield t ++ } return false } let gen <- generator() <| $ { for ( t in range(0,100) ) { if ( t >= 10 ) { continue } yield t } return false } 生成器可以在其块上有一个 ``finally`` 表达式,但 if-then-else 块除外:: let gen <- generator() <| $ { for ( t in range(0,9) ) { yield t } finally { yield 9 } return false } ---------------------- 实现细节 ---------------------- 在以下示例中:: var gen <- generator () <| $ { 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 } 生成 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 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 <- each(new> default<_lambda_thismodule_8_8_1>)