我遇到了嵌套宏定义的问题。虽然我的用例有点不同,但以下是一个最小(非)工作示例:
我想做的事:
我想动态定义一组宏\One
、\Two
和\Three
。它们每个都应采用相同数量的参数,但这个参数数量也应该是可变的。通过调用
\docsvlist{mm, One(#1), Two(#1 #2)}
我希望所有宏都定义成接受两个强制参数,并且
\One{Hi}{Hello}
\Two{Hi}{Hello}
\Three{Hi}{Hello}
回来'
One: One(Hi)
Two: Two(Hi Hello)
Three: One(Hi) + Two(Hi Hello)
代码:
\usepackage{xparse}
\usepackage{etextools}
\DeclareDocumentCommand{\myDeclare}{mmm}{
\DeclareDocumentCommand{\One}{#1}{One: #2\par}
\DeclareDocumentCommand{\Two}{#1}{Two: #3\par}
\DeclareDocumentCommand{\Three}{#1}{Three: #2 + #3\par}
}
\DeclareDocumentCommand{\do}{m}{
\DeclareDocumentCommand{\do}{m}{
%This would work for \One:
%\DeclareDocumentCommand{\One}{#1}{One: ##1\par}
\DeclareDocumentCommand{\do}{m}{
%This also works for \Two:
%\DeclareDocumentCommand{\Two}{#1}{Two: ####1\par}
\myDeclare{#1}{##1}{####1}
%This also does not work for \Three:
%\DeclareDocumentCommand{\Three}{#1}{Three: ##1 + ####1\par}
}
}
}
\docsvlist{mm, One(#1), Two(#1 #2)}
\One{Hi}{Hello}
\Two{Hi}{Hello}
\Three{Hi}{Hello}
这将产生以下输出:
One: One(Two(Hi Hello))
Two: Two(Hi Hello)
Three: One(Two(Hi Hello)) + Two(Hi Hello)
我真正想要的是:
One: One(Hi)
Two: Two(Hi Hello)
Three: One(Hi) + Two(Hi Hello)
我的问题:
发生了什么?我很惊讶它居然能正常工作。它\Two
按我想要的方式定义,但\One
只有按照我注释掉的方式定义它时,它才会被正确定义。我根本找不到\Three
正确定义的方法。
在呼吁
\myDeclare{#1}{##1}{####1}
在 的定义中,似乎从##1
变为,然后又变为。One(#1)
One(####1)
One(Two(#1 #2))
\One
但为什么呢?我该如何防止这种情况发生呢?
编辑:实际用例
我想同时定义几个数学函数或等式(或类似的东西),如(模拟)示例如下:
\MyDefine{
aSet, {},
\Omega, \subset \Reals,
{a nice set},
aFunction, O{i},
f^{#1}, :\aSet \to \aSet,
{some $#1$-th function},
anEquality, O{i}O{j},
\aFunction[#1] \leq \aFunction[#2], \text{for $#1 \leq #2$},
{a nice inequality}
}
这应该定义(其中包括:更新):
\DeclareDocumentCommand{\aSet}{}{
\Omega
}
\DeclareDocumentCommand{\aSetDefinition}{}{
\subset \Reals
}
\DeclareDocumentCommand{\aSetDescription}{}{
a nice set
}
\DeclareDocumentCommand{\aSetLabel}{}{def:aSet}
\DeclareDocumentCommand{\aFunction}{O{i}}{
f^{#1}
}
\DeclareDocumentCommand{\aFunctionDefinition}{O{i}}{
:\aSet \to \aSet
}
\DeclareDocumentCommand{\aFunctionDescription}{O{i}}{
some $#1$-th function
}
\DeclareDocumentCommand{\aFunctionLabel}{}{def:aFunction}
\DeclareDocumentCommand{\anEquality}{O{i}O{j}}{
\aFunction[#1] \leq \aFunction[#2]
}
...
以供以后使用并生成(例如):
\begin{align}
\aSet& \aSetDefinition&& \text{\aSetDescription}\label{\aSetLabel}\\
\aFunction& ...\\
\anEquality& ...
\end{align}
答案1
如果需要,您可以保留逗号列表输入。etextools
如果可以避免,请不要使用:expl3
具有您需要的所有功能:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\declaremacros}{>{\SplitArgument{2}{,}}+m}
{
\declaremacros:nnn #1
}
\cs_new_protected:Nn \declaremacros:nnn
{
\NewDocumentCommand\One{#1}{#2}
\NewDocumentCommand\Two{#1}{#3}
\NewDocumentCommand\Three{#1}{#2 ~ + ~ #3}
}
\ExplSyntaxOff
\declaremacros{mm, One(#1), Two(#1 #2)}
\begin{document}
\One{Hi}{Hello}
\Two{Hi}{Hello}
\Three{Hi}{Hello}
\end{document}
答案2
我可能不会同时使用 etextools 和 expl3,但在这里,你所针对的语法似乎使它变得比它本来应该的更复杂。这会产生所请求的输出
\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand{\zz}{mmm}{%
\DeclareDocumentCommand{\One}{#1}{One: #2\par}%
\DeclareDocumentCommand{\Two}{#1}{Two: #3\par}%
\DeclareDocumentCommand{\Three}{#1}{Three: #2 + #3\par}%
}
\zz{mm}{One(#1)}{Two(#1 #2)}
\begin{document}
\One{Hi}{Hello}
\Two{Hi}{Hello}
\Three{Hi}{Hello}
\end{document}
语法上唯一真正的区别是我使用{}{}
而不是,{ , }
但如果需要逗号列表,使用 expl3 列表处理器会很容易。不过括号组看起来更容易阅读。