2

While trying to give a foreach loop a macro to loop into, I found on Macro not working in foreach loop that I can use \pgfplotsforeachungrouped and it was indeed able to loop through my macro.

However, macro: it returns my list twice. Here is a MWE of what I am talking about:

\documentclass{article}

\usepackage{pgfplots}
\newcommand{\xlabelsol}{0/0,1/1,2/2}
\pgfplotsset{compat=1.18}
\begin{document}
    \pgfplotsforeachungrouped  \x/\label in {\xlabelsol}{%
        \x/\label \\
    }
\end{document}

And the outcome of the MWE:

Doubled list

Ireally need to use a macro for the list in the loop because I am trying to automate the creation of pdf files with a template for the project I am working on. Also, a solution would need to be compatible with XeLaTeX

I have tried to look up how to fix this issue but I can't seem to find a solution.

0

2 Answers 2

3

First, for the original \foreach provided by pgffor (sub)package, its syntax is either

\foreach \x/\label in {0/0,1/1,2/2} {<loop body>}
% or
\foreach \x/\label in \xlabelsol {<loop body>}

but never

\foreach \x/\label in {\xlabelsol} {<loop body>} % wrong syntax

Again, in the easiest case, <list> is either a comma-separated list of values surrounded by curly braces or it is the name of a macro that contain such a list of values.

https://tikz.dev/pgffor#\foreach

Then, \pgfplotsforeachungrouped from pgfplots is simpler than \foreach, such that it can't handle list stored in a macro, like

% not supported in pgfplots v1.18.1
\pgfplotsforeachungrouped  \x/\label in \xlabelsol {<loop body>}

Finally, here's a patch to \pgfplotsforeachungrouped:

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\makeatletter
\long\def\pgfplotsforeachungrouped@#1/#2in{%
    \pgfutil@ifnextchar\bgroup{%
        \pgfplotsforeachungrouped@@{#1}{#2}%
    }{%
%       \pgfplots@error{Found unexpected characters: expected 'in '.}%
    \pgfplotsforeachungrouped@@@{#1}{#2}%
    }%
}

\long\def\pgfplotsforeachungrouped@@@#1#2#3{%
  \expanded{\unexpanded{\pgfplotsforeachungrouped@@{#1}{#2}}{\unexpanded\expandafter{#3}}}%
}
\makeatother

\begin{document}
\setlength\parindent{0pt}
\newcommand{\xlabelsol}{0/0,1/1,2/2}

\foreach  \x/\y in \xlabelsol {%
    (\x)(\y) \\
}

\pgfplotsforeachungrouped \x/\y in \xlabelsol {%
    (\x)(\y) \\
}
\end{document}

Output is two copies of

(0)(0)
(1)(1)
(2)(2)
3
  • Is it safe to patch this command? Commented Jun 6, 2023 at 15:51
  • Reported to pgfplots, see github.com/pgf-tikz/pgfplots/issues/462. Commented Jun 6, 2023 at 15:58
  • @JasperHabicht \pgfplotsforeachungrouped@ has only one implementation in pgfplots so ... it's as dangerous as patching any other internal commands of a package. :) Commented Jun 6, 2023 at 16:00
5

The command \xlabelsol needs to be expanded before the loop starts. So you could do something like this:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\newcommand{\xlabelsol}{0/0, 1/1, 2/2}
\begin{document}
    \edef\myloop{%
        \noexpand\pgfplotsforeachungrouped \noexpand\x/\noexpand\label 
            in {\xlabelsol}{%
            \noexpand\x/\noexpand\label \space
        }%
    }\myloop
\end{document}

Which would ouput:

enter image description here

2
  • 2
    \expanded{\unexpanded{\pgfplotsforeachungrouped \x/\label} in {\xlabelsol}}{\x/\label \space} works too (sorry for wrapping it on only one input line)
    – user691586
    Commented Jun 6, 2023 at 15:31
  • @user691586 Thanks, this is a nice idea since it simplifies the code and makes it more readable. Commented Jun 6, 2023 at 15:49

You must log in to answer this question.

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