Edit (by BLF): This has now been fixed: \tl_map_variable:nNn
and related functions leave the variable equal to the last item in the token list, rather than to a trailing marker.
\tl_map_variable:nNn
does not create a group level, so at the end of the code \l_foo_tl
contains the last token in the list, which is \q_recursion_tail
(which is inserted after your abc
to detect the end of the list). Then, when you do \tl_use:N \l_foo_tl
you expand \q_recursion_tail
, leading to infinite recursion.
\tl_map_variable:nNn
expands once to:
\__tl_map_variable:Nnn #2 {#3} #1 \q_recursion_tail
\prg_break_point:Nn \tl_map_break: { }
and the first thing \__tl_map_variable:Nnn
does is to assign the first item in #1
(which eventually ends up being \q_recursion_tail
) to #2
, which is your ⟨tl var⟩
. You should use another ⟨tl var⟩
to avoid that:
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\tl_new:N \l_foo_tl
\tl_new:N \l_bar_tl
\tl_set:Nn \l_foo_tl {x}
\tl_use:N \l_foo_tl
\tl_map_variable:nNn {abc} \l_bar_tl { \tl_use:N \l_bar_tl }
\tl_use:N \l_foo_tl
\ExplSyntaxOff
\end{document}
The documentation doesn't mention (not that I could find, at least), the contents and usability of the ⟨tl var⟩
after the end of \tl_map_variable:nNn
, so I don't know if this is by design or not.
However you can define a version of \tl_map_variable:nNn
which saves the value of ⟨tl var⟩
and restores it when the function ends:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_protected:Npn \siracusa_tl_map_variable:nNn #1#2
{
\exp_args:NV
\__siracusa_tl_map_variable:nnNn #2 {#1} #2
}
\cs_new_protected:Npn \__siracusa_tl_map_variable:nnNn #1#2#3#4
{
\tl_map_variable:nNn {#2} #3 {#4}
\tl_set:Nx #3 { \exp_not:n {#1} }
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\tl_new:N \l_foo_tl
\tl_set:Nn \l_foo_tl {x}
\tl_use:N \l_foo_tl
\siracusa_tl_map_variable:nNn {abc} \l_foo_tl { \tl_use:N \l_foo_tl }
\tl_use:N \l_foo_tl
\ExplSyntaxOff
\end{document}