
Estou procurando uma boa explicação sobre as diferenças e casos de uso entre o tl_map_function:nN
e tl_map_inline:Nn
. Eu forneço um MWE para o inline
que também parece ser o mais rápido.
\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}
Responder1
As funções \tl_map_function:nN
e \tl_map_function:NN
são totalmente expansíveis (com x
-expansão, não f
-expansão), enquanto a inline
versão não é.
A function
versão também é um pouco mais rápida.
Arquivo de exemplo
\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
versão
Esta é a resposta detime
real 0m4.635s
user 0m4.613s
sys 0m0.016s
e este é o relatório de memória
140188 words of memory out of 5000000
function
versão
Esta é a resposta detime
real 0m4.163s
user 0m4.139s
sys 0m0.020s
e este é o relatório de memória
140188 words of memory out of 5000000
O que deve ser preferido? Costumo considerar \tl_map_inline:nn
mais fácil, pois não exige a definição de uma nova função, mas quando o código fica complicado, a function
versão deve ser empregada para melhor clareza. Deve ser adotado sempre que o mapeamento a ser realizado utilizar uma função definida em outro lugar.
A inline
versão facilita a adição de pontos de interrupção; a function
versão precisa de uma função especialmente adaptada contendo \tl_map_break:
.
Além disso, a function
versão é um pouco mais complexa quando o mapeamento requer mais de um argumento (por exemplo, estamos em um mapeamento aninhado, usando tanto o item externo quanto o interno).