# How to make global a color list definition with \@namedef done inside a foreach loop

### Motivation

As stated in the title, I'm trying to define a command able, from a list of colors as input, to create a list in which colors are numbered. This, manually, has been done in Arrows coordinates in TikZ

### Preliminary work

I've tried to search in the site questions related to the problem, such as How to define macros in a foreach loop with effects between iterations and after the loop without using global?, How to define macros in a foreach loop with effects between iterations and after the loop without using global? (especially solutions shown in Martin's comment). But I can't figure out a solution when the definition is based on \@namedef

### The minimal-non-working-example

This is what I tried:

\documentclass[11pt,a4paper]{article}
\usepackage{tikz}

\makeatletter

\newcommand{\setcolorlist}[1]{
\foreach \listitem [count=\i] in {#1}{
\global\let\@tempa\@namedef{color@\i}{\listitem}
}
\@tempa
}

% Command in which colors are necessary
\newcommand{\drawcoloredarrows}[1]{
\foreach \i  in {#1}{
\edef\mycolor{\@nameuse{color@\i}}
\draw[\mycolor,-stealth] (0,-\i)--(2,-\i);
}
}

\makeatother

\begin{document}
\setcolorlist{red,cyan,blue,green}

\begin{tikzpicture}
\drawcoloredarrows{1,...,4}
\end{tikzpicture}
\end{document}


getting:

### How it should work

This is how it should work:

\documentclass[11pt,a4paper]{article}
\usepackage{tikz}

\makeatletter
\@namedef{color@1}{red}
\@namedef{color@2}{cyan}
\@namedef{color@3}{blue}
\@namedef{color@4}{green}

\newcommand{\setcolorlist}[1]{
\foreach \listitem [count=\i] in {#1}{
\global\let\@tempa\@namedef{color@\i}{\listitem}
}
\@tempa
}

% Command in which colors are necessary
\newcommand{\drawcoloredarrows}[1]{
\foreach \i  in {#1}{
\edef\mycolor{\@nameuse{color@\i}}
\draw[\mycolor,-stealth] (0,-\i)--(2,-\i);
}
}

\makeatother

\begin{document}
%\setcolorlist{red,cyan,blue,green}

\begin{tikzpicture}
\drawcoloredarrows{1,...,4}
\end{tikzpicture}
\end{document}


getting:

-

With this macro

\newcommand{\setcolorlist}[1]{
\foreach \listitem [count=\i] in {#1}{
\global\let\@tempa\@namedef{color@\i}{\listitem}
}
\@tempa
}


you're basically doing

\global\let\@tempa\@namedef


and indeed "color@1red" and so on is printed. Then \@tempa (which is now \@namedef) has to be executed, which probably can't.

With \setcolorlist{red,green,blue} you want to do

\@namedef{color@1}{red}
\@namedef{color@2}{green}
\@namedef{color@3}{blue}


so you want to say

\@namedef{color@\i}{<expansion of \listitem>}


but globally. Since \@namedef{x} expands to

\expandafter\def\csname x\endcsname


and you need to access the expansion of \listitem, the following will do

\newcommand{\setcolorlist}[1]{%
\foreach \listitem [count=\i] in {#1}{%
\global\@namedef{color@\i\expandafter}\expandafter{\listitem}
}%
}


Alternatively, since you know that \listitem and \i expand to a string,

\newcommand{\setcolorlist}[1]{%
\foreach \listitem [count=\i] in {#1}{%
\begingroup\edef\x{\endgroup
\global\noexpand\@namedef{color@\i}{\listitem}}\x
}%
}


Notice that Ahmed method works too, because at each successive step \listitem is defined to expand to the current color name. However that method would fail if you need to do something more complicated that a simple macro equivalence.

### Mandatory expl3 solution

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\setcolorlist}{ m }
{
\claudio_setcolorlist:n { #1 }
}
\int_new:N \l_claudio_cycle_int
\cs_new_protected:Npn \claudio_setcolorlist:n #1
{
\int_zero:N \l_claudio_cycle_int
\clist_map_inline:nn { #1 }
{
\int_incr:N \l_claudio_cycle_int
\cs_set:cpn { color@ \int_to_arabic:n { \l_claudio_cycle_int } } { ##1 }
}
}
\ExplSyntaxOff


You can choose whether doing the assignments globally or locally (use \cs_gset:cpn in the former case), but this is not necessary. So this method is superior to the \foreach one, as it doesn't force you to do global definitions unless you need to.

-
Great answer, thanks. This is a good starting point not only to understand expansions, but also for LaTeX3 because I'm planning to have a look soon at it. –  Claudio Fiandrino Oct 26 '12 at 15:43

Try

\documentclass[11pt,a4paper]{article}
\usepackage{tikz}

\makeatletter
\newcommand{\setcolorlist}[1]{%
\foreach \listitem [count=\i] in {#1}{
\global\expandafter\let\csname color@\i\endcsname\listitem
}
}

% Command in which colors are necessary
\newcommand{\drawcoloredarrows}[1]{
\foreach \i  in {#1}{
\draw[\@nameuse{color@\i},-stealth] (0,-\i)--(2,-\i);
}
}

\makeatother

\begin{document}
\setcolorlist{red,cyan,blue,green}
\begin{tikzpicture}
\drawcoloredarrows{1,...,4}
\end{tikzpicture}
\end{document}


Here is my preferred approach:

\documentclass{article}
\usepackage{tikz}
\makeatletter
\krddefinekeys{claudiocolor}[claudio@col@]{%
cmd/1/black;cmd/2/black;cmd/3/black;cmd/4/black;cmd/5/black;cmd/6/black;
}
\newcommand*\setcolorlist[1]{\krdsetkeys{claudiocolor}{#1}}
\newcommand*\usecolor[1]{\@nameuse{claudio@col@#1}}
% Command in which colors are necessary:
\newcommand*\drawcoloredarrows[1]{%
\foreach \x in {#1}{%
\draw[\usecolor\x,-stealth] (0,-\x)--(2,-\x);
}%
}
\makeatother

\begin{document}
\setcolorlist{1=red,2=blue,3=cyan,4=green,5=magenta,6=purple}
\begin{tikzpicture}
\drawcoloredarrows{1,...,4}
\end{tikzpicture}
\end{document}

-
The \setcolorlist works perfectly, thanks. :) So, basically, the definition by means of \@namedef was not a good choice. I should really study the expansions... –  Claudio Fiandrino Oct 25 '12 at 16:56
You have a redundant \expandafter. :) –  egreg Oct 25 '12 at 17:22
@egreg: Thanks. Removed. –  Ahmed Musa Oct 26 '12 at 14:04