5

Is there a way to run a command on a range of consecutive integers (say, 11, 12, 13, 14, 15), specifying only the first and last numbers (11 and 15)? Basically I'm looking for the general LaTeX equivalent of tikz's \foreach \x in {11,…,15}.

In the MWE below (using etoolbox), \forcsvlist\mycommand{11,12,13,14,15} correctly runs \mycommand on each of the four inputs, and \myrange{11}{15} indeed expands to 11,12,13,14,15. But putting them together \forcsvlist\mycommand{\myrange{11}{15}} doesn't work. I think it comes down to order of expansion, which is way over my head.

\documentclass{article}
\usepackage{amsmath, etoolbox}
\newcommand\mycommand[1]{\boxed{#1} }
\newcounter{mycounter}
\newcommand\myrange[2]{
    \defcounter{mycounter}{#1}
    \themycounter%
    \whileboolexpr
        {test {\ifnumless{\themycounter}{#2}}}
        {\stepcounter{mycounter},\themycounter}
    }
\begin{document}
\forcsvlist\mycommand{11,12,13,14,15}
does not equal
\forcsvlist\mycommand{\myrange{11}{15}}
\end{document}

I've looked at Loop Multi-Contingency using etoolbox, Print all elements of a working array created with etoolbox package, and Remove extra curly braces, but couldn't figure out how to apply them to this situation.

2
  • You are defining and setting counters in your \myrangemacro -- this can't be expandable. There might be more issues, but I can't check right now
    – user31729
    Commented Feb 19, 2018 at 20:45
  • Similar (?) tex.stackexchange.com/a/360959/31729
    – user31729
    Commented Feb 19, 2018 at 20:59

3 Answers 3

7

It is just as easy to loop without any specific package code in this case. enter image description here

\documentclass{article}
\usepackage{amsmath}
\newcommand\mycommand[1]{\boxed{#1} }

\makeatletter
\newcommand\zz[3]{%
 #1{#2}%
 \ifnum#2=\numexpr#3\relax\expandafter\@gobblefour\fi
 \zz#1{\the\numexpr#2+1\relax}{#3}%
 }
\makeatother

\begin{document}


\zz\mycommand{11}{15}
\end{document}
3
  • you get nested \numexpr which numexperts usually remove by suitable \expandafter ;-) (this may also surprise macro \mycommand if the latter parses in some way its argument and chokes on ten nested \numexpr's)
    – user4686
    Commented Feb 20, 2018 at 13:41
  • @jfbu I wondered about adding more expandafter but thought it would obscure the main point, it's not actually wrong is it? Commented Feb 20, 2018 at 13:48
  • nothing wrong ;-)
    – user4686
    Commented Feb 20, 2018 at 15:02
4

Optionally providing also the step; the \int_step_function:nnnN macro takes as argument the starting point, the step, the final point and finally the one parameter macro to which the current value is passed as argument.

\documentclass{article}
\usepackage{xparse}

\newcommand\mycommand[1]{\fbox{#1} }

\ExplSyntaxOn
\NewDocumentCommand{\forrange}{mO{1}mm}
 {
  \int_step_function:nnnN { #1 } { #2 } { #3 } #4
 }
\ExplSyntaxOff

\begin{document}

\forrange{11}{15}{\mycommand}

\forrange{11}[4]{27}{\mycommand}

\forrange{15}[-1]{11}{\mycommand}

\end{document}

enter image description here

4
\documentclass{article}
\usepackage{xinttools}

\newcommand\mycommand[1]{\fbox{#1} }

\newcommand\forrange[4][1]%
    {\xintFor*##1in{\xintSeq[#1]{#2}{#3}}\do{#4{##1}}}

\begin{document}

\forrange{11}{15}{\mycommand}

\forrange[4]{11}{27}{\mycommand}

\forrange[-1]{15}{11}{\mycommand}

\end{document}

Now I picked over that abstraction from another authoritative answer. For everyday use you can also use

\xintFor #1 in {99, 37, -53, 'zouzou'}\do{ whatever }

and replace #1 by ##1 if inside a macro definition.

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .