# Dynamic macro definition in a foreach loop

I created a command to dynamically define vector macros:

\newcommand{\makevec}[1]{\expandafter\def\csname #1\endcsname{\vec{#1}}}


which works as I expected. But then I tried to modify this command to accept a comma separated list of symbols using the \foreach command defined in the pgffor package:

\newcommand{\makevec}[1]{
\foreach \name in {#1} {
\expandafter\def\csname \name\endcsname{\vec{\name}}
}
}


The command compiles without errors, but simply fails to define the correct macros. After a bit of Googling I ran across some questions somewhat similar to mine that suggested the issue may have to do with the scope, so I tried both:

\newcommand{\makevec}[1]{
\foreach \name in {#1} {
\global\expandafter\def\csname \name\endcsname{\vec{\name}}
}
}


and

\newcommand{\makevec}[1]{
\foreach \name in {#1} {
\expandafter\xdef\csname \name\endcsname{\vec{\name}}
}
}


The first of these yields the same results as my initial solution, while the second produces the errors Argument of \reserved@a has an extra } and Paragraph ended before \reserved@a was complete. Any help is appreciated.

UPDATE: Here's a minimal document:

\documentclass{article}

\usepackage{pgffor}

\newcommand{\makevec}[1]{
\foreach \name in {#1} {
\global\expandafter\def\csname \name\endcsname{\textbf{\name}}
}
}

\makevec{v}

\begin{document}

$\v$

\end{document}


This raises an undefined control sequence error at the invocation of \v and compiles to a blank document.

• Try with \noexpand\vec. – user4686 Apr 26 '18 at 18:55
• @DavidCarlisle I've added a minimal complete document to demonstrate the error. – Kwarrtz Apr 26 '18 at 20:37
• Don't redefine \v or other one letter commands for accents; you'll soon regret having done it. – egreg Apr 26 '18 at 20:38
• @egreg I don't use the accents on a regular basis and the entire point of the \makevec command is so I can redefine the commands on a document by document basis, so that if I know I'm going to need a certain accent in a document I can simply not redefine it. – Kwarrtz Apr 26 '18 at 20:52

You're basically doing

\gdef\v{\textbf{\name}}


which of course will raise an error because \name is generally undefined and, even if it were, it would most likely not be “v”. If you do

\makevec{v,w}


you'd define both \v and \w to expand to \name.

You need \xdef, but \textbf should be protected with \noexpand and, for safety, only expand once \name:

\newcommand{\makevec}[1]{%
\foreach \name in {#1} {%
\expandafter\xdef\csname\name\endcsname{\noexpand\textbf{\unexpanded\expandafter{\name}}}%
}%
}


Beware, though, that redefining commands this way is quite dangerous. After \makevec{v} you'll not be able to have an author named Čech in your bibliography, because you have redefined \v to means something else than expected.