1

I can use the \foreach loop to iterate over an array of strings:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\foreach \v in {A, B}{
  \input{the\v file.txt}
}
\end{document}

Now, I would like to compose a string as a macro as in:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\newcommand\var{A, B} % <<< macro
\foreach \v in \var{
  \input{the\v file.txt}
}
\end{document}

Then I get a problem:

! LaTeX Error: File `theA, Bfile.txt' not found.

Using \def instead of \newcommand creates the same problem using Latex version pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6).

How to solve?

Viesturs
  • 7,895
  • Have you tried \def instead of \newcommand? – Foitn Jun 12 '18 at 14:34
  • I do not get your error for the 2nd case. I get the proper errors: ! LaTeX Error: File 'theAfile.txt' not found. and ! LaTeX Error: File 'theBfile.txt' not found. which would not occur if those files existed on my system. – Steven B. Segletes Jun 12 '18 at 14:42
  • You get theA, Bfile.txt if you call \foreach \v in {\var}{...}; not with your code. – egreg Jun 15 '18 at 08:08
  • @egreg, in pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6) I have the problem without the braces {. In pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Debian) I need to add the braces to generate the problem. – Viesturs Jun 15 '18 at 08:49
  • 2
    Probably the relevant information is the version of TikZ. Using newer code in a very old release of TeX is hopeless; anyway, try \expandafter\foreach\expandafter i\expandafter n\expandafter{\var}{...} – egreg Jun 15 '18 at 08:57

3 Answers3

3

I can reproduce the problem with TikZ/PGF version 1.7 (2006/10/11, twelve years ago), but not with later versions.

I guess that, starting with version 2.0, the syntax of \foreach has been extended to cope with the cases

\foreach \v in {<list>}{...}
\foreach \v in \cs{...}

but the latter case was not possible in previous versions.

Solution: update your TeX system.

For the old system you can do, which will also work in newer releases, as follows.

\documentclass{article}
\usepackage[pdftex]{graphicx}
\usepackage{tikz}
\begin{document}
\newcommand\var{A, B} % <<< macro
\expandafter\foreach\expandafter\v\expandafter i\expandafter n\expandafter{\var}{
  \input{the\v file.txt}
}
\end{document}

I had to go back to TeX Live 2007, the earliest release I have on one of my machines, to reproduce the issue: This is pdfTeXk, Version 3.1415926-1.40.9 (Web2C 7.5.7)

egreg
  • 1,121,712
1

Your \newcommand defines one string, so when called it produces that string. For more about the differences, see https://tex.stackexchange.com/a/658/114249. What you should use is the \def command:

\documentclass{article}
\usepackage{tikz}
\begin{document}
    \def\var{A, B} % <<< macro
    \foreach \v in \var{
        \input{the\v file.txt}
    }
\end{document}

This tries to open theAfile.txt and theBfile.txt as requested.

Foitn
  • 298
  • I compiled your code and got exactly the same problem. – Viesturs Jun 12 '18 at 14:40
  • You still get the theA, Bfile.txt not found, so for that exact string? – Foitn Jun 12 '18 at 14:41
  • I use your code exactly. – Viesturs Jun 12 '18 at 14:42
  • And both of the files, so the theAfile.txt and theBfile.txt exist in the same folder as your .tex file is in? Because this does work for me... – Foitn Jun 12 '18 at 14:43
  • That is using Latex version pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6). I succeeded to compile your code using Latex version Version 3.14159265-2.6-1.40.16 (TeX Live 2015/Debian) – Viesturs Jun 12 '18 at 14:52
  • ah, alright, so this answers your question than? – Foitn Jun 12 '18 at 14:54
  • If you see my answer as a solution, could you please mark it as the answer? – Foitn Jun 13 '18 at 06:37
  • Could you explain in your answer the technical clockwork why \def is better than \newcommand in this case? Also, no need to add such reminders as they are provided by the system automatically. – Viesturs Jun 13 '18 at 20:59
  • 1
    Compile with \newcommand in the latest version of pdflatex and see if it still works. – Manuel Jun 15 '18 at 07:45
  • 2
    @Foitn There is no difference at all between \newcommand{\var}{A, B} and \def\var{A, B} (apart from the check done by the former and the fact that the macro it generates is \long, which is inessential here). – egreg Jun 15 '18 at 08:05
  • Than why does it work with \def and not with \newcommand? (Not to prove you wrong or anything, I'm really interested now) – Foitn Jun 15 '18 at 11:14
0

Maybe you use some package releases where \foreach's list-argument must not come from a macro but must be delivered fully expanded.

If so, then something like the following might help:

\documentclass{article}
\usepackage{tikz}
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand\OneLevelExpandedSecond[2]{%
  \expandafter\PassFirstToSecond\expandafter{#2}{#1}%
}%
\begin{document}
\newcommand\var{A, B} % <<< macro
\OneLevelExpandedSecond{\foreach \v in }{\var}{% <- We don't want unneeded spaces due to \endlinechar!
  \input{the\v file.txt}%  <- We don't want unneeded spaces due to \endlinechar!
}% <- We don't want unneeded spaces due to \endlinechar!
\end{document}
Ulrich Diez
  • 28,770