To get the content in a tl variable (in function \foo_my_func:n), I have several ways:

% 1
\foo_my_func:n { \l__foo_test_tl }
% 2
\cs_generate_variant:Nn \foo_my_func:n { N }
\foo_my_func:N \l__foo_test_tl
% 2
\cs_generate_variant:Nn \foo_my_func:n { V }
\foo_my_func:V \l__foo_test_tl

It seems they all give the same result in this simple case. But is there any difference?

  • What's your use-case? Maybe that would make your question clearer.
    – TeXnician
    Nov 24, 2017 at 7:47

1 Answer 1


The first thing to note is that n and N are both 'base' argument types. For tl, we use these two to distinguish

\tl_foo:n { tokens }
\tl_foo:N \l_tokens_tl

The V variant relates to n, so

\tl_foo:V \l_tokens_tl

is equivalent to

\tl_foo:n { <content of \l_tokens_tl> }

Depending on the internals of a particular function, it may be the case that you can pass a tl variable (N-type) and get the same behaviour as you see for the tokens themselves. However, this is not guaranteed and should not be relied on. It will depend on what action the function takes. For example, if we look at \tl_to_str:n, the results of

\tl_set:Nn \l_tmpa_tl { Hello }
\cs_generate_variant:Nn \tl_to_str:n { V }
\tl_to_str:n { \l_tmpa_tl }
\tl_to_str:V \l_tmpa_tl

are very different.

In general, you should not pass tl variables 'inside' an n-type argument. Either use a dedicated N-type function, if available, or pass the value using a V-type variant.

To be clear, the N type argument means 'exactly one token'. The most obvious place this is important is where we are then going to set (or adjust) the content of a tl. For example, \tl_set:Nn has to have the name of a token list variable as the first argument: it cannot be a V type. You cannot assume that an N-type argument 'turns into' some list of tokens inside the function using it.

In contrast, the V-type argument is just a way of getting to an n-type underlying value. Thus anything that will give a 'value' can be used here:

\cs_generate_variant:Nn \tl_set:Nn { NV }
\tl_set:NV \l_tmpa_tl \l_tmpa_int

Notice that the fact I've got the value from an int here is entirely irrelevant: once the V-type has acted, I am left with a list of tokens which can be saved in a tl.

  • Could you explain the differnce between N and V? Or give some examples?
    – stone-zeng
    Nov 24, 2017 at 8:05
  • Recently, I've noticed that for \int_eval:n, l3interface says that any tl variable will be expand inside. So \int_eval:n { \l_my_tl } may be OK here?
    – stone-zeng
    Mar 24, 2018 at 8:24

You must log in to answer this question.

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