1
\documentclass{article}
\usepackage{tikz}
\begin{document}

\newcommand\routine[1] {
    \pgfmathsetmacro\temp{0}
    \foreach[parse=true][remember=\temp] \i in {1,...,#1} {
        \pgfmathsetmacro\temp {
            \pgfmathparse{\temp+\i}\pgfmathresult
        }
    }
    \temp
}

\routine{5}
\end{document}

I created a command that prints the nth triangular numbers. First I set \temp to 0 then I add \i the ith time the loop is entered. Everytime \temp is incremented it is updated. I added [remember=\temp] so that it is not lost after each iteration. Then after the end of the loop the result should be printed. Instead I am met with a ! Incomplete \iffalse; all text was ignored after line 16. error. How should I fix this problem?

  • Macros set in a \foreach loop are defined locally and are forgotten as soon as the loop ends. – egreg Oct 22 '22 at 07:16
  • Besides what @egreg said you also have \pgfmathparse inside \pgfmathsetmacro. That is not correct. Just do \pgfmathsetmacro\temp{\temp+\i} (and then what ever else you need to do with \temp). In this case, I'd rather use the function (#1)*(#1+1)/2. – Qrrbrbirlbel Nov 21 '22 at 13:56

2 Answers2

1

Welcome to TeX.SE!!!

You can remember a local variable with the option \global as in \global\edef or, equivalently, \xdef. See, for example, this post: What are the differences between \def, \edef, \gdef and \xdef?.

So, you can do something like the following code:

\documentclass{article}
\usepackage{tikz}

\newcommand\routine[1] {% \pgfmathsetmacro\myfinaltemp{0}% \foreach\i in {1,...,#1} {% \pgfmathtruncatemacro\temp{\myfinaltemp+\i}% \xdef\myfinaltemp{\temp}% <-- remember \myfinaltemp, \xdef = \global\edef }% \myfinaltemp% }

% anotehr, simpler version \newcommand{\mytriangle}[1]{\pgfmathparse{int(#1*(1+#1)/2)}\pgfmathresult}

\begin{document} \noindent \foreach\j in {1,...,10} {\routine{\j} = \mytriangle{\j}\} \end{document}

Which produces:

enter image description here

Juan Castaño
  • 28,426
0

I believe that \foreach is not the best tool for this job.

But you might do it: the printing should be inside the loop, at the last step and you want int.

\documentclass{article}
\usepackage{pgffor}

\newcommand\routine[1]{% \pgfmathsetmacro\temp{0}% \foreach[parse=true][remember=\temp] \i in {1,...,#1} {% \pgfmathsetmacro\temp{int(\temp+\i)}% \ifnum#1=\i\relax\temp\fi }% }

\begin{document}

\routine{5}

\end{document}

Here's an expandable implementation.

\documentclass{article}

\makeatletter \newcommand{\triangular}[1]{% @triangular{0}{0}{#1}% } \newcommand{@triangular}[3]{% % #1 is the current step % #2 is the accumulated total % #3 is the step we want to get at \ifnum#1=#3 \expandafter@firstoftwo \else \expandafter@secondoftwo \fi {\the\numexpr#2+#1}% {\expanded{\noexpand@triangular{\the\numexpr#1+1}{\the\numexpr#2+#1}{#3}}}% } \makeatother

\begin{document}

\triangular{0}\par \triangular{1}\par \triangular{2}\par \triangular{3}\par \triangular{4}\par \triangular{5}\par \triangular{6}

\edef\test{\triangular{10}} \texttt{\meaning\test}

\end{document}

enter image description here

Without \expanded a slightly more complicated version is needed

\newcommand{\@triangular}[3]{%
  % #1 is the current step
  % #2 is the accumulated total
  % #3 is the step we want to get at
  \ifnum#1=#3
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\the\numexpr#2+#1}%
  {\expandafter\@triangular
      \expandafter{\the\numexpr#1+1\expandafter}%
      \expandafter{\the\numexpr#2+#1}{#3}%
  }
}

Finally, the expl3 code:

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\triangular}{m} { \acter_triangular:nnn { 0 } { 0 } { #1 } }

\cs_new:Nn \acter_triangular:nnn { % #1 is the current step % #2 is the accumulated total % #3 is the step we want to get at \int_compare:nTF { #1 = #3 } {% reached \int_eval:n { #2 + #1 } } {% restart \acter_triangular:een { \int_eval:n { #1 + 1 } } { \int_eval:n { #2 + #1 } } { #3 } } } \cs_generate_variant:Nn \acter_triangular:nnn { ee }

\ExplSyntaxOff

\begin{document}

\triangular{0}\par \triangular{1}\par \triangular{2}\par \triangular{3}\par \triangular{4}\par \triangular{5}\par \triangular{6}

\edef\test{\triangular{10}} \texttt{\meaning\test}

\end{document}

egreg
  • 1,121,712