我使用 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,就不值得实施必要的检查。