summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-07-20 22:14:30 +0000
committerKarl Berry <karl@freefriends.org>2014-07-20 22:14:30 +0000
commit6c2678db440b5260ec13602bde6efebdd00f8549 (patch)
treeed93fc7244f4e5ef1baf86ccb157597dabf6ac1e /Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
parent9790eead4cceaffc951c93887d06de70c02e196a (diff)
l3
git-svn-id: svn://tug.org/texlive/trunk@34671 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3seq.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3seq.dtx190
1 files changed, 189 insertions, 1 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
index 6924433ab00..813aee51c33 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
@@ -37,7 +37,7 @@
\documentclass[full]{l3doc}
%</driver>
%<*driver|package>
-\GetIdInfo$Id: l3seq.dtx 4712 2014-04-30 08:17:49Z joseph $
+\GetIdInfo$Id: l3seq.dtx 5232 2014-07-18 19:32:54Z joseph $
{L3 Sequences and stacks}
%</driver|package>
%<*driver>
@@ -116,6 +116,22 @@
% \meta{sequence_2}.
% \end{function}
%
+% \begin{function}[added = 2014-07-17]
+% {
+% \seq_set_from_clist:NN, \seq_set_from_clist:cN,
+% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
+% \seq_set_from_clist:Nn, \seq_set_from_clist:cn,
+% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
+% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
+% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
+% }
+% \begin{syntax}
+% \cs{seq_set_from_clist:NN} \meta{sequence} \meta{comma-list}
+% \end{syntax}
+% Converts the data in the \meta{comma list} into a \meta{sequence}:
+% the original \meta{comma list} is unchanged.
+% \end{function}
+%
% \begin{function}[added = 2011-08-15, updated = 2012-07-02]
% {
% \seq_set_split:Nnn , \seq_set_split:NnV ,
@@ -273,6 +289,26 @@
% contain the special marker \cs{q_no_value}.
% \end{function}
%
+% \begin{function}[added = 2014-07-17, EXP]{\seq_item:Nn, \seq_item:cn}
+% \begin{syntax}
+% \cs{seq_item:Nn} \meta{sequence} \Arg{integer expression}
+% \end{syntax}
+% Indexing items in the \meta{sequence} from~$1$ at the top (left), this
+% function will evaluate the \meta{integer expression} and leave the
+% appropriate item from the sequence in the input stream. If the
+% \meta{integer expression} is negative, indexing occurs from the
+% bottom (right) of the sequence. When the \meta{integer expression}
+% is larger than the number of items in the \meta{sequence} (as
+% calculated by \cs{seq_count:N}) then the function will expand to
+% nothing.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{item}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
% \section{Recovering values from sequences with branching}
%
% The functions in this section combine tests for non-empty sequences
@@ -407,6 +443,18 @@
% \cs{tl_if_eq:nn(TF)}.
% \end{function}
%
+%
+% \begin{function}[added = 2014-07-18]^^A
+% {^^A
+% \seq_reverse:N, \seq_reverse:c,
+% \seq_greverse:N, \seq_greverse:c
+% }
+% \begin{syntax}
+% \cs{seq_reverse:N} \meta{sequence}
+% \end{syntax}
+% Reverses the order of the items stored in the \meta{sequence}.
+% \end{function}
+%
% \section{Sequence conditionals}
%
% \begin{function}[EXP,pTF]{\seq_if_empty:N, \seq_if_empty:c}
@@ -885,6 +933,51 @@
%
% \begin{macro}
% {
+% \seq_set_from_clist:NN, \seq_set_from_clist:cN,
+% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
+% \seq_set_from_clist:Nn, \seq_set_from_clist:cn
+% }
+% \begin{macro}
+% {
+% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
+% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
+% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
+% }
+% Setting a sequence from a comma-separated list is done using a simple
+% mapping.
+% \begin{macrocode}
+\cs_new_protected:Npn \seq_set_from_clist:NN #1#2
+ {
+ \tl_set:Nx #1
+ { \s_@@ \clist_map_function:NN #2 \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_set_from_clist:Nn #1#2
+ {
+ \tl_set:Nx #1
+ { \s_@@ \clist_map_function:nN {#2} \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_gset_from_clist:NN #1#2
+ {
+ \tl_gset:Nx #1
+ { \s_@@ \clist_map_function:NN #2 \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_gset_from_clist:Nn #1#2
+ {
+ \tl_gset:Nx #1
+ { \s_@@ \clist_map_function:nN {#2} \@@_wrap_item:n }
+ }
+\cs_generate_variant:Nn \seq_set_from_clist:NN { Nc }
+\cs_generate_variant:Nn \seq_set_from_clist:NN { c , cc }
+\cs_generate_variant:Nn \seq_set_from_clist:Nn { c }
+\cs_generate_variant:Nn \seq_gset_from_clist:NN { Nc }
+\cs_generate_variant:Nn \seq_gset_from_clist:NN { c , cc }
+\cs_generate_variant:Nn \seq_gset_from_clist:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
% \seq_set_split:Nnn , \seq_set_split:NnV ,
% \seq_gset_split:Nnn, \seq_gset_split:NnV
% }
@@ -1155,6 +1248,65 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}
+% {\seq_reverse:N, \seq_reverse:c, \seq_greverse:N, \seq_greverse:c}
+% \begin{macro}[aux]{\@@_reverse:NN}
+% \begin{macro}[aux, EXP]{\@@_reverse_item:nwn}
+% Previously, \cs{seq_reverse:N} was coded by collecting the items
+% in reverse order after an \cs{exp_stop_f:} marker.
+% \begin{verbatim}
+% \cs_new_protected:Npn \seq_reverse:N #1
+% {
+% \cs_set_eq:NN \@@_item:n \@@_reverse_item:nw
+% \tl_set:Nf #2 { #2 \exp_stop_f: }
+% }
+% \cs_new:Npn \@@_reverse_item:nw #1 #2 \exp_stop_f:
+% {
+% #2 \exp_stop_f:
+% \@@_item:n {#1}
+% }
+% \end{verbatim}
+% At first, this seems optimal, since we can forget about each item
+% as soon as it is placed after \cs{exp_stop_f:}. Unfortunately,
+% \TeX{}'s usual tail recursion does not take place in this case:
+% since the following \cs{@@_reverse_item:nw} only reads
+% tokens until \cs{exp_stop_f:}, and never reads the
+% |\@@_item:n {#1}| left by the previous call, \TeX{} cannot
+% remove that previous call from the stack, and in particular
+% must retain the various macro parameters in memory, until the
+% end of the replacement text is reached. The stack is thus
+% only flushed after all the \cs{@@_reverse_item:nw} are
+% expanded. Keeping track of the arguments of all those calls
+% uses up a memory quadratic in the length of the sequence.
+% \TeX{} can then not cope with more than a few thousand items.
+%
+% Instead, we collect the items in the argument
+% of \cs{exp_not:n}. The previous calls are cleanly removed
+% from the stack, and the memory consumption becomes linear.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \seq_reverse:N
+ { \@@_reverse:NN \tl_set:Nx }
+\cs_new_protected_nopar:Npn \seq_greverse:N
+ { \@@_reverse:NN \tl_gset:Nx }
+\cs_new_protected:Npn \@@_reverse:NN #1 #2
+ {
+ \cs_set_eq:NN \@@_tmp:w \@@_item:n
+ \cs_set_eq:NN \@@_item:n \@@_reverse_item:nwn
+ #1 #2 { #2 \exp_not:n { } }
+ \cs_set_eq:NN \@@_item:n \@@_tmp:w
+ }
+\cs_new:Npn \@@_reverse_item:nwn #1 #2 \exp_not:n #3
+ {
+ #2
+ \exp_not:n { \@@_item:n {#1} #3 }
+ }
+\cs_generate_variant:Nn \seq_reverse:N { c }
+\cs_generate_variant:Nn \seq_greverse:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Sequence conditionals}
%
% \begin{macro}[pTF]{\seq_if_empty:N, \seq_if_empty:c}
@@ -1434,6 +1586,42 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\seq_item:Nn, \seq_item:cn}
+% \begin{macro}[aux]{\@@_item:wNn, \@@_item:nnn}
+% The idea here is to find the offset of the item from the left, then use
+% a loop to grab the correct item. If the resulting offset is too large,
+% then the stop code |{ ? \__prg_break: } { }| will be used by the auxiliary,
+% terminating the loop and returning nothing at all.
+% \begin{macrocode}
+\cs_new:Npn \seq_item:Nn #1
+ { \exp_after:wN \@@_item:wNn #1 \q_stop #1 }
+\cs_new:Npn \@@_item:wNn \s_@@ #1 \q_stop #2#3
+ {
+ \exp_args:Nf \@@_item:nnn
+ {
+ \int_eval:n
+ {
+ \int_compare:nNnT {#3} < \c_zero
+ { \seq_count:N #2 + \c_one + }
+ #3
+ }
+ }
+ #1
+ { ? \__prg_break: } { }
+ \__prg_break_point:
+ }
+\cs_new:Npn \@@_item:nnn #1#2#3
+ {
+ \use_none:n #2
+ \int_compare:nNnTF {#1} = \c_one
+ { \__prg_break:n { \exp_not:n {#3} } }
+ { \exp_args:Nf \@@_item:nnn { \int_eval:n { #1 - 1 } } }
+ }
+\cs_generate_variant:Nn \seq_item:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Mapping to sequences}
%
% \begin{macro}{\seq_map_break:}