# How to use \cs_generate_variant:Nn to compare token lists?

I want to deal with this question by my method. The example below is some codes from interface3.pdf; But throws the error:

! LaTeX3 Error: Variant form 'VV' deprecated for base form '\tl_if_eq:NNTF'.

\documentclass{article}
\usepackage{expl3}

\begin{document}
\ExplSyntaxOn
\tl_set:Nn \l_tmpa_tl { abc }
\tl_set:Nx \l_tmpb_tl { \tl_to_str:n { abc } }
\cs_generate_variant:Nn \tl_if_eq:NNTF { VV } % without this line, the result is falue, I want to get true with this line.
\tl_if_eq:VVTF \l_tmpa_tl \l_tmpb_tl { true } { false }
\ExplSyntaxOff
\end{document}

• But the two token lists aren't equal. One is a token list abc, and the other is a string abc. – Phelype Oleinik Oct 22 '19 at 11:15
• @Oleinik thanks. but why there is a bug with this code. – Brooks Oct 22 '19 at 11:16

You have two issues. The first is that a V argument doesn't really make sense as variant for an N argument (that's why it's deprecated). When you get the Value of a variable, the result will not necessarily be a single token, so the N argument will fail. That's why you can only make V variants of n arguments.

The second is that one token list contains the letter tokens abc (\tl_analysis_show:N \l_tmpa_tl shows):

The token list \l_tmpa_tl contains the tokens:
>  a (the letter a)
>  b (the letter b)
>  c (the letter c)


while the second token list contains the character tokens abc (\tl_analysis_show:N \l_tmpb_tl):

The token list \l_tmpb_tl contains the tokens:
>  a (the character a)
>  b (the character b)
>  c (the character c)


so they are not equal when doing a token list comparison. You need a string comparison here:

\str_set:Nn \l_tmpa_str { abc }
\str_set:Nx \l_tmpb_str { \tl_to_str:n { abc } }
\str_if_eq:VVTF \l_tmpa_str \l_tmpb_str { true } { false }


Note that \str_set:Nx \l_tmpb_str { \tl_to_str:n { abc } } is redundant. The argument of \str_set:Nx (and other str functions) is already passed through \tl_to_str:n.

• shouldn't the first n be N? – Ulrike Fischer Oct 22 '19 at 11:29
• @UlrikeFischer Oops ;-) – Phelype Oleinik Oct 22 '19 at 12:25

There is no reason to define variants (besides being wrong to begin with, in this case):

\tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl {true} {false}


is already the thing to do (and yields false in your case).

You might think to do a comparison between an explicit token list and (the contents of) a token list variable, defining variants of \tl_if_eq:nnTF.

You can do

\prg_generate_conditional_variant:Nnn \tl_if_eq:nn {Vn,nV} { T,F,TF }


and now something like

\tl_if_eq:nVTF {abc} \l_tmpb_tl {true} {false}
\tl_if_eq:VnTF \l_tmpa_tl {abc} {true} {false}


will work (in your case the former yields false, the latter yields true).

The function \prg_generate_conditional_variant:Nnn is a wrapper around \cs_generate_variant:Nn that's meant to define variants for conditional functions (signature ending in TF, T or F); it avoids having to apply several times the basic function.

With the code above you define all variants

\tl_if_eq:nVTF
\tl_if_eq:nVT
\tl_if_eq:nVF
\tl_if_eq:VnTF
\tl_if_eq:VnT
\tl_if_eq:VnF


at once. Note that defining \tl_if_eq:VVTF is useless, because it would be the same as \tl_if_eq:NNTF, just slower and not fully expandable.

• thanks for your answer. – Brooks Oct 22 '19 at 12:20
• \tl_if_eq:NNTF would not be the same as \tl_if_eq:VVTF. The former is expandable, while the latter, being based on \tl_if_eq:nnTF would not be. – Phelype Oleinik Oct 22 '19 at 12:30
• @PhelypeOleinik Right, I'll add it. – egreg Oct 22 '19 at 12:32