做蠢事导致的愚蠢错误

做蠢事导致的愚蠢错误

当我写论文时,我写了以下两个命令,我发现它们很有用(现在仍然如此)。它们都是定义其他命令的方式。

\usepackage{ifthen}
\makeatletter  
\def\optional #1[#2]#3#4{\newcommand{#1}[#2][@rGUmentmiSSing]{\ifthenelse{\equal{##1}{@rGUmentmiSSing}}{#4}{#3}}}  
\newcommand{\starredcommand}[4][*]{\newcommand{#2}{\@ifnextchar#1{\expandafter #4\@gobble}{#3}}}  
\makeatother

它们不太容易阅读。第一个允许我定义一个带有可选参数的命令,如果存在可选参数,则命令的行为会有很大不同。

第二种方法允许我定义一个带有修饰符的命令,我通常在我有同一对象的两个版本但其中一个版本定义在更大的空间中时使用这种方法。例如我有

\optional{\foo}[1]{F(#1)}{F} 
\starredcommand{\barr}{\mathcal B}{\mathscr B}

所以我可以写

\begin{align}
    \foo &= \foo[x] \\ 
    \barr &\neq \barr*
\end{align}

这将产生与

\begin{align}
    F &= F(x) \\ 
    \mathcal B &\neq \mathscr B
\end{align}

我喜欢这些命令,但它们不能很好地协同工作。例如,如果我写\foo[\bar]或我得到超过 100 个错误,这很糟糕。这与命令吃掉括号 \foo[\bar*]无关。给我同样的东西。这与方括号无关。如果我定义\@gobble\foo[\bar* 123456789]

\newcommand{\fine}[1][y]{X^{#1}}

然后就\fine[\bar]可以按照预期的方式工作了。

我不知道出了什么问题。如果有人能帮忙就太好了。

如果这个问题太简单,这里有一个后续问题。目前,我还没有办法在我的文章中加入论据。\starredcommand如果我想给出\barr一个论据,我通常会这样做

\makeatletter
\newcommand{\@barr}[1]{\mathcal B^{#1}}
\newcommand{\@barrstar}{\mathscr B^{#1}}
\starredcommand{\barr}{\@barr}{\@barrstar}
\makeatother

它可以正常工作(即使使用可选参数或我的\optional命令),但它首先违背了定义的意义\starredcommand。我希望有一个可以与参数一起使用的带星号命令版本,但我想不出如何做到这一点。

答案1

快速尝试xparse

\documentclass{article}
\usepackage{xparse,mathrsfs}
\NewDocumentCommand\optional{mO{}mm}
 {%
  \NewDocumentCommand{#1}{o#2}
   {\IfNoValueTF{##1}{#4}{#3}}%
 }
\NewDocumentCommand\starredcommand{O{s}mmm}
 {%
  \NewDocumentCommand{#2}{#1}
   {\IfBooleanTF{##1}{#4}{#3}}%
 }

\optional{\foo}{F(#1)}{F}
\optional{\baz}[m]{Baz with opt #1 and #2}{Baz without opt and #2}
\starredcommand{\barr}{\mathcal{B}}{\mathscr{B}}
\starredcommand[t{+}]{\carr}{\mathcal{C}}{\mathscr{C}}

\begin{document}
$\foo$

$\foo[x]$

$\foo[\barr*]$

$\foo[\barr]$

$\foo[\carr+]$

$\foo[\carr]$

\baz{x}

\baz[Y]{x}
\end{document}

但是,您必须更改指定参数的方式。您可以在示例中看到如何使用;+代替;以及如何使用强制参数进行定义(可选参数始终存在)。*\optional\baz

在此处输入图片描述

答案2

以下是你可以使用\starredcommand参数的方法

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathrsfs}
\makeatletter
% Following 3 lines thanks to Prof. Enrico Gregorio, from:
% http://tex.stackexchange.com/questions/42318/
%   removing-a-backslash-from-a-character-sequence
\begingroup\lccode`\|=`\\
\lowercase{\endgroup\def\removebs#1{\if#1|\else#1\fi}}
\newcommand{\@macro@name}[1]{\expandafter\removebs\string#1}
%
\newcommand\starredcommand[5]{%
  \gdef\mname{\@macro@name{#1}}%
  \newcommand#1{\@ifstar{\csname @\mname star\endcsname}
                        {\csname @\mname\endcsname}}
  \expandafter\newcommand\csname @\mname\endcsname[#2]{#3}
  \expandafter\newcommand\csname @\mname star\endcsname[#4]{#5}
}
\makeatother
\begin{document}

\starredcommand{\barr}{1}{\mathcal #1}{1}{\mathscr #1}

\begin{align}
    \barr{C} &\neq \barr*{F}
\end{align}

\end{document}

在此处输入图片描述

跟进:这是您的\optional命令的一个版本:

\usepackage{ifthen}
% ...
\def\optional#1[#2]#3#4{%
  \newcommand#1[#2][]{\ifthenelse{\equal{##1}{}}{#4}{#3}}%
}

虽然这并不理想。它确实允许根据用户的意愿,将\barr作为的参数foo,但\barr必须保护,如

\optional{\foo}[1]{F(#1)}{F}
\( \foo = \foo[\protect\barr{Q}] \neq \foo[\protect\barr*{R}]\)

在此处输入图片描述

相关内容