# Difficulty with macro expansion

I'm not getting the output I want from my LaTeX code, and I think the problem is that I'm not expanding things at the right times.

## Code

\documentclass{article}

\usepackage{tikz}
\usepackage{etextools}

\makeatletter

% The result of calling
%   \@defineLine{foo}{35}
% is that the command \wickerson@foo@pos gets defined as 35.
\newcommand*\@defineLine[2]{%
\typeout{Defining wickerson@#1@pos = #2}
\expandafter\xdef\csname wickerson@##1@pos\endcsname{#2}
}

% Project the pos-field from the line with the given
% identifier. For instance, if \wickerson@foo@pos=35 then
%   \@getLinePos{foo}
% will give 35.
\xdef\@getLinePos#1{\csname wickerson@#1@pos\endcsname}

% A comma-separated list of "active" lines. Each element is
% a line identifier.
\newcommand*\@activeLines{}

% Add the given identifier to the list of active lines.
}

% Remove the given identifier from the list of active lines.
\newcommand*\@removeFromActiveLines[1]{%
\@expandtwoargs\@removeelement{#1}\@activeLines\@activeLines
}

% Print each active line identifier, associated with its
% corresponding pos field. Typical output:
%   {a ↦ 10, b ↦ 30, c ↦ 50, d ↦ 70,}
\newcommand*\@printState{%
Current state: $\{ \foreach\i in \@activeLines {% \i \mapsto \@getLinePos\i, } \}$ \par
}

\begin{document}

\foreach \x/\xvalue in {a/10, b/30, c/50, d/70} {
\ExpandNextTwo\@defineLine{\x}{\xvalue}
\@printState
}
\foreach \x in {a, c} {
\ExpandNext\@removeFromActiveLines{\x}
\@printState
}

\end{document}


## Explanation

The first foreach-loop cycles over a list of pairs, building up a function from identifiers (e.g. a,b,etc.) to numbers. The values of this function are stored in a series of macros (e.g. \wickerson@a@pos stores the value of the function for identifier a), and the domain of this function is the comma-separated list \@activeLines. Initially \@activeLines is empty, and by the end it is a,b,c,d.

I print my function after each iteration of the loop. By the end I expect to print

{a↦10, b↦30, c↦50, d↦70}

but instead it prints

{a↦70, b↦70, c↦70, d↦70}

I suspect the problem is when I add a mapping to my function, I'm not expanding the value enough, and so it changes when I add another mapping. I thought using ExpandNextTwo from etextools would expand everything nicely, but it doesn't seem to have helped. Any ideas?

The second foreach-loop tries to remove some of the mappings from my function, with the help of the \@removeelement command. Unfortunately, it doesn't work. The mapping is only removed within the scope of the current loop iteration, and by the next iteration, the mapping has returned. I suspect the problem is that the \@removeelement is not redefining \@activeLines globally, but I don't know how to fix this. Any ideas? (I hope I don't need to switch to the expl3 syntax to achieve this, because that would be require quite a drastic change to my code!)

## Desired output

-

The following two macros need fixing:

\newcommand*\@defineLine[2]{%
\typeout{Defining wickerson@#1@pos = #2}
\expandafter\xdef\csname wickerson@##1@pos\endcsname{#2}
}


That will define for \@defineLine{a}{10} the macro \wickerson@#1@pos instead of \wickerson@a@pos. Fix:

\newcommand*\@defineLine[2]{%
\typeout{Defining wickerson@#1@pos = #2}
\expandafter\xdef\csname wickerson@#1@pos\endcsname{#2}
}


The next macro uses it:

% Project the pos-field from the line with the given
% identifier. For instance, if \wickerson@foo@pos=35 then
%   \@getLinePos{foo}
% will give 35.
\xdef\@getLinePos#1{\csname wickerson@#1@pos\endcsname}


Since \xdef expands, \csname is executed to \wickerson@#1@pos with #1 part of the macro name, not an argument. Fix:

\gdef\@getLinePos#1{\csname wickerson@#1@pos\endcsname}


## Getting rid of the last comma

A feature of \foreach can be used to get rid of the latest comma in the output:

\newcommand*\@printState{%
Current state: $\{ \foreach\i [count=\ii] in \@activeLines {% \ifnum\ii>1 ,\fi \i \mapsto \@getLinePos\i } \}$ \par
}


## Removing

The question uses the following definition for removing elements:

\newcommand*\@removeFromActiveLines[1]{%                                 %
\@expandtwoargs\@removeelement{#1}\@activeLines\@activeLines           %
}                                                                        %


Indeed, the effect of LaTeX's \@removeelement is limited to the current group. If you want to make the changes of \@activeLines global, then \global\let helps:

\newcommand*\@removeFromActiveLines[1]{%                                 %
\@expandtwoargs\@removeelement{#1}\@activeLines\@activeLines           %
\global\let\@activeLines=\@activeLines
}                                                                        %

-
Thank you so much Heiko. Your explanations are extremely clear to me. – John Wickerson May 16 '13 at 19:37
So I wasn't actually defining \wickerson@a@pos, \wickerson@b@pos, etc, but instead defining \wickerson@#1@pos over and over again. Heh. – John Wickerson May 16 '13 at 19:53
Transparent PNG background... I like it. – Werner May 16 '13 at 20:19
@Werner Thanks. The transparent background is the result of ImageMagick's convert from PDF to PNG. It uses Ghostscript with device pngalpha. – Heiko Oberdiek May 16 '13 at 20:26
@JohnWickerson Answer updated (using \global\let\@activeLines=\@activeLines). – Heiko Oberdiek May 17 '13 at 12:46

I believe that with expl3 it's more straightforward, since it doesn't rely on knowing what's needed to expand and when.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_wickerson_list_seq

\NewDocumentCommand{\printState}{>{\SplitList{,}}m}
{
\seq_clear:N \l_wickerson_list_seq
\ProcessList{#1}{\splitatslash}
Current~state\tl_to_str:n { : } ~ %
$\seq_use:Nnnn \l_wickerson_list_seq { , } { , } { , }$
}
\NewDocumentCommand{\splitatslash}{>{\SplitArgument{1}{/}}m}
{
\wickerson_split_element:nn #1
}
\cs_new_protected:Npn \wickerson_split_element:nn #1 #2
{
\seq_put_right:Nn \l_wickerson_list_seq { #1 \mapsto #2 }
}
\ExplSyntaxOff

\begin{document}
\printState{a/10}

\printState{a/10, b/30}

\printState{a/10, b/30, c/50}

\printState{a/10, b/30, c/50, d/70}
\end{document}


A different implementation that makes it possible to remove states; I've used both a sequence for the "before slash" parts and a property list that holds the vaule ("after slash").

The command \defineStates reinitializes the variables, while \addStates put new states in the variables; similarly, \removeStates removes states. Finally, \printStates just gives a visual representation of the states.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

%%% variables
\seq_new:N \g_wickerson_list_seq
\prop_new:N \g_wickerson_states_prop

%%% document commands
\NewDocumentCommand{\defineStates}{m}
{
\wickerson_definestates:n { #1 }
}
{
\wickerson_addstates:n { #1 }
}
\NewDocumentCommand{\removeStates}{m}
{
\clist_map_inline:nn { #1 }
{
\seq_gremove_all:Nn \g_wickerson_list_seq { ##1 }
% The following also removes the state from the property list
% You can choose whether keep it or comment it out
\prop_gremove:Nn \g_wickerson_states_prop { ##1 }
}
}
\NewDocumentCommand{\printStates}{}
{
Current~state\tl_to_str:n { : } ~ %
$\seq_map_inline:Nn \g_wickerson_list_seq { ##1 \mapsto \prop_get:Nn \g_wickerson_states_prop { ##1 }, }$
}

%%% internal commands
{
\clist_map_inline:nn { #1 }
{
\wickerson_split_element:ww ##1 \q_stop
}
}
\cs_new_protected:Npn \wickerson_definestates:n #1
{
\seq_gclear:N \g_wickerson_list_seq
\prop_gclear:N \g_wickerson_states_prop
\wickerson_addstates:n { #1 }
}
\cs_new_protected:Npn \wickerson_split_element:ww #1 / #2 \q_stop
{
\seq_gput_right:Nn \g_wickerson_list_seq { #1 }
\prop_gput:Nnn \g_wickerson_states_prop { #1 } { #2}
}

\ExplSyntaxOff

\begin{document}
%% Initialize
\defineStates{a/10,b/30}\printStates

%% Add new states


I think it would be more natural to use a delimited function at the expl3 level, not xparse. Namely, \cs_new_protected:Npn \wickerson_split_element:ww #1 / #2 \q_stop {...}. – Bruno Le Floch May 17 '13 at 12:48
@BrunoLeFloch I agree, but I wanted to use less expl3 as possible. I'll provide a "full" expl3 version later. – egreg May 17 '13 at 12:53
I'm trying to learn more about this expl3 stuff, but so far have only found a short introduction (here‌​). Where can I learn about things like what {>{\SplitList{,}}m} means? – John Wickerson May 18 '13 at 15:46
@JohnWickerson That's in the documentation of xparse: texdoc xparse – egreg May 18 '13 at 15:47
Note that as of September 2014, \prop_get:Nn has been renamed to \prop_item:Nn` – egreg Sep 17 '14 at 17:58