识别宏是否为别名

识别宏是否为别名

我使用 adef作为别名,如下所示:

\def\alias{\foo}

稍后我想检查是否\alias是 foo 的别名。(X 是 Y 的别名意味着 X 的当前定义是def\X{\Y})。

请参阅下面的 MWE 了解我所尝试的操作:

梅威瑟:

\documentclass{article}
%\usepackage{trace}
\def\foo{bar}
\def\bar{bar}

\newcommand{\isFoo}[1]{
%   \expandafter\if\expandafter\noexpand\alias\noexpand\foo  %false positives
%   \expandafter\ifx\alias\foo                               %this one compares text
%   \expandafter\ifx\expandafter\noexpand\alias\noexpand\foo %false negatives
        It is a \textbackslash foo #1
    \else
        Not a \textbackslash foo #1
    \fi
}
\begin{document}
    \def\alias{\foo}
    \isFoo{ab}

    \def\alias{\bar}
    \isFoo{xy}

    \def\bar{baz}
    \isFoo{xy}
\end{document}

expandafter/代码背后的想法noexpand\alias只扩展一次,然后比较两个标记而不进行任何进一步扩展,以避免比较它们的返回值。

答案1

您也可以为 设置另一个别名,\foo然后\alias与其进行比较\ifx

\documentclass{article}

% \def\foo{bar}
% \def\bar{bar}

\def\knownaliasforfoo{\foo}
\newcommand{\isFoo}[1]{%
  \ifx\alias\knownaliasforfoo
    It is a \textbackslash foo #1%
  \else
    Not a \textbackslash foo #1%
  \fi
}

\begin{document}
    \def\alias{\foo}
    \isFoo{ab}

    \def\alias{\bar}
    \isFoo{xy}

    \def\bar{baz}
    \isFoo{xy}
\end{document}

在此处输入图片描述

您可以取消注释其中一行或两行注释,输出仍保持不变。

答案2

expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\ifisaliasTF}{mmmm}
 {% #1 = token to test
  % #2 = macro
  % #3 = true case
  % #4 = false case
  \ted_ifisalias:nnTF { #1 } { #2 } { #3 } { #4 }
 }

\prg_generate_conditional_variant:Nnn \tl_if_empty:n { f } { T,F,TF,p }
\prg_generate_conditional_variant:Nnn \tl_if_single:n { o } { T,F,TF,p }

\prg_new_conditional:Nnn \ted_ifisalias:nn { T,F,TF,p }
 {
  \token_if_macro:NTF #1
   {% the first argument is a macro
    \tl_if_empty:fTF { \token_get_arg_spec:N #1 }
     {% the macro has no arguments
      \tl_if_single:oTF { #1 }
       {% the expansion is a single token
        \exp_last_unbraced:No \token_if_eq_meaning:NNTF #1 #2
         {% the first level expansion of #1 is the same as #2
          \prg_return_true:
         }
         {% false
          \prg_return_false:
         }
       }
       {% false
        \prg_return_false:
       }
     }
     {% false
      \prg_return_false:
     }
   }
   {% false
    \prg_return_false:
   }
 }
\ExplSyntaxOff

\newcommand{\foo}{Whatever}
\newcommand{\alias}{\foo}
\newcommand{\notaliasA}[1]{\foo}
\newcommand{\notaliasB}{\foo\foo}

\begin{document}

\ifisaliasTF{\alias}{\foo}{Alias}{Not alias}

\ifisaliasTF{\foo}{\foo}{Alias}{Not alias}

\ifisaliasTF{\notaliasA}{\foo}{Alias}{Not alias}

\ifisaliasTF{\notaliasB}{\foo}{Alias}{Not alias}

\end{document}

在此处输入图片描述

答案3

下面应该可以实现你想要的效果。

\documentclass[]{article}

\usepackage{pdftexcmds}

\def\alias{\foo}
\makeatletter
\newcommand\checkalias[2]
  {%
    \expandafter\expandafter\expandafter
    \checkalias@a\expandafter\expandafter\expandafter
      {\expandafter\detokenize\expandafter{#1}}{#2}%
  }
\newcommand\checkalias@a[2]
  {%
    \expandafter\ifnum
    \expandafter\pdf@strcmp\expandafter{\detokenize{#2}}{#1}=0
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
\makeatother

\begin{document}
\checkalias{\alias}{\foo}
  {still an alias}{no longer an alias}
\def\alias{\bar}
\checkalias{\alias}{\foo}
  {still an alias}{no longer an alias}
\end{document}

但是它不会检查第一个参数是否会抓取任何参数,因此不如 @egreg 的检查安全。不过我认为,如果不使用 expl3,就不值得实施必要的检查。

相关内容