Lua iterator state cost (stateless < closure < state table < coroutine)

简介:
generic for循环函数的代价, 成本从低到高.
首先考虑使用stateless, 也就是函数中无状态值, 状态值通常在exp-list中直接指出.
其次是使用closure, 使用non-local变量传递状态值.
再次是使用状态表存储状态.
最后是coroutine.

Simply put, a closure is a function plus all it needs to access non-local variables correctly.

Whenever possible, you should try to write stateless iterators, those that  keep all their state in the for variables. 
With them, you do not create new objects when you start a loop. 
If you cannot fit your iteration into this model, then you should try closures. 
Besides being more elegant, typically a closure is more efficient than an iterator using tables: 
1.first, it is cheaper to create a closure than a table; 
2.second, access to non-local variables is faster than access to table fields. 
Later we will see yet another way to write iterators, with coroutines. 
This is the most powerful solution, but a little more expensive.

1. 无状态的例子
iterator 函数, 参数为状态和控制变量
> function iter(s,i)
>>   i = i+1
>>   local v = s[i]
>>   if v then
>>     return i,v
>>   end
>> end

factory函数, 返回iterator函数, 状态和控制变量初始值, 状态值通过exp-list直接传入, 所以对于factory函数来说是不存储state值的, 因此称为stateless .
> function ipairs(s)
>>   return iter, s, 0
>> end

> a = {"one", "two", "three"}
> for i,v in ipairs(a) do 
>>   print (i,v)
>> end
1       one
2       two
3       three


2. 使用closure的例子, 将状态值存储在closure中.
factory函数, 返回iterator匿名函数以及state状态值. state封装在iterator匿名函数中.

> function allwords()
>>    local state = {line = io.read(), pos = 1}  -- 使用factory函数的local变量表存储状态值, 对iterator来说就是non-local变量
>>    return function (state)
>>    while state.line do  -- 重复直到最后一行
>>      local s,e = string.find(state.line, "%w+", state.pos)  -- 查找单词
>>      if s then
>>        state.pos = e+1
>>        return string.sub(state.line, s, e)  -- 返回单词
>>      else  -- 否则下一行
>>        state.line = io.read()
>>        state.pos = 1
>>      end
>>    end
>>    return nil  -- 如果没有值, iterator函数返回nil给控制变量, 因此结束generic for循环.
>>  end, state
>> end

> for w in allwords() do
>>  print (w)
>> end
hello nihao a
hello
nihao
a


3. 使用状态表的例子
上一个例子改一下就变成表存储state值了, 只要把iterator函数放到外面即可.

> function iterator(state)  -- 因为iterator函数在外头定义, 所以没有non-local变量, 所以和上面的例子差就差在这里.
>>    while state.line do
>>      local s,e = string.find(state.line, "%w+", state.pos)
>>      if s then
>>        state.pos = e+1
>>        return string.sub(state.line, s, e)
>>      else
>>        state.line = io.read()
>>        state.pos = 1
>>      end
>>    end
>>    return nil
>>  end
> 
> function allwords()
>>     local state = {line = io.read(), pos = 1}  -- 使用表存储state值, 同时传递给iterator函数. 
>>     return iterator, state
>> end
> for w in allwords() do
>>   print(w)
>> end
hello nihao, yes   
hello
nihao
yes

相关文章
|
6月前
|
存储 Java C语言
lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】
lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】
47 0
|
XML Java 数据格式
【Lua基础 第2章】lua遍历table的方式、运算符、math库、字符串操作方法
lua遍历table的方式、运算符、math库、字符串操作方法
576 0
【Lua基础 第2章】lua遍历table的方式、运算符、math库、字符串操作方法
|
C# 数据库
Lua Table转C# Dictionary
Lua Table转C# Dictionary
90 0
|
Java 索引
Lua语言——table(表)
Lua语言——table(表)
128 0
|
XML Java 数据格式
【Lua基础 第4章】Lua的流程控制、#的作用、table的创建方式、table表常用方法、函数、多返回值、可变长参数
Lua的流程控制、#的作用、table的创建方式、table表常用方法、函数、多返回值、可变长参数
119 0
【Lua基础 第4章】Lua的流程控制、#的作用、table的创建方式、table表常用方法、函数、多返回值、可变长参数
|
数据采集 存储 JavaScript
Lua 语法 Table 与模块|学习笔记
快速学习 Lua 语法 Table 与模块
157 0
Lua 语法 Table 与模块|学习笔记
Lua Table表实现字典
Lua Table表实现字典
681 0
Lua Table表实现字典
|
存储 应用服务中间件