局部变量扩展到多个标签点的宏

局部变量扩展到多个标签点的宏

我终于从egreg 的回答在我之前的问题中(定义一个具有三个可选参数的宏,形式为 \newmacro{a}{b}[c]{d}[e][f] 和 \newmacro{a}{b}[c]{d}*[f])虽然我最初的答案是关于制作更短的代码,但我最终得到了一个大约 190 行的包。如果您好奇,您可以查看它在 github 上并且也有记录这里

宏工作正常,除了我想要实现的显示模式:我希望宏在表格环境中工作,例如arrayalign:这将允许排版几个函数定义保留一些对齐。

然而我发现了一个问题。

我们来看看下面的代码:

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

得到这样的结果:10 1 20 1 30 1

改变定义\mymacroi

\newcommand\mymacroi{\tempi , \tempii}

新的结果是:1 10,1b // 20,2 30,3

在第一个代码中,制表符 之后的更改\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

定义\tempi2\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}

相关内容