\tl_if_eq:NNTF 的奇怪行为

\tl_if_eq:NNTF 的奇怪行为

在下面的 MWE 中NewDocumentCommands \myComparison,和\myNewComparison都使用一个控制序列\cookbook_Compare:nn,该序列被输入两个要比较的 tokenlist 参数。这些参数被定义为可选O{}类型参数;在\myComparison默认值是按字面定义的,而在\myNewComparison它们是通过变量定义的tokenlist。调用 1.、2. 和 3. 的\myComparison工作符合预期,调用 4. 和 5. 也是如此\myNewComparison。但是,如果\myNewComparison像在 6. 中那样不带参数地调用,则\tl_if_eq:NNTF在比较两个内容相同的变量时会得出错误的答案tokenlist。为什么?

\usepackage[check-declarations]{expl3}
\usepackage{xparse}
%   ----------------------------------------
\ExplSyntaxOn
%   VARIABLE DECLARATIONS:
\tl_new:N \l_rn_OpOne_tl
\tl_new:N \l_rn_OpTwo_tl
\tl_new:N \l_rn_OpOneDefault_tl
\tl_new:N \l_rn_OpTwoDefault_tl
\tl_set:Nn \l_rn_OpOneDefault_tl {abc} 
\tl_set:Nn \l_rn_OpTwoDefault_tl {abc} 
%   ----------------------------------------
\NewDocumentCommand\myComparison{O{abc}O{abc}}
 {
 \cookbook_Compare:nn {#1}{#2}
 }
\NewDocumentCommand\myNewComparison{O{\l_rn_OpOneDefault_tl}O    {\l_rn_OpTwoDefault_tl}}
 {
 \cookbook_Compare:nn {#1}{#2}
 }
\cs_new_protected:Npn \cookbook_Compare:nn #1 #2 
    {
        \tl_set:Nn \l_rn_OpOne_tl {#1}
        \tl_set:Nn \l_rn_OpTwo_tl {#2}
        Op~1:~\l_rn_OpOne_tl\\
        Op~2:~\l_rn_OpTwo_tl\\
        Op~1~=~ Op~2~  
        \tl_if_eq:NNTF \l_rn_OpOne_tl \l_rn_OpTwo_tl
            {TRUE\\}{FALSE\\}
    }
\ExplSyntaxOff
\begin{document}
1. \verb+\myComparison[zz][zz]+:\\
 \myComparison[zz][zz]
2. \verb+\myComparison[1z][zz]+:\\
 \myComparison[1z][zz]
3. \verb+\myComparison+:\\
\myComparison
4. \verb+\myNewComparison[zz][zz]+:\\
 \myNewComparison[zz][zz]
5. \verb+\myNewComparison[1z][zz]+:\\
 \myNewComparison[1z][zz]
6. \verb+\myNewComparison+:\\
\myNewComparison
\end{document}

答案1

标记列表等价性的测试不是“它们最终是否扩展为相同的东西”,而是“它们是否具有相同的内容”。使用你的代码,你实际上最终会得到

\tl_set:Nn \l_rn_OpOne_tl {\l_rn_OpOneDefault_tl}
\tl_set:Nn \l_rn_OpTwo_tl {\l_rn_OpTwoDefault_tl}

它们是不相等的:它们包含不同的 tl 变量,但碰巧具有相同的内容。

如果您想比较此处的内容,并且还想允许文字和存储的输入,那么您必须使用 强制扩展至“文本” \tl_set:Nx。 风险在于使用 LaTeX2e 输入时,您可能会遇到脆弱的命令,因此除非您处于非常受限的情况,\protected@edef否则您应该使用。 (expl3不提供后者的任何等效项,因为“原生”LaTeX3 材料不需要 LaTeX2e 稳健机制。)

答案2

您必须使用不同的方式来测试可选参数,以便您可以比较正确的标记;否则,您正在比较\l_rn_OpOneDefault_tl\l_rn_OpTwoDefault_tl而不是变量的内容)。

\documentclass{article}
\usepackage[check-declarations]{expl3}
\usepackage{xparse}
%   ----------------------------------------
\ExplSyntaxOn
%   VARIABLE DECLARATIONS:
\tl_new:N \l_rn_OpOne_tl
\tl_new:N \l_rn_OpTwo_tl
\tl_new:N \l_rn_OpOneDefault_tl
\tl_new:N \l_rn_OpTwoDefault_tl
\tl_set:Nn \l_rn_OpOneDefault_tl {abc} 
\tl_set:Nn \l_rn_OpTwoDefault_tl {abc} 
%   ----------------------------------------
\NewDocumentCommand\myComparison{O{abc}O{abc}}
 {
 \cookbook_Compare:nn {#1}{#2}
 }
\NewDocumentCommand\myNewComparison{oo}
 {
  \IfNoValueTF{#1}
   { \cookbook_Compare:VV \l_rn_OpOneDefault_tl \l_rn_OpTwoDefault_tl }
   {
    \IfNoValueTF{#2}
     { \cookbook_Compare:nV { #1 } \l_rn_OpTwoDefault_tl }
     { \cookbook_Compare:nn { #1 } { #2 } }
   }
 }
\cs_new_protected:Npn \cookbook_Compare:nn #1 #2 
    {
        \tl_set:Nn \l_rn_OpOne_tl {#1}
        \tl_set:Nn \l_rn_OpTwo_tl {#2}
        Op~1:~\l_rn_OpOne_tl\\
        Op~2:~\l_rn_OpTwo_tl\\
        Op~1~=~ Op~2~  
        \tl_if_eq:NNTF \l_rn_OpOne_tl \l_rn_OpTwo_tl
            {TRUE\\}{FALSE\\}
    }
\cs_generate_variant:Nn \cookbook_Compare:nn { nV , VV }
\ExplSyntaxOff
\begin{document}
1. \verb+\myComparison[zz][zz]+:\\
 \myComparison[zz][zz]
2. \verb+\myComparison[1z][zz]+:\\
 \myComparison[1z][zz]
3. \verb+\myComparison+:\\
\myComparison
4. \verb+\myNewComparison[zz][zz]+:\\
 \myNewComparison[zz][zz]
5. \verb+\myNewComparison[1z][zz]+:\\
 \myNewComparison[1z][zz]
6. \verb+\myNewComparison+:\\
\myNewComparison
\end{document}

在此处输入图片描述

相关内容