# How to assign values with foreach?

I have trouble to assign values with \foreach. Can somebody help me? The following code is wrong. The purpose is to asing the values: \lx1=1, \ly1=2, \lz1=3, for example.

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
\def\x{\y}
\x{\y}
{

-
Do you want to assign values to \lx1, \ly1 and \lz1 before entering \foreach? Moreover, you cannot use macros as-is with numbers in it. –  Werner Aug 27 '12 at 2:32

There are several reasons, why this does not work:

• \lx1 is not a command name, it consists of the command \lx, followed by digit 1. Either replace 1 by a letter or the usage is a little more complex via \csname.

• \x and \y contain the x and y values, the definition of \x defines \x, not the macro inside and \y whill change with every loop. \expandafter expands a macro one level:

\expandafter\def\x{...}


Doing the same with \y requires lots of more \expandafter, therefore using \let is easier here.

• \foreach puts the loop body inside groups, thus local definitions will be lost. This can be solved by global definitions.

Example:

\usepackage{pgffor}

\foreach \x/\y in {\lxA/1,\lyA/2,\lzA/3}
{%
\global\expandafter\let\x\y
}


Or with \lx1 as macro:

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
\begingroup
\escapechar=-1 % suppresses backslash with \string
\global\expandafter\let
\csname \expandafter\string\x\endcsname\y
\endgroup
}

\typeout{\expandafter\string\csname lx1\endcsname:
\expandafter\meaning\csname lx1\endcsname}


Addition for the fans of \expandafter:

\gdef can be used instead of \global\let by using additional \expandafter:

\foreach \x/\y in {\lxA/1,\lyA/2,\lzA/3}
{%
\expandafter\expandafter\expandafter
\gdef\expandafter\x\expandafter{\y}%
}

\typeout{\string\lxA: \meaning\lxA}

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
\begingroup
\escapechar=-1 % suppresses backslash with \string
\expandafter\gdef
\csname \expandafter\string\x\expandafter\endcsname
\expandafter{\y}%
\endgroup
}

\typeout{\expandafter\string\csname lx1\endcsname:
\expandafter\meaning\csname lx1\endcsname}


As can be seen, the version with \let is more efficient and elegant.

-
Is it possible to make the same thing but using \def (or \gdef) and with each value of \y defined as {some TeX code...}? You just say it requires "lots of \exandafter"... –  Paul Gaborit Aug 27 '12 at 6:51
Thanks for your addition (Am I really a fan of \expandafter? ;-)). –  Paul Gaborit Aug 27 '12 at 8:31
I'll take the first solution. It's simple and clear. Thanks Heiko. –  gnoejh Aug 29 '12 at 8:26