为什么 \ifx 认为 \MakeUppercase{1} 和 \MakeLowercase{1} 不同?

为什么 \ifx 认为 \MakeUppercase{1} 和 \MakeLowercase{1} 不同?

在这个最小的例子中,大写数字与小写数字不同。为什么?

\documentclass{memoir}

\begin{document}

\def\testone{\MakeUppercase{1}}
\def\testtwo{\MakeLowercase{1}}

\ifx\testone\testtwo
    Equal
\else
    Diff
\fi

\end{document}

打印:不同

答案1

就像 Donald Hosek 所说的那样,\ifx不扩展其参数。您正在比较未扩展的宏\MakeUppercase{1}\MakeLowercase{1}。您可以通过完全扩展所比较的宏来解决这个问题。

但是,这并不能为您提供完整的解决方案,因为\MakeUppercase\MakeLowercase不可扩展。因此,\edef\upperone{{\MakeUppercase 1}}将失败。您应该改用完全可扩展的 expl3 函数,并且还支持Unicode。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
    
\ExplSyntaxOn
\edef\upone{\text_uppercase:n {1}}
\edef\lowone{\text_lowercase:n {1}}
\ExplSyntaxOff
    
\begin{document}
{\upone} and {\lowone} are
\ifx\upone\lowone
  identical.
\else
  different.
\fi
    
\end{document}

这就得到了“1 和 1 相同”。

编辑

Joseph Wright 指出,你可能真的需要进行不区分大小写的比较。为此,你应该使用\str_fold_case:n,它支持 LuaTeX 或 XeTeX 上的 Unicode,但仅支持 PDFTeX 上的 ASCII。

答案2

您将得到不同的结果,因为您正在比较两个宏的定义。\MakeUppercase{1}与不同值得注意的是\MakeLowercase{1}\MakeUppercase\MakeLowercase宏本身足够复杂,以至于尝试扩展它们以纯文本获取结果的简单方法仍然不会给出预期的结果(因此,例如,\edef或多个\expandafters 不会让您得到您可能希望得到的结果)。

答案3

该测试未能证明(至少)两个层面上的平等。

第一级

\MakeUppercase\MakeLowercase指示打印它们的参数的大写或小写版本。它们不会“直接”转换它们的参数。

第二级

\ifx仅比较两个 token 的“表面含义”,而不进行任何宏扩展。具体而言,当且仅当两个宏(用 定义的每个 token\def都是一个宏)被认定为相等时,\ifx

  1. \long它们在、\outer和方面具有相同的地位\protected
  2. 它们的参数文本相同;
  3. 它们的顶层扩展是相等的。

在你的情况下,子测试 1 和 2 通过,但子测试 3 没有通过,因为顶级扩展是

\MakeUppercase{1}

\MakeLowercase{1}

分别是不同的标记序列。


一个可能更简单的例子是

\def\firstX{X}
\def\secondX{X}
\def\testA{\firstX}
\def\testB{\secondX}

条件\ifx\firstX\secondX会返回 true,但是\ifx\testA\testB会返回 false。

另一个例子:

\def\first#1{#1}
\def\second#1{#1}
\def\testA{\first{X}}
\def\testB{\second{X}}

条件将返回 false,因为和\ifx\testA\testB的顶层扩展不同,即使最终和会产生相同的结果。但 TeX 在进行比较时并不看“最终”效果,而只看表面。\testA\testB\first{X}\second{X}\ifx

相关内容