6

I am looking for a good explanation of the differences and use cases, between the tl_map_function:nN and tl_map_inline:Nn. I provide a MWE for the inline which also appears to be the fastest.

\documentclass{article}
\usepackage{expl3,xparse}

\begin{document}
\ExplSyntaxOn
\cs_new:Nn\whatever:n{..{#1}~}
\tl_new:N  \tl_phd_temp_a
\tl_new:N  \tl_phd_temp_b
\tl_new:N  \tl_phd_temp_c
\DeclareDocumentCommand\Test{ }
    {
       \tl_set:Nn  \tl_phd_temp_a {Yiannis Mary John}
       \tl_set:Nn  \tl_phd_temp_b {{Lazarides}{Lou}{Smith}}
       \tl_concat:NNN \tl_phd_temp_c \tl_phd_temp_a \tl_phd_temp_b
       \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
   }   
\ExplSyntaxOff 
\Test
\end{document}
3
  • I always thought the difference was expandability. With \tl_map_inline:Nn you have to define the function that everything is mapped onto. With \tl_map_function:NN you already have it defined, so it's expandable. And, the reason of \tl_map_inline:Nn is faster, I think, is that since it's not expandable, they don't care how to do the mapping, with map_function I guess they have to play a little more with the code so the map is expandable.
    – Manuel
    Commented May 1, 2015 at 18:37
  • My comment applies to seq_map, sorry for the confusion. In case of tl_map it seems that tl_map_inline defines first the function and then maps, while the other one just maps.
    – Manuel
    Commented May 2, 2015 at 13:00
  • @Manuel Thanks for the comments, just made me look at the code for both.
    – yannisl
    Commented May 2, 2015 at 13:02

1 Answer 1

2

The functions \tl_map_function:nN and \tl_map_function:NN are fully expandable (with x-expansion, not f-expansion), while the inline version aren't.

The function version is also slightly faster.

Example file

\documentclass{article}
\usepackage{expl3}

\begin{document}

\ExplSyntaxOn
\cs_new:Nn\whatever:n{}
\tl_new:N  \tl_phd_temp_a
\tl_new:N  \tl_phd_temp_b
\tl_new:N  \tl_phd_temp_c
\tl_set:Nn  \tl_phd_temp_a {Yiannis Mary John}
\tl_set:Nn  \tl_phd_temp_b {{Lazarides}{Lou}{Smith}}
\tl_concat:NNN \tl_phd_temp_c \tl_phd_temp_a \tl_phd_temp_b

\cs_new:Npn \xinline
 {
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
  \tl_map_inline:Nn\tl_phd_temp_c{\whatever:n{##1}}
 }
\cs_new:Npn \xfunction
 {
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
  \tl_map_function:NN\tl_phd_temp_c \whatever:n
 }

\cs_new:Npn \y #1
 {
  #1 #1 #1 #1 #1 #1 #1 #1 #1 #1
 }
\cs_new:Npn \z #1
 {
  \y{#1}\y{#1}\y{#1}\y{#1}\y{#1}
  \y{#1}\y{#1}\y{#1}\y{#1}\y{#1}
 }
\cs_new:Npn \zz #1
 {
  \z{#1}\z{#1}\z{#1}\z{#1}\z{#1}
  \z{#1}\z{#1}\z{#1}\z{#1}\z{#1}
 }
\cs_new:Npn \zzz #1
 {
  \zz{#1}\zz{#1}\zz{#1}\zz{#1}\zz{#1}
  \zz{#1}\zz{#1}\zz{#1}\zz{#1}\zz{#1}
 }

\ExplSyntaxOff

\zzz{\xinline}
%\zzz{\xfunction}

\stop

inline version

This is the response by time

real    0m4.635s
user    0m4.613s
sys     0m0.016s

and this is the memory report

 140188 words of memory out of 5000000

function version

This is the response by time

real    0m4.163s
user    0m4.139s
sys     0m0.020s

and this is the memory report

 140188 words of memory out of 5000000

What's to be preferred? I tend to consider \tl_map_inline:nn easier, because it doesn't require defining a new function, but when the code becomes complicated, the function version should be employed for better clarity. It should be adopted whenever the mapping to be performed uses a function defined elsewhere.

The inline version makes it easier to add break points; the function version needs a specially tailored function containing \tl_map_break:.

Also, the function version is a bit more complex when the mapping requires more than one argument (for instance we're in a nested mapping, using both the outer and the inner item).

1
  • Thanks for your fine answer. Personally I prefer the function style as it is nearer to the concept of callback in other languages.
    – yannisl
    Commented May 2, 2015 at 14:52

You must log in to answer this question.

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