`foreach` 循环中的动态宏定义

`foreach` 循环中的动态宏定义

我创建了一个命令来动态定义矢量宏:

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

效果和我预期的一样。但随后我尝试使用包\foreach中定义的命令修改此命令以接受逗号分隔的符号列表pgffor

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

该命令编译时没有错误,但无法定义正确的宏。经过一番谷歌搜索后,我遇到了一些与我的问题有些类似的问题,这些问题表明问题可能与范围有关,所以我尝试了以下两种方法:

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

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

第一个产生的结果与我最初的解决方案相同,而第二个产生错误Argument of \reserved@a has an extra }Paragraph ended before \reserved@a was complete。任何帮助都值得赞赏。

更新:这是一份最基本的文档:

\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}

这会undefined control sequence error在调用时引发\v并编译为空白文档。

答案1

你基本上是在做

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

这当然会引发错误,因为\name通常是未定义的,而且即使定义,也很可能不是“v”。如果你这样做

\makevec{v,w}

您需要定义\v\w扩展为\name

您需要\xdef,但\textbf应该用 进行保护\noexpand,为了安全起见,只展开一次\name

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

但请注意,以这种方式重新定义命令非常危险。之后,\makevec{v}您将无法在参考书目中添加名为 Čech 的作者,因为您已将“ \vto”重新定义为与预期不同的意思。

相关内容