我发现自己写了$\{0,1\}^x$
很多东西,所以我想定义一个简写宏:
\def\zo#1{\{0,1\}^{#1}}
但是,有时我需要$\{0,1\}$
没有上标。如果我写的话,\zo{}
在右括号后会得到一点点额外的空间(因为那里有一个空的上标)。我发现摆脱它的唯一方法是
\def\zo#1{\{0,1\}\if\relax\detokenize{#1}\relax\else^{#1}\fi}
这听起来有点拗口。有没有更优雅的方法来实现这一点?请注意,我正在编写的实际文档是 LaTeX 格式的,因此如果 amsmath(例如)能达到目的,那将是一个很好的答案。我用纯 TeX 表达了这个问题,因为它从根本上来说是一个关于核心数学引擎的问题。
如果你看不到那一点点额外的空间,这个 MWE(需要(pdf)etex
)会让它变得明显:
\def\a#1{\{0,1\}^{#1}}
\def\b#1{\{0,1\}\if\relax\detokenize{#1}\relax\else^{#1}\fi}
\leavevmode\rlap{$\a{}\a{}\a{}\a{}$}$\b{}\b{}\b{}\b{}$
\bye
→ (400% 缩放)
答案1
解决方案 A
使用
\def\a{\{0,1\}}
^{<stuff>}
如果需要的话,可以添加。
解决方案 B
笔记
\csname <something else>\endcsname
\relax
如果\<something else>
未定义,则扩展为。\qrrgobbletwo<something>
在<something>
可以作为 参数的地方,不得命名任何其他宏\a
。- 其他答案中使用的所有其他“技巧”和帮助程序(
\newcommand
带有可选参数/\@ifnextchar
)仍然可以应用。 (但无论如何我都会使用条件!)
参考
代码
\def\qrrgobbletwo#1#2{}
\def\a#1{%
\{0,1\}\csname qrrgobbletwo\detokenize{#1}\endcsname^{#1}%
}
\def\b#1{\{0,1\}\if\relax\detokenize{#1}\relax\else^{#1}\fi}
\leavevmode\rlap{$\a{}\a{}\a{}\a{}$}$\b{}\b{}\b{}\b{}$
\leavevmode\rlap{$\a{a}\a{a}\a{a}\a{a}$}$\b{a}\b{a}\b{a}\b{a}$
\bye
输出
答案2
这似乎是一个可选功能,因此应该是一个可选参数:
\newcommand\zo[1][]{\{0,1\}\ifx\relax#1\relax\else^{#1}\fi}
\zo \zo[x]
答案3
使用例如xparse
你会得到更易读的代码:
\usepackage{xparse}
\DeclareDocumentCommand\zo{g}{%
\ensuremath{%
\{0,1\}%
\IfNoValueTF{#1}{}{^{#1}}%
}%
}
使用{o}
作为参数说明符而不是{g}
将使命令使用可选的([]
-delimited)参数,这可能更合适。
答案4
\makeatletter
\newcommand\zo[1]{\begingroup\def\x{#1}\ifx\x\@empty\{0,1\}\else\{0,1\}^{\x}\fi\endgroup}
\makeatother
我们通过 收集参数\def\x{#1}
,然后通过 测试它是否为空\ifx\x\@empty
。其余的应该很清楚。这个解决方案比你的好一点,因为我们只读了一次 #1。如果用 替换 来使其更强大\newcommand
,可能是一个好主意\DeclareRobustCommand
,这样你也可以在奇怪的上下文中将它用作章节标题。
为了实现它纯粹的 TeX,您可以执行以下操作:
\def\zo#1{\begingroup\def\x{#1}\def\y{}\ifx\x\y\{0,1\}\else\{0,1\}^{\x}\fi\endgroup}
例子:
\makeatletter
\newcommand\zo[1]{\begingroup\def\x{#1}\ifx\x\@empty\{0,1\}\else\{0,1\}^{\x}\fi\endgroup}
\newcommand\oldzo[1]{\{0,1\}^{#1}}
\makeatother
\noindent
$\zo{}\zo{}\zo{}\zo{}$\\
$\oldzo{}\oldzo{}\oldzo{}\oldzo{}$\\
$\{0,1\}\{0,1\}\{0,1\}\{0,1\}$
具有可选参数的变体:
\makeatletter
\def\zo@opt[#1]{\{0,1\}^{#1}}
\newcommand\zo{\@ifnextchar[\zo@opt{\{0,1\}}}
\makeatother
$\zo[2] \neq \zo \zo$