Assume I have a function that takes a tl var as an argument:

\module_myfunc:N \l_module_tlvar_tl

But what I have at hand is not the tl var but the name of the tl var:


How do I invoke \module_myfunc:N with \l_module_tlvarname_tl in LaTeX3?


\tl_new:N \l_module_tlvar_tl
\tl_new:N \l_module_tlvarname_tl
\tl_set:Nn \l_module_tlvar_tl { dope }
\tl_set:Nn \l_module_tlvarname_tl { l_module_tlvar_tl }
\cs_new:Npn \module_myfunc:N #1
    \cs_to_str:N #1
%%  This is what I want.
\module_myfunc:N \l_module_tlvar_tl
%%  This is how I do it in LaTeX2e.
%%  In LaTeX3: Is this the same as what I want?
\tl_new:N \l_module_tlvara_tl
\tl_set:Nn \l_module_tlvara_tl { \tl_use:c { \l_module_tlvarname_tl } }
\module_myfunc:N \l_module_tlvara_tl
  • Please note that the correct name of tl variables is \<l/g>_<module>_<name>_tl with <l/g> being l for local and g for global variables and followed by a second underscore for internal variables, <module> being the name of your module, and <name> being the actual meaningful name for the variable.
    – Skillmon
    Jun 29, 2020 at 17:34
  • 1
    If you want to access the value of a variable which's name you need to build, you can use the v argument type: \tl_set:Nv \l_cyker_vara_tl { l_cyker_varname_tl }.
    – Skillmon
    Jun 29, 2020 at 17:35
  • I know that module name thing but I think it's too heavy for a small example here. In fact interface3 also uses simple variable names like \l_mya_tl. Isn't that more readable?
    – Cyker
    Jun 29, 2020 at 17:43
  • no your example is much less readable. In expl3 you can see if a variable is local or global by looking at the begin, you can see if something is a tl or clist by looking at the end, and you can see what is a function (by looking for a colon) and how many arguments it has. All this is missing in your example. Jun 29, 2020 at 17:47
  • @UlrikeFischer There it is. Does this look good to you now?
    – Cyker
    Jun 29, 2020 at 17:59

1 Answer 1


You should conform to the naming scheme. Really, I mean it.

You seem to be wanting something like

\tl_new:N \l_cyker_vara_tl
\tl_new:N \l_cyker_varb_tl
\tl_new:N \l_cyker_varname_tl

\tl_set:Nn \l_cyker_vara_tl { something }
\tl_set:Nn \l_cyker_varname_tl { vara }

\tl_set:Nv \l_cyker_varb_tl { l_cyker_ \l_cyker_varname_tl _tl }

This will set \l_cyker_varb_tl to something, because the v variant first builds a token (using \csname...\endcsname), then uses V, so you get

\tl_set:NV \l_cyker_varb_tl \l_cyker_vara_tl

which does the final assignments of the contents of \l_cyker_vara_tl to \l_cyker_varb_tl.

  • \module_myfunc:N \l_module_vara_tl and \module_myfunc:N \l_module_varb_tl are not the same if the function \module_myfunc:N contains \cs_to_str:N. So the code will fail if the function checks csname.
    – Cyker
    Jun 29, 2020 at 18:14
  • And what is the difference between \tl_set:NV and \tl_set_eq:NN then?
    – Cyker
    Jun 29, 2020 at 18:20
  • The tricky thing is how to produce \l_module_var_tl on the input stream using \l_module_varname_tl, so that that the function takes as input exactly this variable not another variable with the same content.
    – Cyker
    Jun 29, 2020 at 18:25
  • @Cyker Not much difference, actually. I can't understand your last comment, sorry.
    – egreg
    Jun 29, 2020 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.