2

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
  • 1
    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
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.