我终于从egreg 的回答在我之前的问题中(定义一个具有三个可选参数的宏,形式为 \newmacro{a}{b}[c]{d}[e][f] 和 \newmacro{a}{b}[c]{d}*[f])虽然我最初的答案是关于制作更短的代码,但我最终得到了一个大约 190 行的包。如果您好奇,您可以查看它在 github 上并且也有记录这里。
宏工作正常,除了我想要实现的显示模式:我希望宏在表格环境中工作,例如array
或align
:这将允许排版几个函数定义保留一些对齐。
然而我发现了一个问题。
我们来看看下面的代码:
\documentclass{article}
\def\tempi{0}
\def\tempii{1}
\newcommand\mymacro[1]{
\let\tempiii\tempi
\def\tempi{#1\tempiii}
\def\tempii{#1}
\mymacroi
}
\newcommand\mymacroi{\tempi & \tempii}
\begin{document}
\[
\begin{array}{cccc}
a & \mymacro{1} & b \\
\mymacro{2} & \mymacro{3}
\end{array}
\]
\end{document}
得到这样的结果:
改变定义\mymacroi
\newcommand\mymacroi{\tempi , \tempii}
新的结果是:
在第一个代码中,制表符 之后的更改\tempii
未保留&
。第二个显示了 的修改\tempii
(但没有对齐)。
使用\begingroup
于\mymacro
:
\newcommand\mymacro[1]{
\begingroup
\let\tempiii\tempi
\def\tempi{#1\tempiii}
\def\tempii{#1}
\mymacroi
\endgroup
}
并且,使用原始版本\mymacroi
(带有的版本&
)时,我收到错误。
因此,问题确实是尝试&
从宏中使用,同时保留宏的本地更改,同时将这些更改扩展到多个单元格。
(在此 MWE 中存在循环引用,但在我的原始宏中并不存在。)
更新:
我最初的例子太简单,无法显示一些期望的结果,并且考虑到我的宏应该在表格环境和非表格环境中工作,我将通过重新定义来模仿这个 MWE \mymacroi
。我只复制文档环境。
\begin{document}
\[
\begin{array}{cccccc}
a & \mymacro{7} & b & \tempi & \tempii \\
\mymacro{2} & \mymacro{3} & \tempi & \tempii
\end{array}
\]
\renewcommand\mymacroi{%
\edef\tmp{\tempi,\tempii}%
\tmp
}
\par Test 1 \(\mymacro{5};\tempi,\tempii\)
\par Test 2 \(\mymacro{4};\tempi,\tempii\)
\end{document}
预期结果是
:
答案1
表格中的每个单元格都构成一个组。因此,您使用
\mymacro{2}
扩展为
\let\tempiii\tempi
\def\tempi{2\tempiii}
\def\tempii{2}
\mymacroi
定义\tempi
为2\tempiii
(相当于2\tempi
)并\tempii
定义为2
。然后调用\mymacroi
扩展为
\tempi & \tempii
\tempi
和都已\tempii
定义,但更新的定义是在(第一个)组/单元格内完成的。因此,第二个包含 的单元格\tempii
将恢复为原始定义(如序言中所做的那样\def\tempii{1}
)。每次使用 时都会发生这种情况\mymacro
,似乎您希望让本地重新定义跨越这些单元格。为此,请使用g
全局重新def
初始化(或可能是x
扩展的全局重新def
初始化):
\documentclass{article}
\newcommand\tempi{0}
\newcommand\tempii{1}
\makeatletter
\newcommand{\storetemps}{%
\global\let\store@tempi\tempi%
\global\let\store@tempii\tempii}
\newcommand{\restoretemps}{%
\global\let\tempi\store@tempi%
\global\let\tempii\store@tempii}
\newcommand\mymacro[1]{
\storetemps%
\xdef\tempi{#1\tempi}%
\xdef\tempii{#1}%
\mymacroi%
}
\newcommand\mymacroi{%
\ifnum\pdfstrcmp{\@currenvir}{array}=0
\let\select@type\@firstoftwo%
\else
\let\select@type\@secondoftwo%
\fi
\select@type{\tempi & \tempii}{\tempi, \tempii}%
\restoretemps%
}
\makeatother
\begin{document}
$
\begin{array}{cccccc}
a & \mymacro{7} & b & \tempi & \tempii \\
\mymacro{2} & \mymacro{3} & \tempi & \tempii
\end{array}
$
Test 1 \(\mymacro{5};\tempi,\tempii\) \par
Test 2 \(\mymacro{4};\tempi,\tempii\)
\end{document}
上述版本的\mymacroi
条件取决于您是否处于array
环境中,允许您在环境中按原样使用它。
答案2
您似乎想要扩展当前组中的宏,但在不同的组中对它们进行评估,因此使用\edef
(或者如果有任何用户提供的 LaTeX 输入,\protected@edef
)将扩展和排版分开。此外,您还缺少几%
行结尾。
\documentclass{article}
\def\tempi{0}
\def\tempii{1}
\newcommand\mymacro[1]{%
\let\tempiii\tempi
\def\tempi{#1\tempiii}%
\def\tempii{#1}%
\mymacroi
}
\newcommand\mymacroi{%
\edef\tmp{\tempi&\tempii}%
\tmp}
\begin{document}
\[
\begin{array}{cccc}
a & \mymacro{1} & b \\
\mymacro{2} & \mymacro{3}
\end{array}
\]
\end{document}