# Ignore expansion in edef

I would like to populate a tabular environment programmatically using an edef.

For simplicity, I brought a simple example:

\let\\=\relax
\let\hline=\relax
\edef\mmm{\hline A & B\\}
\edef\mmm{\mmm\hline C & D\\}
\edef\mmm{\mmm\hline 1 & 2\\\hline}
\begin{tabular}{|c|c|}\mmm\end{tabular}


The result:

Expected:

In this example, how can I suppress expansion of \hline once it being used in a edef? I used \let\hline=\relax but it does not generate the expected result.

• Yep, so did I and no juice – that's why I deleted it :) Just the first thing that popped into my head. – Sean Allred Nov 1 '15 at 14:48
• Not getting a line ought to be the "expected result" if you redefine \hline to be \relax ! – David Carlisle Nov 1 '15 at 14:49
• @DavidCarlisle You're absolutely right. But I'm pretty new in TeX. – frogatto Nov 1 '15 at 14:59

If you use \edef you need to reset \\ and \hline afterwards, but it is typically not safe to use \edef with LaTeX input. The second form doesn't repeatedly expand the tokens. Please always make examples complete documents, as below.

\documentclass{article}

\begin{document}
{\let\\=\relax
\let\hline=\relax
\xdef\mmm{\hline A & B\\}
\xdef\mmm{\mmm\hline C & D\\}
\xdef\mmm{\mmm\hline 1 & 2\\\hline}
}
\begin{tabular}{|c|c|}\mmm\end{tabular}

\makeatletter
\def\mmm{\hline A & B\\}
\makeatother
\begin{tabular}{|c|c|}\mmm\end{tabular}

\end{document}


There are several ways for appending tokens to the replacement text of a macro. The simplest one is with etoolbox:

\usepackage{etoolbox}

[...]

\def\mmm{\hline A & B\\}
\appto\mmm{\hline C & D\\}
\appto\mmm{\hline 1 & 2\\\hline}
\begin{tabular}{|c|c|}\mmm\end{tabular}


Without packages,

\def\appto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}


and the code above will do the same.

If you want to use \edef,

\def\mmm{\hline A & B\\}
\edef\mmm{\unexpanded\expandafter{\mmm}\unexpanded{\hline C & D\\}}
\edef\mmm{\unexpanded\expandafter{\mmm}\unexpanded{\hline 1 & 2\\\hline}}


A better interface with expl3. When you want to define a new variable or reinitialize it, use \apptovar*, otherwise \apptovar. You can define as many variables as you want and they'll obey the normal scoping rules.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\apptovar}{smm}
{
\IfBooleanT{#1}
{
\tl_clear_new:c { l_abforce_var_#2_tl }
}
\tl_put_right:cn { l_abforce_var_#2_tl } { #3 }
}
\DeclareExpandableDocumentCommand{\usevar}{m}
{
\tl_use:c { l_abforce_var_#1_tl }
}

\ExplSyntaxOff

\begin{document}

\apptovar*{mmm}{\hline A & B\\}% initialize
\apptovar{mmm}{\hline C & D\\}
\apptovar{mmm}{\hline 1 & 2\\\hline}

\begin{tabular}{|c|c|}\usevar{mmm}\end{tabular}

\end{document}


• I guess this is probably what OP is going after ultimately :) – Sean Allred Nov 1 '15 at 14:45
• Thank you. However, unfortunately I can't mark two answers as accepted. – frogatto Nov 1 '15 at 14:57
• @abforce Unfortunately you accepted the wrong one. ;-) – egreg Nov 1 '15 at 14:58
• @abforce egreg is teasing :) – Sean Allred Nov 1 '15 at 15:00
• @egreg Excuse me! I'd rather prefer reseting \hline than use other approaches. However, I'm so grateful for your answer. – frogatto Nov 1 '15 at 15:03