[latex3-commits] [git/latex3] sowreap: add \tl_sow:Nn / \tl_sow_reap:N & friends (377418f)
Will Robertson
wspr81 at gmail.com
Thu Jan 4 15:42:18 CET 2018
Repository : https://github.com/latex3/latex3
On branch : sowreap
Link : https://github.com/latex3/latex3/commit/377418fde60ae7dd7cf21ad5bd9a446523d2fd35
>---------------------------------------------------------------
commit 377418fde60ae7dd7cf21ad5bd9a446523d2fd35
Author: Will Robertson <wspr81 at gmail.com>
Date: Thu Jan 4 22:42:18 2018 +0800
add \tl_sow:Nn / \tl_sow_reap:N & friends
this was discussed, oh, ages ago. to be discussed about whether we actually want it!!
>---------------------------------------------------------------
377418fde60ae7dd7cf21ad5bd9a446523d2fd35
l3kernel/l3candidates.dtx | 163 ++++++++++++++++++++++++++++++++++++++++
l3kernel/testfiles/m3tl015.lvt | 163 ++++++++++++++++++++++++++++++++++++++++
l3kernel/testfiles/m3tl015.tlg | 100 ++++++++++++++++++++++++
3 files changed, 426 insertions(+)
diff --git a/l3kernel/l3candidates.dtx b/l3kernel/l3candidates.dtx
index 851b381..c038fcb 100644
--- a/l3kernel/l3candidates.dtx
+++ b/l3kernel/l3candidates.dtx
@@ -1067,6 +1067,42 @@
% \end{texnote}
% \end{function}
%
+
+% \begin{function}[added = 2018-01-04]{\tl_sow_prepare:N,\tl_sow:Nn,\tl_sow_reap:,\tl_gsow_prepare:N,\tl_gsow:Nn,\tl_gsow_greap:}
+% \begin{syntax}
+% \cs{tl_sow_prepare:N} \meta{tl var} \\
+% \cs{tl_sow:Nn} \meta{tl var} \Arg{tokens} \\
+% \cs{tl_sow_reap:N} \meta{tl var}
+% \end{syntax}
+% When building the contents of token list variables with multiple \cs{tl_put_right:Nn}
+% commands, performance can be poor when there are many iterations.
+% The \cs{tl_sow:Nn} and \cs{tl_sow_reap:N} commands provide a faster alternative
+% for large variable sizes at the expense of greater memory consumption and \TeX\ hash space.
+%
+% To start, `prepare' for the sowing to come:
+% \begin{verbatim}
+% \tl_sow_prepare:N \l_tmpa_tl
+% \end{verbatim}
+% This clears the token list variable and initialises internal variables.
+% Here, call \cs{tl_sow:Nn} as many times as necessary:
+% \begin{verbatim}
+% \tl_sow:Nn \l_tmpa_tl {tokens1}
+% \tl_sow:Nn \l_tmpa_tl {tokens2}
+% \tl_sow:Nn \l_tmpa_tl {tokens3}
+% \tl_sow:Nn \l_tmpa_tl {tokens4}
+% \end{verbatim}
+% At this point, the token list variable (here, \cs{l_tmpa_tl}) will be unchanged
+% from its original definition. Now `reap' the token list variable:
+% \begin{verbatim}
+% \tl_sow_reap:N \l_tmpa_tl
+% \end{verbatim}
+% This defines the token list variables as the concatenation of the tokens defined in each `sow' command.
+% To complete the example, the contents of \cs{l_tmpa_tl} are now:
+% \begin{verbatim}
+% tokens1tokens2tokens3tokens4
+% \end{verbatim}
+% \end{function}
+%
% \section{Additions to \pkg{l3token}}
%
% \begin{variable}[added = 2017-08-07]{\c_catcode_active_space_tl}
@@ -4277,6 +4313,133 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Sow/reap}
+%
+% This is a sketch of how sow/reap works:
+% \begin{verbatim}
+% \def\l_foo_1_tl{\unexpanded{sow1}}
+% \def\l_foo_2_tl{\unexpanded{sow2}}
+% % ...
+% \edef\foo{\l_foo_1_tl\l_foo_2_tl...}
+% \end{verbatim}
+% We use a variable-specific to keep track of as many sow/reap variables
+% as desired.
+%
+% Important question: after reaping, should we also zero all internal sow
+% tl variables? Would it help memory consumption in any meaningful way
+% or just slow things down a bit?
+%
+% Both local and global variantions are defined, and this is done manually
+% because there are too many different functions that need to be switched
+% between the cases.
+%
+% \begin{macro}{\__tl_sow_item:Nn,\__tl_gsow_item:Nn}
+% Helper variables for constructing \verb|c|-type arguments.
+% \begin{macrocode}
+\cs_new:Nn \__tl_sow_item:Nn { l___sow___ \token_to_str:N #1 ___ #2 ___tl }
+\cs_new:Nn \__tl_gsow_item:Nn { g___sow___ \token_to_str:N #1 ___ #2 ___tl }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\__tl_sow_int:N,\__tl_gsow_int:N}
+% Helper variables for constructing \verb|c|-type arguments.
+% \begin{macrocode}
+\cs_new:Nn \__tl_sow_int:N { l___sow___ \token_to_str:N #1 ___int }
+\cs_new:Nn \__tl_gsow_int:N { g___sow___ \token_to_str:N #1 ___int }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tl_sow_prepare:N,\tl_gsow_prepare:N}
+% \begin{macrocode}
+\cs_new:Nn \tl_sow_prepare:N
+ {
+ \tl_clear:N #1
+ \int_zero_new:c { \__tl_sow_int:N #1 }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn \tl_gsow_prepare:N
+ {
+ \tl_gclear:N #1
+ \int_gzero_new:c { \__tl_gsow_int:N #1 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tl_sow:Nn,\tl_gsow:Nn}
+% \begin{macrocode}
+\cs_new:Nn \tl_sow:Nn
+ {
+ \int_incr:c { \__tl_sow_int:N #1 }
+ \tl_clear_new:c
+ {
+ \__tl_sow_item:Nn #1
+ { \int_use:c { \__tl_sow_int:N #1 } }
+ }
+ \tl_set:cn
+ {
+ \__tl_sow_item:Nn #1
+ { \int_use:c { \__tl_sow_int:N #1 } }
+ }
+ { #2 }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn \tl_gsow:Nn
+ {
+ \int_gincr:c { \__tl_gsow_int:N #1 }
+ \tl_gclear_new:c
+ {
+ \__tl_gsow_item:Nn #1
+ { \int_use:c { \__tl_gsow_int:N #1 } }
+ }
+ \tl_gset:cn
+ {
+ \__tl_gsow_item:Nn #1
+ { \int_use:c { \__tl_gsow_int:N #1 } }
+ }
+ { #2 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tl_sow_reap:N,\tl_gsow_greap:N}
+% \begin{macrocode}
+\cs_new:Nn \tl_sow_reap:N
+ {
+ \cs_set:Npn \__tl_sow_tmp:n ##1
+ {
+ \exp_not:v { \__tl_sow_item:Nn #1 {##1} }
+ }
+ \tl_set:Nx #1
+ {
+ \int_step_function:nnnN {1} {1}
+ { \int_use:c { \__tl_sow_int:N #1 } }
+ \__tl_sow_tmp:n
+ }
+
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn \tl_gsow_greap:N
+ {
+ \cs_set:Npn \__tl_sow_tmp:n ##1
+ {
+ \exp_not:v { \__tl_gsow_item:Nn #1 {##1} }
+ }
+ \tl_gset:Nx #1
+ {
+ \int_step_function:nnnN {1} {1}
+ { \int_use:c { \__tl_gsow_int:N #1 } }
+ \__tl_sow_tmp:n
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{Additions to \pkg{l3token}}
%
% \begin{variable}{\c_catcode_active_space_tl}
diff --git a/l3kernel/testfiles/m3tl015.lvt b/l3kernel/testfiles/m3tl015.lvt
new file mode 100644
index 0000000..a1882f9
--- /dev/null
+++ b/l3kernel/testfiles/m3tl015.lvt
@@ -0,0 +1,163 @@
+%
+% Copyright (C) 2012,2015 The LaTeX3 Project
+%
+\documentclass{minimal}
+\input{regression-test}
+\RequirePackage[check-declarations,log-functions]{expl3}
+
+\begin{document}
+
+\START
+\AUTHOR{Will Robertson}
+\ExplSyntaxOn
+
+\tl_new:N \l_A_tl \tl_set:Nn \l_A_tl { Abc }
+\tl_new:N \l_B_tl \tl_set:Nn \l_B_tl { Bcd }
+\tl_new:N \l_C_tl \tl_set:Nn \l_C_tl { Cde }
+\tl_new:N \g_A_tl \tl_gset:Nn \g_A_tl { Abc }
+\tl_new:N \g_B_tl \tl_gset:Nn \g_B_tl { Bcd }
+\tl_new:N \g_C_tl \tl_gset:Nn \g_C_tl { Cde }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~sow/reap }
+ {
+ {
+ \tl_sow_prepare:N \l_A_tl
+ \tl_log:N \l_A_tl
+ \tl_sow:Nn \l_A_tl {A1}
+ \tl_log:N \l_A_tl
+ \tl_sow:Nn \l_A_tl {A2}
+ \tl_sow:Nn \l_A_tl {A3}
+ \tl_sow:Nn \l_A_tl {A4}
+ \tl_sow_reap:N \l_A_tl
+ \tl_log:N \l_A_tl
+ }
+ \tl_log:N \l_A_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~gsow/reap }
+ {
+ {
+ \tl_gsow_prepare:N \g_A_tl
+ \tl_log:N \g_A_tl
+ \tl_gsow:Nn \g_A_tl {A1}
+ \tl_log:N \g_A_tl
+ \tl_gsow:Nn \g_A_tl {A2}
+ \tl_gsow:Nn \g_A_tl {A3}
+ \tl_gsow:Nn \g_A_tl {A4}
+ \tl_gsow_greap:N \g_A_tl
+ \tl_log:N \g_A_tl
+ }
+ \tl_log:N \g_A_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~gsow/reap~2 }
+ {
+ {
+ \tl_gsow_prepare:N \g_A_tl
+ \tl_log:N \g_A_tl
+ \tl_gsow:Nn \g_A_tl {A1}
+ \tl_log:N \g_A_tl
+ \tl_gsow:Nn \g_A_tl {A2}
+ \tl_gsow:Nn \g_A_tl {A3}
+ \tl_gsow:Nn \g_A_tl {A4}
+ }
+ \tl_gsow_greap:N \g_A_tl
+ \tl_log:N \g_A_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~sow/reap~interleaved }
+ {
+ {
+ \tl_sow_prepare:N \l_A_tl
+ \tl_sow_prepare:N \l_B_tl
+ \tl_log:N \l_A_tl
+ \tl_log:N \l_B_tl
+ \tl_sow:Nn \l_A_tl {A1}
+ \tl_sow:Nn \l_B_tl {B1}
+ \tl_sow:Nn \l_A_tl {A2}
+ \tl_sow:Nn \l_B_tl {B2}
+ \tl_sow:Nn \l_A_tl {A3}
+ \tl_sow:Nn \l_B_tl {B3}
+ \tl_sow_reap:N \l_A_tl
+ \tl_sow_reap:N \l_B_tl
+ \tl_log:N \l_A_tl
+ \tl_log:N \l_B_tl
+ }
+ \tl_log:N \l_A_tl
+ \tl_log:N \l_B_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~gsow/reap~interleaved }
+ {
+ {
+ \tl_gsow_prepare:N \g_A_tl
+ \tl_gsow_prepare:N \g_B_tl
+ \tl_log:N \g_A_tl
+ \tl_log:N \g_B_tl
+ \tl_gsow:Nn \g_A_tl {A1}
+ \tl_gsow:Nn \g_B_tl {B1}
+ \tl_gsow:Nn \g_A_tl {A2}
+ \tl_gsow:Nn \g_B_tl {B2}
+ \tl_gsow:Nn \g_A_tl {A3}
+ \tl_gsow:Nn \g_B_tl {B3}
+ \tl_gsow_greap:N \g_A_tl
+ \tl_gsow_greap:N \g_B_tl
+ \tl_log:N \g_A_tl
+ \tl_log:N \g_B_tl
+ }
+ \tl_log:N \g_A_tl
+ \tl_log:N \g_B_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~gsow/reap~interleaved~2 }
+ {
+ {
+ \tl_gsow_prepare:N \g_A_tl
+ \tl_gsow_prepare:N \g_B_tl
+ \tl_log:N \g_A_tl
+ \tl_log:N \g_B_tl
+ \tl_gsow:Nn \g_A_tl {A1}
+ \tl_gsow:Nn \g_B_tl {B1}
+ \tl_gsow:Nn \g_A_tl {A2}
+ \tl_gsow:Nn \g_B_tl {B2}
+ \tl_gsow:Nn \g_A_tl {A3}
+ \tl_gsow:Nn \g_B_tl {B3}
+ }
+ \tl_gsow_greap:N \g_A_tl
+ \tl_gsow_greap:N \g_B_tl
+ \tl_log:N \g_A_tl
+ \tl_log:N \g_B_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~sow/reap~empty }
+ {
+ {
+ \tl_sow_prepare:N \l_C_tl
+ \tl_log:N \l_C_tl
+ \tl_sow_reap:N \l_C_tl
+ \tl_log:N \l_C_tl
+ }
+ \tl_log:N \l_C_tl
+ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\TEST { tl~gsow/reap~empty }
+ {
+ {
+ \tl_gsow_prepare:N \g_C_tl
+ \tl_log:N \g_C_tl
+ \tl_gsow_greap:N \g_C_tl
+ \tl_log:N \g_C_tl
+ }
+ \tl_log:N \g_C_tl
+ }
+
+
+\END
diff --git a/l3kernel/testfiles/m3tl015.tlg b/l3kernel/testfiles/m3tl015.tlg
new file mode 100644
index 0000000..b3239de
--- /dev/null
+++ b/l3kernel/testfiles/m3tl015.tlg
@@ -0,0 +1,100 @@
+This is a generated file for the LaTeX (2e + expl3) validation system.
+Don't change this file in any respect.
+Author: Will Robertson
+Defining \l_A_tl on line ...
+Defining \l_B_tl on line ...
+Defining \l_C_tl on line ...
+Defining \g_A_tl on line ...
+Defining \g_B_tl on line ...
+Defining \g_C_tl on line ...
+============================================================
+TEST 1: tl sow/reap
+============================================================
+Defining \l___sow___\l_A_tl___int on line ...
+\l___sow___\l_A_tl___int=\count...
+> \l_A_tl=.
+Defining \l___sow___\l_A_tl___1___tl on line ...
+> \l_A_tl=.
+Defining \l___sow___\l_A_tl___2___tl on line ...
+Defining \l___sow___\l_A_tl___3___tl on line ...
+Defining \l___sow___\l_A_tl___4___tl on line ...
+> \l_A_tl=A1A2A3A4.
+> \l_A_tl=Abc.
+============================================================
+============================================================
+TEST 2: tl gsow/reap
+============================================================
+Defining \g___sow___\g_A_tl___int on line ...
+\g___sow___\g_A_tl___int=\count...
+> \g_A_tl=.
+Defining \g___sow___\g_A_tl___1___tl on line ...
+> \g_A_tl=.
+Defining \g___sow___\g_A_tl___2___tl on line ...
+Defining \g___sow___\g_A_tl___3___tl on line ...
+Defining \g___sow___\g_A_tl___4___tl on line ...
+> \g_A_tl=A1A2A3A4.
+> \g_A_tl=A1A2A3A4.
+============================================================
+============================================================
+TEST 3: tl gsow/reap 2
+============================================================
+> \g_A_tl=.
+> \g_A_tl=.
+> \g_A_tl=A1A2A3A4.
+============================================================
+============================================================
+TEST 4: tl sow/reap interleaved
+============================================================
+Defining \l___sow___\l_B_tl___int on line ...
+\l___sow___\l_B_tl___int=\count...
+> \l_A_tl=.
+> \l_B_tl=.
+Defining \l___sow___\l_B_tl___1___tl on line ...
+Defining \l___sow___\l_B_tl___2___tl on line ...
+Defining \l___sow___\l_B_tl___3___tl on line ...
+> \l_A_tl=A1A2A3.
+> \l_B_tl=B1B2B3.
+> \l_A_tl=Abc.
+> \l_B_tl=Bcd.
+============================================================
+============================================================
+TEST 5: tl gsow/reap interleaved
+============================================================
+Defining \g___sow___\g_B_tl___int on line ...
+\g___sow___\g_B_tl___int=\count...
+> \g_A_tl=.
+> \g_B_tl=.
+Defining \g___sow___\g_B_tl___1___tl on line ...
+Defining \g___sow___\g_B_tl___2___tl on line ...
+Defining \g___sow___\g_B_tl___3___tl on line ...
+> \g_A_tl=A1A2A3.
+> \g_B_tl=B1B2B3.
+> \g_A_tl=A1A2A3.
+> \g_B_tl=B1B2B3.
+============================================================
+============================================================
+TEST 6: tl gsow/reap interleaved 2
+============================================================
+> \g_A_tl=.
+> \g_B_tl=.
+> \g_A_tl=A1A2A3.
+> \g_B_tl=B1B2B3.
+============================================================
+============================================================
+TEST 7: tl sow/reap empty
+============================================================
+Defining \l___sow___\l_C_tl___int on line ...
+\l___sow___\l_C_tl___int=\count...
+> \l_C_tl=.
+> \l_C_tl=.
+> \l_C_tl=Cde.
+============================================================
+============================================================
+TEST 8: tl gsow/reap empty
+============================================================
+Defining \g___sow___\g_C_tl___int on line ...
+\g___sow___\g_C_tl___int=\count...
+> \g_C_tl=.
+> \g_C_tl=.
+> \g_C_tl=.
+============================================================
More information about the latex3-commits
mailing list