[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: lpeg.Cb bug (?) with repeated evaluation of group capture pattern
- From: Roberto Ierusalimschy <roberto@...>
- Date: Wed, 14 Sep 2016 16:27:54 -0300
> I found that for some reason LPeg is evaluating a pattern in a group
> capture multiple times:
>
> local patt = lpeg.Cg(lpeg.Ct"", "foo") * lpeg.Cb "foo" * lpeg.Cb "foo";
> print(patt:match "") --> table: 0x1634280 table: 0x16342c0
>
> (two unique tables!) Or:
>
> local patt = lpeg.P {
> lpeg.Cg(lpeg.V "v", "foo") * lpeg.Cb "foo" * lpeg.Cb "foo";
> v = lpeg.Ct "" / function(...) print(...) return ... end,
> }
> print(patt:match "") --> table: 0x233d4a0 \n table: 0x22f0ab0 \n
> table: 0x233d4a0 table: 0x22f0ab0
>
> Whereas:
>
> local patt = lpeg.Cg(lpeg.Cmt("", function(s,p) return p, {} end),
> "foo") * lpeg.Cb "foo" * lpeg.Cb "foo";
> print(patt:match "") --> table: 0x87a950 table: 0x87a950
>
> (one table!)
>
> Is this a bug?
Well, I know it works that way :-)
Except for 'Cmt', captures in LPeg have a functional flavor. LPeg does
not specify in what order it evaluates its captures. It does not specify
even whether it actually will execute a capture. All that matters are
the results from the captures. (For instance, the manual does not say
that LPeg will not execute captures for failed match attempts; what it
ensures is that those values are not used in its results.)
In general, we should avoid captures with side effects (again, except
for 'Cmt') or, more to the point, we should not depend on these side
effects. (Checking whether two tables with the same contents are the
same is an example of a dependency on a side effect.) If we must
accumulate something, we should use a fold.
-- Roberto