Lua程序设计(六十八)

将协程用作迭代器

循环迭代器可以视为生产者-消费者模式的一种特例:一个迭代器会生产由循环体消费的内容。因此,用协程来实现迭代器也是自然的一种方式。同时,协程最关键的特性就是能够颠倒调用者与被调用这之间的关系。有了这种特性,我们在编写迭代器时就无须担心如何保存连续调用之间的状态了。

要编写这样一种迭代器并不容易,所以我们选择编写一个递归函数来产生所有的排列。思路也很简单,只要依次将每个数组元素放到最后一个位置,然后递归地生成其余元素的所有排列即可。

function permgen (a, n)
	n = n or #a
	if n <= 1 then
		printResult(a)
	else
		for i = 1, n do
			a[n], a[i] = a[i], a[n]
			permgen(a, n - 1)
			a[n], a[i] = a[i], a[n]
		end
	end
end

function printResult (a)
	for i = 1,  #a do io.write(a[i], " ") end
	io.write("\n")
end

permgen({1, 2, 3, 4})

--有了生成器后,将其转换为迭代器就很容易了。首先,我们把printResult 改为 yield:
function permgen (a, n)
	n = n or #a
	if n <= 1 then
		coroutine.yield(a)
	else
		for i =1, n do
			a[n], a[i] = a[i], a[n]
			permgen(a, n-1)
			a[n], a[i] = a[i], a[n]
		end
	end
end

--然后我们定义一个将生成器放入协程运行并创建迭代函数的工厂。迭代器只是简单地唤醒协程,让其产生下一个排列:
function permutations (a)
	local co = coroutine.create(function() permgen(a) end)
	return function()
		local code, res = coroutine.resume(co)
		return res
	end
end

--如此一来,在for循环中遍历一个数组的所有排列就非常简单了:
for p in permutations{"a", "b", "c"} do
	printResult(p)
end

函数permutations使用了Lua语言中一种常见的模式,即将唤醒对应协程的调用包装在一个函数中,由于这种模式十分常见,Lua语言专门提供了一个特殊的函数coroutine.wrap来完成这个功能。函数wrap用来创建一个新的例程, 并返回一个函数,当这个函数被调用时就会唤醒协程。

function permutations (a)
	return coroutine.wrap(function () permgen(a) end)
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值