neuer Befehl: Makro kann nicht als Argument enthalten sein

neuer Befehl: Makro kann nicht als Argument enthalten sein

Ich komme mir ein bisschen dumm vor, aber warum kann ich keine Makros in das Argument meines einfügen newcommand? Und warum kann mein Makro nicht \prainnerhalb der alignUmgebung funktionieren, obwohl es definitiv funktioniert, wenn ich das erweiterte Makro einfach manuell schreibe?

Mein Makro (zur Angabe von Wahrscheinlichkeiten):

\newcommand*{\pr}[2][]{\ifthenelse{\equal{#1}{}}{\Pr[\,#2\,]}{\Pr_{#1}[\,#2\,]}}

Das sollte ungefähr Folgendes ergeben:

Bildbeschreibung hier eingeben

Das funktioniert:

\pr[b \leftarrow \{0,1\}]{a = 0 \mid b = 0} 

Dies schlägt fehl:

\pr[\substack{a \leftarrow \{0,1\}}]{a = 0 \mid b = 0}

mit dem Fehler:

ERROR: Use of \\pr doesn't match its definition.

--- TeX said ---
\new@ifnextchar ...served@d = #1\def \reserved@a {
                                                  #2}\def \reserved@b {#3}\f...l.18 ...k{a \leftarrow \{0,1\}}]{a = 0 \mid b = 0}
                                                  \]

Und noch seltsamer: Innerhalb einer alignGleichung funktioniert jetzt nicht mehr die Version \prdes Makros, die vorher funktioniert hat, während es funktioniert, wenn ich alles manuell schreibe ...

Danke!

MWE:

\documentclass[]{article}

\usepackage{amsmath}
\usepackage{ifthen}
\setlength{\parindent}{0pt}

\newcommand*{\pr}[2][]{\ifthenelse{\equal{#1}{}}{\Pr[\,#2\,]}{\Pr_{#1}[\,#2\,]}}

\newcommand*{\pra}[2][]{\ifthenelse{\equal{#1}{}}{\Pr[\,#2\,]}{\Pr_{\substack{#1}}[\,#2\,]}}

\begin{document}
This works:
\[\pr{a = 0 \mid b = 0}\]
\[\pr[b \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]
\[\Pr_{\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}} [a = 0 \mid b = 0]\]
This fails:
% \[\pr[\substack{a \leftarrow \{0,1\}}]{a = 0 \mid b = 0}\]
% \[\pr[\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}]{a = 0 \mid b = 0}\]

But if I put substack inside, it works:
\[\pra[a \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]
\[\pra[a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]

Now, it's still stranger: if I put the full expression without my macro, it works inside an align:
\begin{align}
  \Pr_{\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}}[a = 0 \mid b = 0]
\end{align}
But if I use the macro that was used before, it fails:

% \begin{align}
%   \pra[a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}]{a = 0 \mid b = 0}
% \end{align}

% even if I use protect:
%\begin{align}
%  \pr[\protect\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}]{a = 0 \mid b = 0}
%\end{align}

\end{document}

Antwort1

Im Allgemeinen können Sie Makros als Argumente angeben, aber Sie müssen bei der Verwendung dieser Argumente etwas vorsichtig sein. Nicht alle Makros können mit allen Eingaben gleich gut umgehen.

\ifthenelsescheint mit komplexen Monstern wie nicht allzu glücklich zu sein \substack. Ich glaube, \ifthenelseder Test von \equalversucht, die verglichenen Zeichenfolgen zu erweitern, was schiefgeht, weil \substacknicht erweiterbar ist. In diesem Fall kann eine ordentliche Dosis von \protectvor nicht erweiterbarem Inhalt helfen, aber das wird nach einer Weile wahrscheinlich langweilig.

Ich würde es \ifthenelse{\equal{#1}{}}durch etoolbox's ersetzen \ifblank{#1}, das keine Erweiterung vornimmt und daher keine weitere Hilfe benötigt, um selbst mit komplexen Dingen wie \substackhier fertig zu werden.

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{etoolbox}

\newcommand*{\pr}[2][]{%
  \ifblank{#1}
    {\Pr[\,#2\,]}
    {\Pr_{#1}[\,#2\,]}}

\begin{document}
\begin{align}
  \pr[\substack{a \leftarrow \{0,1\}\protect\\b \leftarrow \{0,1\}}]{a = 0 \mid b = 0}
\end{align}
\end{document}

Die Tatsache, dass \ifblanksein Argument nicht erweitert, während \equaldies der Fall ist, bedeutet, dass es Unterschiede im Verhalten der beiden Tests gibt.

Vergleichen

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{etoolbox}
\usepackage{ifthen}

\newcommand*{\imblank}{}

\begin{document}
\ifthenelse{\equal{\imblank}{}}
  {T}
  {F}

\ifblank{\imblank}
  {T}
  {F}
\end{document}

Antwort2

Der \ifthenelseTest ist etwas fragil. Es gibt viel bessere Möglichkeiten, mit leeren optionalen Argumenten umzugehen.

Mit xparsedem Argumenttyp ist der Test auf ein nicht erscheinendes optionales Argument möglich o. Siehe die „einfache Definition“, die ich auskommentiere, weil eine noch bessere möglich ist, indem man \pr*anstelle eines anderen Befehls verwendet, der \substackbei Bedarf eingefügt wird.

\documentclass{article}

\usepackage{amsmath}
\usepackage{xparse}

%%% Easy version
%\NewDocumentCommand{\pr}{om}{%
%  \IfNoValueTF{#1}
%   {% no optional argument
%    \Pr[\,#2\,]%
%   }
%   {% optional argument is expressed
%    \Pr_{#1}[\,#2\,]%
%   }%
%}
%%% Better version
\NewDocumentCommand{\pr}{som}{%
  % * = use substack
  % #2 = optional
  % #3 = mandatory
  \Pr\IfValueT{#2}{_{\IfBooleanTF{#1}{\substack{#2}}{#2}}}[\,#3\,]
}

\begin{document}

\begin{gather*}
\pr{a = 0 \mid b = 0}
\\
\pr[b \leftarrow \{0,1\}]{a = 0 \mid b = 0}
\\
\pr*[a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}]{a = 0 \mid b = 0}
\end{gather*}

\end{document}

Was passiert? Wenn das optionale Argument nicht vorkommt, \IfNoValueTFgibt es den True-Zweig zurück, andernfalls den False-Zweig. Umgekehrt verhält es sich mit \IfValueTF. Hier können wir mit abkürzen \IfValueT, da wir bei fehlendem optionalen Argument nichts tun müssen.

Innerhalb dieses bedingten Textes verwenden wir eine weitere Bedingung: Wenn *nach steht \pr, \IfBooleanTFwird der wahre Zweig zurückgegeben und das optionale Argument ist von umgeben \substack. Andernfalls wird das einfache Argument verwendet.

Bildbeschreibung hier eingeben

Antwort3

Es muss ein optionales Argument enthalten sein [wenn \protectes verwendet wird].\substack\ifthenelse

\documentclass[]{article}

\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{ifthen}
\setlength{\parindent}{0pt}

\newcommand*{\pr}[2][]{\ifthenelse{\equal{#1}{}}{\Pr[\,#2\,]}{\Pr_{#1}[\,#2\,]}}

\newcommand*{\pra}[2][]{\ifthenelse{\equal{#1}{}}{\Pr[\,#2\,]}{\Pr_{\substack{#1}}[\,#2\,]}}

\begin{document}
This works:
\[\pr{a = 0 \mid b = 0}\]
\[\pr[b \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]
\[\Pr_{\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}} [a = 0 \mid b = 0]\]
This [no longer] fails with \verb|\protect|:
 \[\pr[\protect\substack{a \leftarrow \{0,1\}}]{a = 0 \mid b = 0}\]
 \[\pr[\protect\substack{a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}}]{a = 0 \mid b = 0}\]

But if I put substack inside, it works:
\[\pra[a \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]
\[\pra[a \leftarrow \{0,1\}\\b \leftarrow \{0,1\}]{a = 0 \mid b = 0}\]

\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen