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'.


\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 }
  • But the two token lists aren't equal. One is a token list abc, and the other is a string abc. Oct 22, 2019 at 11:15
  • @Oleinik thanks. but why there is a bug with this code.
    – Brooks
    Oct 22, 2019 at 11:16

2 Answers 2


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.

  • 1
    shouldn't the first n be N? Oct 22, 2019 at 11:29
  • 1
    thanks, I read interface3 more carefully after reading your nice answer.
    – Brooks
    Oct 22, 2019 at 11:29
  • @UlrikeFischer Oops ;-) Oct 22, 2019 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


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, 2019 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. Oct 22, 2019 at 12:30
  • 1
    @PhelypeOleinik Right, I'll add it.
    – egreg
    Oct 22, 2019 at 12:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .