Lua iterator and generic for

简介:
lua有两种循环的用法
1.  数字递增用法
> for i=1,10,3 do
>> print(i)
>> end
1
4
7
10


2. generic for用法
不写步长step则默认是1.
> t = {"hello","nihao",nil,"yes"}
> for k,v in ipairs(t) do
>>   print("k:" .. k .. " v:" .. v) 
>> end
k:1 v:hello
k:2 v:nihao

使用table.pack将...变量参数打包成sequence表以及n存储sequences个数.
> c = table.pack("he","hello",nil,"a ")
> for i=1, c.n do
print(c[i])
end
he
hello
nil
a

其他常用的generic for函数
Despite its apparent simplicity, the generic for is powerful. With proper
iterators, we can traverse almost anything in a readable fashion. The standard
libraries provide several iterators, which allow us to iterate over 
the lines of a file (io.lines), 
the pairs of a table (pairs), 
the entries of a sequence (ipairs), 
the words of a string (string.gmatch), 
and so on.

在没有generic for函数前的自定义循环用法, 使用factory 函数封装non-local变量和iterator函数(匿名函数), 多次调用iterator函数, 变更non-local变量的值来达到循环的目的. 例如 : 
> function factory(t)  -- 工厂函数, 返回一个匿名函数
>>   local i = 0  -- 封装一个本地变量
>>   return function () i = i+1; return t[i] end  把上层本地变量引入这个匿名函数(后面用它做循环)
>> end
> tbl = {10,20,30}
> iterator = factory(tbl)  -- 使用工厂函数生成一个循环函数
> while true do
>>   local element = iterator()
>>   if element == nil then break end
>>   print (element)
>> end
10
20
30


直接使用generic for : 
> for element in factory(tbl) do
>>   print (element)
>> end
10
20
30

generic for 的语法  : 
for <var-list> in <exp-list> do
  <body>
end

解释 : 
<var-list> 是1个或多个变量名, 逗号隔开, 不需要事先定义. 列表中的第一个变量为控制变量.
<exp-list> 是一个或多个表达式, 逗号隔开.
Lua处理generic for语法的方法和顺序.
1. 首先运行exp-list中的表达式, 把所有表达式的返回值转成3个返回值, 注意如果其中有返回多值的函数, 最后可能只用第一个返回值. 例如.
> function x(...) return ... end
> = x(1,2,3)
1       2       3
> =x(1,2,3),4
1       4
> a,b,c=x(1,2,3),4  -- 函数后面还有其他变量或表达式时, 取第一个返回值.
> = a,b,c
1       4       nil
> a,b,c = 4,x(1,2,3)  -- 函数在最后一位时, 返回多值
> = a,b,c
4       1       2
> a,b,c = 4,(x(1,2,3))  -- 函数外加括号, 强制取第一个返回值
> = a,b,c
4       1       nil

如果exp-list中有多个表达式, 则需要考虑以上情况, 不管怎么样, 第一次运行这些表达式的结果会转换成3个值, 多则废弃多的, 少则末尾以nil填补.
这三个值分别代表iterator function(使用_f表示), invariant state (使用_s表示) , initial value for the control variable (使用_var表示) .
2. 第二步则调用iterator函数, 并把结果赋予给var-list的各个变量.
var_1, ..., var_n = _f(_s, _var)
_var = var_1
然后判断var_1是否为nil, 如果为nil则退出循环, 如果不为nil则继续调用_f(_s, _var);
所以以下两种用法实际上是同样的效果 :
for var_1, ..., var_n in <exp-list> do <block> end

等同于
do 
local _f, _s, _var = <exp-list>
while true do
  local var_1, ..., var_n = _f(_s, _var)
  _var = var_1
  if _var == nil then break end
  <block>
  end
end

目录
相关文章
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
702 1
|
缓存 NoSQL 搜索推荐
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
本文介绍了如何通过Lua脚本在Redis中实现分布式锁的原子性操作,避免并发问题。首先讲解了Lua脚本的基本概念及其在Redis中的使用方法,包括通过`eval`指令执行Lua脚本和通过`script load`指令缓存脚本。接着详细展示了如何用Lua脚本实现加锁、解锁及可重入锁的功能,确保同一线程可以多次获取锁而不发生死锁。最后,通过代码示例演示了如何在实际业务中调用这些Lua脚本,确保锁操作的原子性和安全性。
828 6
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
831 0
|
NoSQL Redis 数据库
Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
通过本文的介绍,我们详细讲解了 Lua 脚本在 Redis 中的作用、`eval` 命令的使用方法以及 `redis.call` 和 `redis.pcall` 的区别和用法。通过合理使用 Lua 脚本,可以实现复杂的业务逻辑,确保操作的原子性,并减少网络开销,从而提高系统的性能和可靠性。
1105 13
|
监控 安全
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
326 6
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
278 2
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
JSON 监控 数据格式
使用Lua代码扩展上网行为管理软件的脚本功能
本文介绍了如何使用Lua脚本增强上网行为管理,包括过滤URL、记录用户访问日志、控制带宽和自动提交监控数据到网站。Lua是一种轻量级语言,适合编写扩展脚本。文中提供多个示例代码,如URL过滤器、用户活动日志记录器和带宽控制器,帮助用户根据需求定制网络管理功能。通过这些示例,用户可以快速掌握Lua在上网行为管理中的应用。
429 4
|
存储 NoSQL Redis
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决