伪代码

伪代码

我可以使用pgffor循环宏(控制序列)吗?例如\foreach \macro in {\lions,\tigers,\bears}

如果你还没搞清楚,我喜欢模块化

假设我有三个命令需要修补:

  1. \a1
  2. \a2
  3. \a3

伪代码

此代码是为了实现我想要的功能而尝试的。为了好玩并测试我的理解,我曾经\csname创建名称中包含数字的宏。

\documentclass{article}
\usepackage{tikz}
\usepackage{regexpatch}
\expandafter\newcommand\csname a1\endcsname[1]{}
\expandafter\newcommand\csname a2\endcsname[1]{}
\expandafter\newcommand\csname a3\endcsname[1]{}

\foreach \macro in {\csname a1\endcsname,\csname a2\endcsname,\csname a3\endcsname} {%
  \expandafter\xapptocmd{\macro}{\unexpanded{#1}, oh my!}{}{}% Apply patches to all macros in list
}%
\begin{document}
\csname a1\endcsname{Lions}

\csname a2\endcsname{tigers}

\csname a3\endcsname{and bears}
\end{document}

预期页面输出

Lions, oh my!

tigers, oh my!

and bears, on my!

替代半工作示例,无\csname

\documentclass{article}
\usepackage{tikz}
\usepackage{regexpatch}
\newcommand\lions[1]{}
\newcommand\tigers[1]{}
\newcommand\bears[1]{}

%\foreach \macro in {\lions,\tigers,\bears} {% Loop up the following junk
  \xapptocmd{\lions}{\unexpanded{#1}, oh my!}{}{}% inefficient use of my time
  \xapptocmd{\tigers}{\unexpanded{#1}, oh my!}{}{}% inefficient use of my time
  \xapptocmd{\bears}{\unexpanded{#1}, oh my!}{}{}% inefficient use of my time
%}%
\begin{document}
\lions{Lions}

\tigers{tigers}

\bears{and bears}
\end{document}

输出

在此处输入图片描述

答案1

除了使用expl3循环(如\clist_map_inline:nn)之外,您还可以使用提供的etoolbox

\documentclass{scrartcl}

\usepackage{etoolbox,regexpatch}

\csdef{a1}#1{}
\csdef{a2}#1{}
\csdef{a3}#1{}

\begin{document}

\renewcommand*\do[1]{\expandafter\xapptocmd\csname#1\endcsname{##1, oh my!}{}{\typeout{Misreable filure}}}
\docsvlist{a1,a2,a3}

\csuse{a1}{Lions}\par
\csuse{a2}{tigers}\par
\csuse{a3}{and bears}

\end{document}

我使用了\csdef\csuse只是为了向他们展示,您可以像往常一样使用\expandafter\newcommand\csname .. \endcsname\csname .. \endcsname

正如 egreg 所说,总是重复出现的问题\foreach是一切都在组内。我从来没有想过,但我不知道为什么不定义类似的东西\foreach \foo in { a, b } { <code> }\let\save\foo \def\foo{a} <code> \def\foo{b} <code> \let\foo\save这样可以解决很多问题。无论如何,如果你想为自己定义一个完整的宏来自动化你可以做的一切,例如,这两个选项:

\usepackage{etoolbox}
\newcommand\doforeach[2]{\renewcommand\do[1]{#2}\docsvlist{#1}}

或者

\usepackage{expl3}
\ExplSyntaxOn
\NewDocumentCommand \doforeach { +m +m } { \clist_map_inline:nn { #1 } { #2 } }
\ExplSyntaxOff

然后你就可以轻松使用

\doforeach{a1,a2,a3}{\expandafter\xapptocmd\csname#1\endcsname{##1, oh my!}{}{\typeout{Misreable filure}}}

而且您不需要输入困难的东西。

答案2

常见的问题:\foreach在组中完成其工作,因此一旦组结束,补丁就会失效。但是,您正在尝试修补\macro,这会扩展到\csname a1\endcsname等等,因此尝试显然会失败。

定义\temp为与“双重扩展”相同\macro;修补它;全局重新定义该\csname宏为修补版本。

\documentclass{article}
\usepackage{tikz}
\usepackage{regexpatch}
\expandafter\newcommand\csname a1\endcsname[1]{#1}
\expandafter\newcommand\csname a2\endcsname[1]{#1}
\expandafter\newcommand\csname a3\endcsname[1]{#1}

\foreach \macro in {\csname a1\endcsname,\csname a2\endcsname,\csname a3\endcsname}
  {%
   \expandafter\expandafter\expandafter\let\expandafter\expandafter\expandafter\temp\macro
   \xapptocmd\temp{, oh my!}{}{}%
   \global\expandafter\expandafter\expandafter\let\macro\temp
  }

\begin{document}
\csname a1\endcsname{Lions}

\csname a2\endcsname{tigers}

\csname a3\endcsname{and bears}
\end{document}

在此处输入图片描述

如果您希望在补丁中使用参数说明符,可以这样做。请注意, 的倍数#,因为我们在 的参数中\foreach

\documentclass{article}
\usepackage{tikz}
\usepackage{regexpatch}
\expandafter\newcommand\csname a1\endcsname[1]{}
\expandafter\newcommand\csname a2\endcsname[1]{}
\expandafter\newcommand\csname a3\endcsname[1]{}

\foreach \macro in {\csname a1\endcsname,\csname a2\endcsname,\csname a3\endcsname}
  {%
   \expandafter\expandafter\expandafter\let\expandafter\expandafter\expandafter\temp\macro
   \xapptocmd\temp{##1, oh my!}{}{}%
   \global\expandafter\expandafter\expandafter\let\macro\temp
  }

\begin{document}
\csname a1\endcsname{Lions}

\csname a2\endcsname{tigers}

\csname a3\endcsname{and bears}
\end{document}

答案3

我宁愿使用\seq列表并在里面扩展它。

\documentclass{article}
\usepackage{tikz}
\usepackage{regexpatch}
\expandafter\newcommand\csname macro1\endcsname[1]{}
\expandafter\newcommand\csname macro2\endcsname[1]{}
\expandafter\newcommand\csname macro3\endcsname[1]{}



\begin{document}
Before patching:

\csname macro1\endcsname{Lions}
\csname macro2\endcsname{Tigers}
\csname macro3\endcsname{and Bears}


\ExplSyntaxOn
\seq_set_from_clist:Nn \l_tmpa_seq {macro1,macro2,macro3}
\seq_map_inline:Nn \l_tmpa_seq  {%
 \exp_after:wN \xapptocmd\cs:w #1\cs_end:{##1,~oh~my!}{\typeout{Success!}}{}
}
\ExplSyntaxOff

After patching:

\csname macro1\endcsname{Lions}

\csname macro2\endcsname{Tigers}

\csname macro3\endcsname{and Bears}


\end{document}

其他版本,使用正确的参数##1和以及带有的旁路\global\csletcs,因为\foreach仅运行它的代码组。

\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{regexpatch}
\expandafter\newcommand\csname a1\endcsname[1]{}
\expandafter\newcommand\csname a2\endcsname[1]{}
\expandafter\newcommand\csname a3\endcsname[1]{}

\begin{document}

\foreach \macro in {a1,a2,a3} {%
  \let\santaslittlehelper\macro
  \expandafter\xapptocmd\csname \santaslittlehelper\endcsname{##1, oh my!}{}{\typeout{Miserable failure}}% Apply patches to all macros in list
  \global\csletcs{\macro}{\santaslittlehelper}
}
\csname a1\endcsname{Lions}

\csname a2\endcsname{tigers}

\csname a3\endcsname{and bears}

\end{document}

在此处输入图片描述

相关内容