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.

  • 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 Feb 19 '18 at 20:45
  • Similar (?) tex.stackexchange.com/a/360959/31729 – user31729 Feb 19 '18 at 20:59
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}
  • 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 Feb 20 '18 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? – David Carlisle Feb 20 '18 at 13:48
  • nothing wrong ;-) – user4686 Feb 20 '18 at 15:02
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

3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.