# dynamic macro definition problem

It is likely that the answer to the problem is buried on this site somewhere -- it is my limited understanding of macro expansion which seems to defy my search foo...

I am trying to define macros which I can use like this:

\begin{document}

...
% later, in some table

Which should result in output like this

\begin{itemize}
\end{itemize}

\begin{itemize}
\end{itemize}

I have the following macro set in place:

\expandafter\def\csname AimTask#1\endcsname{ \item #2}
}

\expandafter\def\csname AimTask#1\endcsname{ \tmp \item #2}
}

I am doing something wrong with the 'tmp' definition/usage, as I see the following errors:

?
! Missing control sequence inserted.
<inserted text>
\inaccessible

?

and the result contains only the last specified task. I would appreciate any insight in what is going on with \tmp.

Many thanks, Andre.

• Pretty sure your problem is here \expandafter\def\tmp. The \expandafter skips \def and tries to expand \tmp which hasn't been defined. I get an undefined control sequence at that point when copy/pasting your code into a document. – Scott H. Jul 13 '12 at 1:35

The following does what you're after (but requires e-TeX; it can be modified to work without as well):

\documentclass{article}

\makeatletter
\expandafter\def\csname AimTask#1\endcsname{ \item #2}%
}
% Check for repeated entries (AM):
\@expandtwoargs\in@
{\detokenize{\item #2}}
\ifin@\else
\fi
\else
\fi%
}
\makeatother
\begin{document}

Explicit definition:

\begin{itemize}
\end{itemize}

\begin{itemize}
\end{itemize}

\ldots

Macro definition:

\end{document}

In order to append things to an existing macro, it's sufficient to use \g@addto@macro{<macro>}{<stuff>}. Also, I've updated \AimTaskAdd to check for the existence of AimTask#1 and create it if it doesn't exist. That allows you to do

without being concerned that AimTask1 exists already (I've also used this in my example as an illustration).

• \g@addto@macro -- cool! Excellent, that is exactly what I was looking for, really :-) – Andre Merzky Jul 13 '12 at 8:21

An implementation with expl3 facilities.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\AimTaskDef}{ m m }{ \andre_task_def:nn { #1 } { #2 } }
{
\begin{itemize} \prop_get:Nn \g_andre_tasks_prop { #1 } \end{itemize}
}

\msg_new:nnn { andre } { task-exist }
{
}
\msg_new:nnn { andre } { task-not-exist }
{
}

\cs_new_protected:Npn \andre_task_def:nn #1 #2
{
\prop_if_in:NnT \g_andre_tasks_prop { #1 }
{
\msg_warning:nnx { andre } { task-exist } { #1 }
}
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
{
\prop_if_in:NnTF \g_andre_tasks_prop { #1 }
{
\prop_gput:Nnx \g_andre_tasks_prop { #1 }
{
\prop_get:Nn \g_andre_tasks_prop { #1 } \exp_not:n { \item #2 }
}
}
{
\msg_warning:nnx { andre } { task-not-exist } { #1 }
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
}
\ExplSyntaxOff

\begin{document}

\end{document}

The macros warn if \AimTaskDef is used with an already defined task and, in this case, overwrite it (this could be changed); they also warn if \AimTaskAdd is used on a not yet defined task (and define it).

A possibly more efficient version (thanks to Bruno Le Floch):

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\AimTaskDef}{ m m }{ \andre_task_def:nn { #1 } { #2 } }
{
\begin{itemize} \prop_get:Nn \g_andre_tasks_prop { #1 } \end{itemize}
}

% Variables
\tl_new:N \l_andre_temp_tl

% Messages
\msg_new:nnn { andre } { task-exists }
{
}
\msg_new:nnn { andre } { task-exists-not }
{
}

% Functions
\cs_new_protected:Npn \andre_task_def:nn #1 #2
{
\prop_if_in:NnT \g_andre_tasks_prop { #1 }
{
\msg_warning:nnx { andre } { task-exists } { #1 }
}
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
{
\prop_get:NnNTF \g_andre_tasks_prop { #1 } \l_andre_temp_tl
{
\tl_put_right:Nn \l_andre_temp_tl { \item #2 }
\prop_gput:NnV \g_andre_tasks_prop { #1 } \l_tmpa_tl
}
{
\msg_warning:nnx { andre } { task-exists-not } { #1 }
\prop_gput:Nnn \g_andre_tasks_prop { #1 } { \item #2 }
}
}
\ExplSyntaxOff

\begin{document}