为什么我的第三个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}
我该如何修正我的动态宏?
答案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=#2
) - 要执行的定义
- 需要定义的事物列表
这里举几个例子。
\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}
如您所见,第一个例子使用默认值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}