7
9
2015
0

yield

今天看 C# 发现这样一种用法:

class IntManager
{
	int[] arr = { 0, 1, 2, 3 };
	public IEnumerator<int> GetEnumerator()
	{
		for (int i = 0; i<4; i++)
		{
			yield return arr[i];
		}
	}
}

是的……对我这样孤陋寡闻的人来说,这就是这么神奇……居然可以这样写出迭代器!

而且根据一些资料来看,这个迭代器是随用随取的,也就是说如果资源不在内存上,那就可以需要多少取多少,不会一次性全部取回来,非常方便。

以前我只知道 yield 用在 coroutine 上。不过把这两个一结合,我就发现了神奇的现象……Tcl 的 yield 其实也不过是这样而已。

proc y {} { 
    set i 0
    while 1 {
        yield [incr i]
    }
}
coroutine coro y ;; -> 1,这里会调用一次 y 所以是 1
coro ;; -> 2
coro ;; -> 3
coro ;; -> 4

没错,这还是一个……嗯,我们不如来研究一些好玩的。

proc fibo {} {
    ;# 第一次 yield 之前可以尝试做一些初始化工作
    yield ;# 然后用 yield 返回结果,这里自然是不需要的
    set a 0
    set b 1
    while 1 {
        ;# a,b = b,a+b
        set t $b
        set b [expr $a+$t]
        set a $t
        yield $a
    }
}
coroutine next fibo
next ;; -> 1
next ;; -> 1
next ;; -> 2
-> 就是 1,1,2,3,5,8,13,21,34,55,...

实际上用这个求这个数列的效率不高,因为求过一次数据就丢弃了,不如以前写过的一个缓存版本快。但是这个版本不会爆栈(相比递归版本),因为根本只有一个栈帧和循环版的效率理论上来说差不多,没测试。

Category: 编程 | Tags: | Read Count: 994

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Powered by Chito | Hosted at is-Programmer | Theme: Aeros 2.0 by TheBuckmaker.com