当动态定义宏时,数学模式下的行为会发生变化

当动态定义宏时,数学模式下的行为会发生变化

为什么我的第三个O比前两个大?

\documentclass{report}
\usepackage[english]{babel}
\usepackage{pgffor}
\usepackage{amsmath}

% defining a plain macro
\def\macro{\text{O}}

% defining it dynamically
\foreach \mname/\cmd in {%
    dynmacro/\text{O},%
    } {%
    \expandafter\xdef\csname\mname\endcsname{\cmd}%
}

\begin{document}

\begin{equation}
    2^{\text{O}} \times % okay
    2^{\macro} \times   % okay
    2^{\dynmacro}       % this one yields a weird result
\end{equation}

\end{document}

enter image description here

我该如何修正我的动态宏?

答案1

如果你问\show\dynmacro\begin{document}你会得到答案

> \dynmacro=macro:
->\protect \unhbox \voidb@x \hbox {O}.

这可不是你想要的,不是吗?问题是\xdef。你甚至很幸运,一些有意义的事情发生了。用 而\textbf不是 ,\text你会得到几个错误。你只需要一步扩展。

\documentclass{report}
\usepackage[english]{babel}
\usepackage{pgffor}
\usepackage{amsmath}

% defining a plain macro
\def\macro{\text{O}}

% defining it dynamically
\foreach \mname/\cmd in {%
    dynmacro/\text{O},%
    } {%
    \expandafter\gdef\csname\mname\expandafter\endcsname\expandafter{\cmd}%
}

\begin{document}

\show\dynmacro

\begin{equation}
    2^{\text{O}} \times % okay
    2^{\macro} \times   % okay
    2^{\dynmacro}       % this one yields a weird result
\end{equation}

\end{document}

控制台现在将报告

> \dynmacro=macro:
->\text {O}.

重要的提示: \text对此来说并不是最好的,但它应该是\mathrm


不同的实现:\dyndef需要三个参数

  1. 输入表单(可选,默认#1=#2
  2. 要执行的定义
  3. 需要定义的事物列表

这里举几个例子。

\documentclass{report}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\dyndef}{O{##1=##2}mm}
 {
  \cs_set:Npn \__iagolito_dyndef_aux:w #1 \q_stop { #2 }
  \clist_map_function:nN { #3 } \iagolito_dyndef:n
 }
\cs_new:Nn \iagolito_dyndef:n { \__iagolito_dyndef_aux:w #1 \q_stop }
\ExplSyntaxOff

% defining it dynamically
\dyndef{\expandafter\newcommand\csname#1\endcsname{#2}}{
    dynmacro=\text{O},
    dynmacroA=\mathbf{0},
}

\dyndef[#1/#2/#3]{\newcommand#1{#2-#3}}{
  \foo/A/B,
}

\begin{document}

\begin{equation}
2^{\text{O}} \times 2^{\dynmacro} + 2^{\dynmacroA}+(\foo)
\end{equation}

\end{document}

enter image description here

如您所见,第一个例子使用默认值dynmacro=\text{O};对于第二个例子,参数的规范是#1/#2/#3;在第一个强制参数中使用相同的占位符。

答案2

主要问题是\xdef完全扩展了它的参数,这会将添加\unhbox\voidb@x到您的\dynmacro。使用etoolbox\expandonce可以\cmd仅扩展一次(并使用\csxdef使其更简单):

\documentclass{report}
\usepackage[english]{babel}
\usepackage{pgffor}
\usepackage{amsmath}
\usepackage{etoolbox}

% defining a plain macro
\def\macro{\text{O}}

% defining it dynamically
\foreach \mname/\cmd in {%
    dynmacro/\text{O},%
    } {%
    \csxdef{\mname}{\expandonce\cmd}%
}

\begin{document}

\begin{equation}
    2^{\text{O}} \times % okay
    2^{\macro} \times   % okay
    2^{\dynmacro}       % okay :)
\end{equation}

\end{document}

答案3

您可以使用不封装宏中的项目的循环

\documentclass{report}
\usepackage[english]{babel}
\usepackage{pgffor}
\usepackage{amsmath}
\usepackage{xinttools}

% defining a plain macro
\def\macro{\text{O}}

\makeatletter % for LaTeX's \@namedef
% defining it dynamically
\xintForpair #1#2 in {%
  (dynmacro, \text{O})%
  % add more comma-separated "pairs" if needed
  % (no ending comma, though, only to separate pairs)
}\do
{%
    \@namedef{#1}{#2}%
}
\makeatother

\begin{document}

\begin{equation}
    2^{\text{O}} \times % okay
    2^{\macro} \times   % okay
    2^{\dynmacro}        % this one is also okay
\end{equation}

% \showoutput
\end{document}

enter image description here

相关内容