一个悄无声息失败的Lua迭代器?
2014-6-11 12:59:30
收藏:0
阅读:143
评论:2
我有一个非常简单的问题需要使用一个简单的迭代器。
假设我设计了一个名为“files()”的函数,可以迭代访问文件夹中的所有文件:
for file in files("/path/to/folder") do
print(file)
end
现在,看起来完美无缺,但是有一个问题:如果文件夹不存在或者我们没有读取它的权限怎么样?
我们如何表明这样的错误?
一种解决方案是在这种情况下让“files()”返回“nil,无读取权限”。我们可以将“files()”调用包装在“assert()”中:
for file in assert(files("/path/to/folder")) do
print(file)
end
这似乎解决了问题。但是,这强迫我们的用户总是使用“assert()”。如果用户不关心错误怎么办?对于这种用户,我们希望我们的“files()”表现得好像文件夹是空的。但是Lua--如果“files()”表明错误--会尝试调用返回的“nil”,这将导致错误(“尝试调用一个空值”)。
那么,
我们如何设计一个迭代器“files()”,以迎合既关心错误的用户,又不关心错误的用户?
如果不可能,你会建议什么替代方案?
点赞
用户3677376
首先:不要返回 nil 加错误消息,考虑在 files 函数中引发错误(使用 error)。这样你就不会忘记 assert 调用,并且不会出现令人困惑的 "attempt to call a nil value" 错误。
当你不想引发错误时,可以在 files 中传递一个额外的布尔参数——在这种情况下,你应该返回一个空函数 (function() end),而不是调用 error。
一个更通用的方法如下所示:
-- 立即停止 for 循环的迭代器
local function dummy_iter() end
-- 捕获错误并在这种情况下跳过 for 循环
function iterpcall( g, ... )
local ok, f, st, var = pcall( g, ... )
if ok then
return f, st, var
else
return dummy_iter
end
end
for file in iterpcall( files, "/path/to/folder" ) do
print( file )
for line in iterpcall( io.lines, file ) do -- 也适用于其他迭代器
print( line )
end
end
上面的 iterpcall 实现仅处理迭代器 生成器 ( files 或 io.lines ) 中引发的错误,而不是迭代器函数 ( f ) 本身中引发的错误。你必须在一个带有 pcall 的闭包中包装 f 才能做到这一点。
2014-06-11 11:12:27
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
有一个问题是,如果在迭代过程中出现错误(例如,对于递归迭代的子文件夹访问被拒绝),你想要做什么。在这种情况下,
assert无法帮助你。在这种情况下,我创建了两个迭代器的变体(内部和外部)。
-- 抛出错误 for file in files(...) do ... end -- 返回错误 files(...,function(file) ... end)或者只创建两个不同的迭代器。