为什么 Latex 输出四倍而不是三倍?

为什么 Latex 输出四倍而不是三倍?

为了跟踪论文中的定义,我为一些宏编写了两个版本。一个只是宏,就像\mymacro,另一个是宏的展开版本,我通常称之为\mymacro@unfold。然后我编写了一个命令\unfold,如果我写\unfold{\mymacro},输出就是\mymacro@unfold。这至少是我打算让它工作的方式(在大多数情况下它确实如此),但在这个例子中它没有,我不知道为什么。

MWE 如下。它首先定义\unfold宏,然后定义两个宏\cftalg及其\extalg展开版本。虽然 的输出\unfold{\cftalg{A}}\cftalg@unfold{A}应该的, 的输出\unfold{\extalg{A}}也是\cftalg@unfold{A}

\documentclass{article}

\makeatletter

%%%% To replace a token by another, use the following:
\newcommand{\@replace}[2]{#1}

%%%% Unfold replaces macros with their unfolded versions:
\newcommand{\unfold}[1]{%
  \@ifnextchar\cftalg{\@replace{\cftalg@unfold}}{%
  \@ifnextchar\extalg{\@replace{\extalg@unfold}}{%
  }}
  #1}

\newcommand{\algfont}{\mathbf}

\newcommand{\cftalg}{\algfont}

\newcommand{\cftalg@unfold}[1]{%
  ( \cftalgc{\cftalg{#1}},
    \cftalgf{\cftalg{#1}},
    \cftctxext{\cftalg{#1}},
    \cftempc{\cftalg{#1}})
  }

\newcommand{\extalg}{\algfont}

\newcommand{\extalg@unfold}[1]{%
  (\cftalgc{\algfont{#1}},
    \cftalgf{\algfont{#1}},
    \cftctxext{\algfont{#1}})
  }

%%%% The intended use of `\cftctx` is `\cftctx{\cftalg{#1}}`.
\newcommand{\cftalgc}[1]{%
  { \renewcommand{\cftalg}[1]{##1}
    #1
    }
  }

%%%% The intended use of `\cftfam` is `\cftfam{\cftalg{#1}}`.
\newcommand{\cftalgf}[1]{\mathcal{F}_{#1}}

\newcommand{\cftctxext}[1]{\epsilon^{#1}}

\newcommand{\cftempc}[1]{\phi^{#1}}

\makeatother

\begin{document}

We analyze some kind of algebras $\cftalg{A}$.
\begin{itemize}
\item Algebras of this kind are quadruples: $\unfold{\cftalg{A}}$
\item Underlying it is a simpler kind of algebras which is only a triple, but LaTeX thinks differently about this: 
      $\unfold{\extalg{A}}$
\end{itemize}

\end{document}

答案1

中的比较\@ifnextchar基于\ifx。由于\cftalg和具有相同的定义,因此即使宏为 ,也会使用 的\extalg分支。\cftalg\extalg

\cftalg一个简单的解决方法是使和的定义\extalg不同,例如:

\newcommand{\extalg}{\@empty\algfont}

或者

\newcommand*{\extalg}{\algfont}

完整示例:

\documentclass{article}

\makeatletter

%%%% To replace a token by another, use the following:
\newcommand{\@replace}[2]{#1}

%%%% Unfold replaces macros with their unfolded versions:
\newcommand{\unfold}[1]{%
  \@ifnextchar\cftalg{\@replace{\cftalg@unfold}}{%
  \@ifnextchar\extalg{\@replace{\extalg@unfold}}{%
  }}
  #1}

\newcommand{\algfont}{\mathbf}

\newcommand{\cftalg}{\algfont}

\newcommand{\cftalg@unfold}[1]{%
  ( \cftalgc{\cftalg{#1}},
    \cftalgf{\cftalg{#1}},
    \cftctxext{\cftalg{#1}},
    \cftempc{\cftalg{#1}})
  }

\newcommand{\extalg}{\@empty\algfont}

\newcommand{\extalg@unfold}[1]{%
  (\cftalgc{\algfont{#1}},
    \cftalgf{\algfont{#1}},
    \cftctxext{\algfont{#1}})
  }

%%%% The intended use of `\cftctx` is `\cftctx{\cftalg{#1}}`.
\newcommand{\cftalgc}[1]{%
  { \renewcommand{\cftalg}[1]{##1}
    #1
    }
  }

%%%% The intended use of `\cftfam` is `\cftfam{\cftalg{#1}}`.
\newcommand{\cftalgf}[1]{\mathcal{F}_{#1}}

\newcommand{\cftctxext}[1]{\epsilon^{#1}}

\newcommand{\cftempc}[1]{\phi^{#1}}

\makeatother

\begin{document}

We analyze some kind of algebras $\cftalg{A}$.
\begin{itemize}
\item Algebras of this kind are quadruples: $\unfold{\cftalg{A}}$
\item Underlying it is a simpler kind of algebras which is only a triple:
      $\unfold{\extalg{A}}$
\end{itemize}

\end{document}

结果

根据宏名进行比较

根据宏名实现比较的方法有很多种。下面的实现将第一个标记放入#1宏中\unfold@param,并将其与\unfold@cftalg和进行比较\unfold@extalg,这两个宏分别包含\cftalg\extalg

\documentclass{article}

\makeatletter

%%%% To replace a token by another, use the following:
\newcommand{\@replace}[2]{#1}

%%%% Unfold replaces macros with their unfolded versions:
\newcommand{\unfold}[1]{%
  \unfold@#1%
}
\newcommand*{\unfold@}[1]{%
  \def\unfold@param{#1}%
  \ifx\unfold@param\unfold@cftalg
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  \cftalg@unfold
  {%
    \ifx\unfold@param\unfold@extalg
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    \extalg@unfold
    {#1}%
  }%
}
\newcommand*{\unfold@cftalg}{\cftalg}
\newcommand*{\unfold@extalg}{\extalg}

\newcommand{\algfont}{\mathbf}

\newcommand{\cftalg}{\algfont}

\newcommand{\cftalg@unfold}[1]{%
  ( \cftalgc{\cftalg{#1}},
    \cftalgf{\cftalg{#1}},
    \cftctxext{\cftalg{#1}},
    \cftempc{\cftalg{#1}})
  }

\newcommand{\extalg}{\algfont}

\newcommand{\extalg@unfold}[1]{%
  (\cftalgc{\algfont{#1}},
    \cftalgf{\algfont{#1}},
    \cftctxext{\algfont{#1}})
  }

%%%% The intended use of `\cftctx` is `\cftctx{\cftalg{#1}}`.
\newcommand{\cftalgc}[1]{%
  { \renewcommand{\cftalg}[1]{##1}
    #1
    }
  }

%%%% The intended use of `\cftfam` is `\cftfam{\cftalg{#1}}`.
\newcommand{\cftalgf}[1]{\mathcal{F}_{#1}}

\newcommand{\cftctxext}[1]{\epsilon^{#1}}

\newcommand{\cftempc}[1]{\phi^{#1}}

\makeatother

\begin{document}

We analyze some kind of algebras $\cftalg{A}$.
\begin{itemize}
\item Algebras of this kind are quadruples: $\unfold{\cftalg{A}}$
\item Underlying it is a simpler kind of algebras which is only a triple:
      $\unfold{\extalg{A}}$
\end{itemize}

\end{document}

如果有两个以上的宏\cftalg,则扩展性更好的变体\extalg。实现假定\<macro>@unfold每个都存在\<macro>。此类宏声明为

\unfold@def\<macro>

完整示例:

\documentclass{article}

\makeatletter

%%%% To replace a token by another, use the following:
\newcommand{\@replace}[2]{#1}

%%%% Unfold replaces macros with their unfolded versions:
\newcommand{\unfold}[1]{%
  \unfold@#1%
}
\newcommand*{\unfold@}[1]{%
  \@ifundefined{unfold@@\detokenize{#1}}{#1}{%
    \csname unfold@@\detokenize{#1}\endcsname
  }%
}
\newcommand*{\unfold@def}[1]{%
  \expandafter\def\csname unfold@@\detokenize{#1}\expandafter\endcsname
  \expandafter{%
    \csname\expandafter\@gobble\string#1@unfold\endcsname
  }%
}
\unfold@def\cftalg
\unfold@def\extalg

\newcommand{\algfont}{\mathbf}

\newcommand{\cftalg}{\algfont}

\newcommand{\cftalg@unfold}[1]{%
  ( \cftalgc{\cftalg{#1}},
    \cftalgf{\cftalg{#1}},
    \cftctxext{\cftalg{#1}},
    \cftempc{\cftalg{#1}})
  }

\newcommand{\extalg}{\algfont}

\newcommand{\extalg@unfold}[1]{%
  (\cftalgc{\algfont{#1}},
    \cftalgf{\algfont{#1}},
    \cftctxext{\algfont{#1}})
  }

%%%% The intended use of `\cftctx` is `\cftctx{\cftalg{#1}}`.
\newcommand{\cftalgc}[1]{%
  { \renewcommand{\cftalg}[1]{##1}
    #1
    }
  }

%%%% The intended use of `\cftfam` is `\cftfam{\cftalg{#1}}`.
\newcommand{\cftalgf}[1]{\mathcal{F}_{#1}}

\newcommand{\cftctxext}[1]{\epsilon^{#1}}

\newcommand{\cftempc}[1]{\phi^{#1}}

\makeatother

\begin{document}

We analyze some kind of algebras $\cftalg{A}$.
\begin{itemize}
\item Algebras of this kind are quadruples: $\unfold{\cftalg{A}}$
\item Underlying it is a simpler kind of algebras which is only a triple:
      $\unfold{\extalg{A}}$
\end{itemize}

\end{document}

答案2

以下是解决给定问题的一种更简单的方法:

\documentclass{article}

\def\folddef#1#2{\expandafter\def \csname unfold@#1\string#2\endcsname}
\def\unfold#1#2{\csname unfold@#1\string#2\endcsname}

\folddef3\cftalg#1{(\mathbf{#1},\mathcal{F}_\mathbf{#1},\epsilon^\mathbf{#1})}
\folddef4\cftalg#1{(#1,\mathcal{F}_\mathbf{#1},\epsilon^\mathbf{#1},\phi^\mathbf{#1})}

\def\cftalg#1{\mathbf{#1}}

\begin{document}

We analyze some kind of algebras $\cftalg{A}$.
\begin{itemize}
\item Algebras of this kind are quadruples: $\unfold4\cftalg{A}$
\item Underlying it is a simpler kind of algebras which is only a triple:
      $\unfold3\cftalg{A}$
\end{itemize}

\end{document}

相关内容