Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}
{
share|improve this question
    
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
add comment

1 Answer 1

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.

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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