There are cases where you want to know how many of a certain match there are.
Here's an example:
uparse "<<<stuff>>>" [
(n: 0)
some ["<" (n: n + 1)]
x: between here n ">"
]
Here I'm just trying to match the number of >
on the right to how many <
were on the left.
(Note: I still think this INTEGER! abstracting of rules is confusing to read. Is a REPEAT/LOOP keyword missing that would help? I've written about this, please register an opinion.)
Meet TALLY!
uparse "<<<stuff>>>" [
n: tally "<"
x: between <here> repeat n ">"
]
So oddly enough, TALLY without paying attention to the result can be used as the replacement for historical instances of ANY or WHILE.
>> uparse "aaaccc" [some "a" tally "b" tally "c"]
== 3
>> uparse "aaaccc" [some "a" tally "b" some "c" tally "d"]
== 0
"Count the number of times this matches" along with ignoring the count is pretty lightweight, and perhaps some would consider it idiomatic for opt some
opt some
tally ; three fewer characters, same as WHILE
I don't care for the tradeoff myself...but...it's worth pointing out that many result-bearing constructs have their results ignored.
1 Like
So I've never used this unusual suggestion of taking advantage of the zero-times-match.
But I'm wondering: are we limiting TALLY's applications by not allowing it to ever fail?
If you want a non-matching TALLY to be zero, that's now easy enough, since integers are literal:
[tally rule | 0]
And if you want NULL in the zero case, you could then say:
opt tally rule
But you don't have these choices when TALLY will never fail.
Still...it's a little hard for me to say it won't consider a count of 0. I can think of a lot of scenarios where that is what you want, and having to write [tally rule | 0] for it feels awkward.