【发布时间】:2015-12-29 05:33:31
【问题描述】:
(我使用的是 Lua 5.2 和 LPeg 0.12)
假设我有一个模式P 会产生一些不确定数量的捕获(如果有的话),我想编写一个模式Q 来捕获P 以及P 之后的位置--但是以便在P 的捕获之前返回该位置。本质上,如果lpeg.match(P * lpeg.Cp(), str, i) 产生v1, v2, ..., j,那么我希望lpeg.match(Q, str, i) 产生j, v1, v2, ...。
这是否可以在每次匹配P 时不必创建新表来实现?
主要是为了简化一些产生迭代器的函数。 Lua的stateless iterator functions只获取一个控制变量,需要是迭代器函数返回的第一个值。
在一个允许人们命名可变参数函数的 last 参数的世界中,我可以这样写:
function pos_then_captures(pattern)
local function roll(..., pos)
return pos, (...)
end
return (pattern * lpeg.Cp()) / roll
end
唉。简单的解决方案是明智地使用lpeg.Ct():
function pos_then_captures(pattern)
-- exchange the order of two values and unpack the first parameter
local function exch(a, b)
return b, unpack(a)
end
return (lpeg.Ct(pattern) * lpeg.Cp()) / exch
end
或者让lpeg.match 的调用者跳起打包/删除/插入/解包的舞蹈。尽管后者听起来很恶心,但我可能会这样做,因为lpeg.Ct() 可能会对pos_then_captures 的病态但“正确”的论点产生一些意想不到的后果。
每次成功匹配pattern 时,其中任何一个都会创建一个新表,诚然这在我的应用程序中并不重要,但是有没有办法在没有任何打包解包魔法的情况下做到这一点?
我不太熟悉 Lua 的内部结构,但感觉我真正想做的就是从 Lua 的堆栈中弹出一些东西并将其放回其他地方,这看起来不像是一个操作直接或有效地支持,但也许 LPeg 在这种特定情况下可以做一些事情。
【问题讨论】:
-
您可以在 vararg 函数中使用
select来获取从 vararg 参数中的任意点开始的元素select(-1, ...)是最后一个元素。所以return select(-1, ...), ...应该将最后一个元素添加到返回的列表中,尽管它不会从列表的末尾删除该元素,但是如果您的循环在到达其计数器时停止,这对这种用法无关紧要。 -
select非常有趣。不敢相信我在手册中错过了!谢谢:)