在 for 循环内定义新命令

在 for 循环内定义新命令

我想通过在 for 循环中使用计数器来定义一些相关命令。

例如我想定义 26 个命令,如下所示:

\newcommand{\calA}{{\cal A}}
\newcommand{\calB}{{\cal B}}
...

我已经搜索了一段时间(实际上已经学到了很多),但仍然没有找到答案。这是我最近的尝试(它使用了包forloop):

\newcounter{ct}
\forLoop{1}{26}{ct}{
    \expandafter\newcommand\expandafter%
    {\csname cal\Alph{ct}\endcsname}%
    {{\cal \Alph{ct}}}
}

所有 26 个命令都已创建,但都定义为{\cal Z}。我猜{\cal \Alph{ct}}只有在循环完成后才会展开。

我如何才能实现我的目标?它是如何运作的?

答案1

你没有说你的循环宏来自哪个包。这只是使用\loopLaTeX 中的(最初来自纯 TeX)

> \calA=\long macro:
->\mathcal {A}.
l.18 \show\calA

? 
> \calZ=\long macro:
->\mathcal {Z}.
l.20 \show\calZ

产自

\documentclass{article}

\makeatletter

\def\foo#1{%
\expandafter\newcommand\csname cal#1\endcsname{\mathcal{#1}}}

\count@=0
\loop
\advance\count@ 1
\edef\y{\@Alph\count@}%
\expandafter\foo\y
\ifnum\count@<26
\repeat



\show\calA

\show\calZ

\stop

答案2

这些类型的构造最好通过 LaTeX2e、内核命令和构造、硬核 TeX 或使用诸如 etoolbox(或 LaTeX3)之类的包来完成。

在这种情况下,我更喜欢以下方法。

首先定义一个命令,该命令将定义其他命令。我们称之为\commandfactory

  \def\commandfactory#1{%
     \expandafter\def\csname cal#1\endcsname{\mathcal{#1}}}

我们需要一个新的计数器来跟踪迭代并为命令提供“字母”。

   \newcounter{ctr}

在这种情况下,最简单的循环结构将是 Knuth 的\loop..\repeat构造。最后是 MWE。

\documentclass{article}
\makeatletter

\def\commandfactory#1{%
   \expandafter\def\csname cal#1\endcsname{\mathcal{#1}}}

\newcounter{ctr}
\loop
  \stepcounter{ctr}
  \edef\X{\@Alph\c@ctr}%
  \expandafter\commandfactory\X
\ifnum\thectr<26
\repeat

\begin{document}
\setcounter{ctr}{0}
\loop
  \stepcounter{ctr}
   $\@nameuse{cal\@Alph\c@ctr}$, 
\ifnum\thectr<26
\repeat

\end{document}

我通常更喜欢这种方法的原因是它使用在软件包和内核中非常常见的构造(即,您使用通用范例)并且易于查找信息。人们有时会反对混合 TeX/LaTeX 命令,但是嘿,重要的是您的代码可以正常工作。

答案3

啊哈,没有与 TikZ 相关的答案!不可接受....

您还可以使用pgffor外部使用 PGF/TikZ 包的模块。这也使您有机会直接迭代字母。我曾使用过ensuremath直接使用它,但您可以删除它和相应的\noexpand。请参阅何时不应使用 \ensuremath 作为数学宏?了解更多信息。

\documentclass{article}
\usepackage{pgffor}
\foreach \x in {A,...,Z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\noexpand\mathcal{\x}}}
}
\begin{document}
\calP\calG\calF / \calT\calI\calK\calZ
\end{document}

enter image description here

我担心最后我会因此而纹身。

编辑由 Andrew Stacey 提供

具有更精美的书法和正确大写字母的 XeLaTeX 解决方案

\documentclass{article}
\usepackage{unicode-math}
\setmathfont{xits-math.otf}
\usepackage{pgffor}
\AtBeginDocument{
\foreach \x in {A,...,Z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\csname mscr\x\endcsname}}
}
\foreach \x in {a,...,z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\csname mscr\x\endcsname}}
}
}
\begin{document}
\calP\calG\calF / \calT\cali\calK\calZ
\end{document}

enter image description here

答案4

forloop 包定义了两个命令 \forloop(首选用法)和 \forLoop(已弃用)。

forloop 的定义是

\forloop[⟨step⟩]{⟨counter⟩}{⟨initial value⟩}{⟨condition⟩}{⟨code⟩}

但这不是这里的问题。你的问题来自 的扩展\Alph{ct}。很多答案都很好,这里我使用了类似 percusse 的东西,你可以看到你可以用\forloop代替\foreach

但我不同意:

它们更易读,并且 forloop 包似乎被广泛

因为如果你比较 percusse 的答案和我的答案,我不知道哪个更易读。现在在这种情况下,我认为最好像 David 那样做,避免\forloop

\documentclass[]{article}
\usepackage[utf8]{inputenc}
\usepackage{forloop}
\makeatletter 
\let\FOR\@for
\let\NAMEUSE\@nameuse   
\makeatother

\begin{document}

\newcounter{ct} 
\forloop{ct}{1}{\value{ct} < 27}{%
\expandafter\xdef\csname cal\Alph{ct}\endcsname{%
\noexpand\ensuremath{\noexpand\mathcal{\Alph{ct}}}}
}

\FOR\letter:={A,L,T,E,R,M,U,N,D,U,S}\do{% 
\NAMEUSE{cal\letter}}

\end{document} 

酒吧!

enter image description here

相关内容