# Why did my \xdef fail?

Building upon what I was doing in this thread, why didn't my \xdef work?

The Exercise Page comes out just fine. Ideally, the Answer Page would look identical, except, of course with the answers there.

But the Answers Page is gobbledygook. And sometimes it compiles and sometimes it doesn't.

The code works perfectly if I comment out the \AnswerList near the bottom. So the problem is related to that.

What gives?

Here's the code.

\documentclass{article}

\usepackage[margin=2cm]{geometry}
\usepackage{ifthen}
\usepackage{pgf}
\usepackage{pgffor}
\usepackage{tikz}

\setlength{\parindent}{0pt}

\pgfmathsetseed{\number\pdfrandomseed}

\newcommand{\InitVariables}
{
\pgfmathsetmacro{\FactorA}{int(random(1,9))}
\pgfmathsetmacro{\FactorB}{int(random(1,9))}
\pgfmathsetmacro{\Product}{int(\FactorA*\FactorB)}
\pgfmathsetmacro{\Structure}{int(random(0,2))}
}

{%
\tikz[baseline=6pt]{\draw (0,0)rectangle(0.9,0.9);}
}

{%
\tikz[baseline=6pt]{\draw (0,0)rectangle(0.9,0.9); \node[center] at (0.45,0.35) {\color{blue}#1};}
}

\newcommand{\OneEquation}
{%
\large
\InitVariables
\ifcase\Structure\relax
\def\Exercise{$$\FactorA \times \FactorB = \AnswerSpace$$}
\def\Answer{$$\FactorA \times \FactorB =\ASF{\Product}$$}
\or
\def\Exercise{$$\FactorA \times \AnswerSpace = \Product$$}
\def\Answer{{$$\FactorA \times \ASF{\FactorB} = \Product$$}}
\or
\def\Exercise{$$\AnswerSpace \times \FactorB = \Product$$}
\def\Answer{$$\ASF{\FactorA} \times \FactorB = \Product$$}
\fi
}

\newcommand{\ExerciseList}[1]
{%
\foreach \x in {1,2,3,...,{#1}}
{%
\OneEquation \Exercise \par \vspace{0.5cm}
}
}

\begin{document}

\section{Exercises}
\ExerciseList{10}

\pagebreak

\end{document}

• Too many reasons. An easy one is that \vspace cannot be used in \xdef, but it's the simplest. – egreg Oct 7 '16 at 22:59
• Ok. How else am I supposed to create vertical space between the lines then? And what were the other problems? I thought my code closely resembled the code from the prior thread (see link in OP). – WeCanLearnAnything Oct 7 '16 at 23:02
\edef\Answer{\noexpand$$\FactorA \times \FactorB =\noexpand\ASF{\Product}\noexpand$$}
\or
\def\Exercise{$$\FactorA \times \AnswerSpace = \Product$$}
\edef\Answer{{\noexpand$$\FactorA \times\noexpand \ASF{\FactorB} = \Product\noexpand$$}}
\or
\def\Exercise{$$\AnswerSpace \times \FactorB = \Product$$}
\edef\Answer{\noexpand$$\noexpand\ASF{\FactorA} \times \FactorB = \Product\noexpand$$}
\fi
}

\makeatletter
\newcommand{\ExerciseList}[1]
{%
\foreach \x in {1,2,3,...,{#1}}
{%
\OneEquation \Exercise \par \vspace{0.5cm}
}
}
\makeatother

\begin{document}

\section{Exercises}
\ExerciseList{10}

\pagebreak

\end{document}


• Whoa. This will take me some time to grock. Will look more tonight and tomorrow. Thanks! – WeCanLearnAnything Oct 7 '16 at 23:18
• How does one learn which commands can and can't go into \xdef and \edef? – WeCanLearnAnything Oct 8 '16 at 17:54
• \edef isn't a documented latex command so formally no commands can. Otherwise, you need to check that it only works by expansion, so basically anything defined by anything more complicated than \newcommand\foo{hello world} will not work in edef. – David Carlisle Oct 8 '16 at 21:57

You're using \ASF in \xdef: this is not going to work, because \tikz is not an expandable command. It's not the only dangerous macro in that context.

Here's a different implementation using expl3. There's some code duplication, but it's possible you want to use different renderings for exercises and solutions, so I defined different functions for doing them.

\documentclass[twocolumn]{article}

\usepackage[margin=2cm]{geometry}
\usepackage{tikz}
\usepackage{xparse}

\setlength{\parindent}{0pt}

\pgfmathsetseed{\number\pdfrandomseed}

\NewDocumentCommand{\InitVariables}{}{%
\pgfmathsetmacro{\FactorA}{int(random(1,9))}%
\pgfmathsetmacro{\FactorB}{int(random(1,9))}%
\pgfmathsetmacro{\Product}{int(\FactorA*\FactorB)}%
\pgfmathsetmacro{\Structure}{int(random(0,2))}%
}

\tikz[baseline=6pt]{\draw (0,0)rectangle(0.9,0.9);}%
}

\tikz[baseline=6pt]{%
\draw (0,0)rectangle(0.9,0.9);
\node[blue] at (0.45,0.35) {#1};
}%
}

\ExplSyntaxOn
\NewDocumentCommand{\OneEquation}{}
{
\InitVariables
\int_case:nn { \Structure }
{
{0}{
}
{1}{
}
{2}{
}
}
}

\seq_new:N \l_wcla_exercise_list_seq

\cs_new_protected:Nn \wcla_make_exercise:nnn
{
\seq_put_right:Nn \l_wcla_exercise_list_seq { $$#1 \times #2 = #3$$ }
}
\cs_generate_variant:Nn \wcla_make_exercise:nnn { xxx }

{
\seq_put_right:Nn \l_wcla_answer_list_seq { $$#1 \times #2 = #3$$ }
}

\NewDocumentCommand{\ExerciseList}{m}
{
\prg_replicate:nn { #1 } { \OneEquation }
\seq_use:Nn \l_wcla_exercise_list_seq { \par \vspace{0.5cm} }
}

{
\seq_use:Nn \l_wcla_answer_list_seq { \par \vspace{0.5cm} }
}
\ExplSyntaxOff

\begin{document}

\section{Exercises}
\ExerciseList{10}

\newpage


I used twocolumn just for getting everything in the same picture, for better checking.
The most notable thing is how \wcla_make_exercise:xxx is defined. First I define \wcla_make_exercise:nnn to add to the sequence containing the list of exercises the formula $$#1\times#2=#3$$. Then the variant is defined that fully expands its three arguments and this is called so the values of \FactorA, \FactorB and \Product are the current ones. There is no problem in fully expanding \ASF here, because \NewDocumentCommand makes it robust.