[I encourage you to check out Phelype's impressive approach]
I hear about macros that do things like "expand until they reach an unexpandable token" and this question may (or may not) be related to that kind of thing and the \romannumeral
trick. In particular, I'm thinking of the behavior of things like \numexpr
which terminate upon encountering a \relax
token. However, they also terminate without a \relax
token, if an end-of-group is reached (and apparently also when a begin-group is reached). Thus
\the\numexpr 1+1+1\relax
and
{\the\numexpr 1+1+1}
both work.
I have an interest in a recursive version of \numexpr
, call it \rnumexpr
, that will expand groups in its argument, continuing the calculation using the previously grouped data.
Here it is and it seems to work great. It relies on a feature of tokenization that if a group is passed as an argument, the grouping is stripped and the contents of the group become the actual argument.
However, with my coding, it requires an explicit terminator (in this case, \rrelax
).
EDITED to handle up to 8 nesting levels (i.e., 8 successive left braces), but it still can't handle an implicit delimiter
\documentclass{article}
\makeatletter
\let\@relax\relax
% CAN HANDLE 8 SUCCESSIVE LEFT BRACES
\def\rnumexpr#1\rrelax{\numexpr\@rnumexpr
\@empty\@empty\@empty\@empty\@empty\@empty\@empty\@empty\@empty
#1\relax \@empty\@empty\@empty\@empty\@empty\@empty\@relax}
\def\@rnumexpr#1#2#3#4#5#6#7#8#9\@relax{%
#1\ifx\relax#2\relax\else\@rnumexpr#2#3#4#5#6#7#8#9\@relax\fi}
\makeatother
\begin{document}
\the\numexpr+1+1+1+1+1\relax,
\the\numexpr+1+1{+1+1+1}\relax,
\the\numexpr+1+1{+1{+1+1}}\relax
\the\rnumexpr+1+1+1+1+1\rrelax,
\the\rnumexpr+1+1{+1+1+1}\rrelax,
\the\rnumexpr+1+1{+1{+1+1}}\rrelax,
Expandable! \edef\z{\the\rnumexpr+1+1{+1{+1+1}}\rrelax}\z
\the\rnumexpr+1+1+1+1+1\rrelax,
\the\rnumexpr+1+1{+1+1+1}\rrelax,
\the\rnumexpr+1+1{+1{+1+1}}\rrelax,
\the\rnumexpr{+1{+1{+1{+1{+1{+1{+1{+1{+1{+1}}}}}}}}}}+1\rrelax,
Can handle up to 8 successive left braces:
\the\rnumexpr{+1{{{{{{{{+1}+1}+1}+1}+1}+1}+1}+1}+1}+1\rrelax{},
\the\rnumexpr{+1{{{{{{{{+1}}}}}}}}}+1\rrelax{},
\the\rnumexpr{{{{{{{{+1}}}}}}}}\rrelax{}
{\the\numexpr1+1+1} numexpr uses implicit delimiter
%{\the\rnumexpr1+1+1}
but rnumexpr won't work...EXPLICIT DELIMITER EXPECTED
\end{document}
The first two lines compare the results of \numexpr
and \rnumexpr
, showing how \numexpr
appears to stop when it reaches the begin-group, whereas \rnumexpr
extracts it and continues the calculation. It is even shown to be expandable!
The 3rd and 4th lines show put \rnumexpr
to a tougher test. Phelype pointed out that my original request was quite limited as to how many levels of nesting it could handle. This edited approach can handle more nesting levels (up to 8 successive left braces), but still has a finite limit.
The 5th line of output shows how \numexpr
can terminate without an explicit \relax
. Attempting such a syntax with \rnumexpr
does not work because I've coded it to expect an explicit delimiter.
Is there a way to redefine \rnumexpr
to also end when reaching an end-of-group rather than an explicit terminator (while at the same time not ending when reaching a start-of-group)
Note: The purpose here is not to develop a logical approach to nested calculations. While that may be a desirable thing in certain applications, that is not what is being attempted here. Thus, approaches that suggest using parens rather than braced subunits do not address my concern.
As I replied to David, the process I am really interested in is counting certain "qualified" tokens across an arbitrary argument. Using the approach I am taking to this larger question, for example, I ignore "unqualified" tokens, but when I come across "qualified" tokens, I place a +1
in the output macro. However, the process I have developed also retains the grouping of the original argument in the output macro.
So when I am done examining the argument token-by-token (with grouping retained), the output contains an arbitrary number of +1
tokens within the argument's original grouping structure. It is this output macro that I hope to operate on with \rnumexpr
. Since I am writing the code, I can always be sure that I add the \rrelax
at the end, but this question has more to do with me wondering if it was possible to rewrite \rnumexpr
without the closing delimiter.
{}
groups rather than()
? especially\rnumexpr+1+1{+1+1+1}\rrelax
which looks like it should be an error rather than\rnumexpr+1+1+{1+1+1}\rrelax
?\relax
or brace-delimited, or anything else). With an optional delimiter like for\numexpr
it could perhaps be done un-expandably (using\futurelet
and a huge processing time). Both I think it's not possible without making the code extremely (and I mean it) fragile. Would you be okay with a mandatory delimiter?\numexpr
expression with ignorable relax isn't feasible with anything like a reasonable amount of code.\numexpr
, but I can't think of an expandable way to test whether that token is}
without running intoextra }
errors.