diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3seq.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3seq.dtx | 192 |
1 files changed, 191 insertions, 1 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index e4aeffa83ff..d5d0a521460 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2023-05-05} +% \date{Released 2023-05-11} % % \maketitle % @@ -474,6 +474,24 @@ % \cs{tl_if_eq:nnTF}. % \end{function} % +% \begin{function}[added = 2021-04-29, noTF] +% {\seq_set_item:Nnn, \seq_set_item:cnn, \seq_gset_item:Nnn, \seq_gset_item:cnn} +% \begin{syntax} +% \cs{seq_set_item:Nnn} \meta{seq~var} \Arg{int expr} \Arg{item} +% \cs{seq_set_item:NnnTF} \meta{seq~var} \Arg{int expr} \Arg{item} \Arg{true code} \Arg{false code} +% \end{syntax} +% Removes the item of \meta{sequence} at the position given by +% evaluating the \meta{int expr} and replaces it by +% \meta{item}. Items are indexed from $1$ on the left/top of the +% \meta{sequence}, or from $-1$ on the right/bottom. If the +% \meta{int expr} is zero or is larger (in absolute value) +% than the number of items in the sequence, the \meta{sequence} is not +% modified. In these cases, \cs{seq_set_item:Nnn} raises an error +% while \cs{seq_set_item:NnnTF} runs the \meta{false code}. In cases +% where the assignment was successful, \meta{true code} is run +% afterwards. +% \end{function} +% % \begin{function}[added = 2014-07-18] % { % \seq_reverse:N, \seq_reverse:c, @@ -621,6 +639,24 @@ % and so on) as~|#1| and the \meta{item} as~|#2|. % \end{function} % +% \begin{function}[rEXP, added = 2023-05-10] +% { +% \seq_map_pairwise_function:NNN, \seq_map_pairwise_function:NcN, +% \seq_map_pairwise_function:cNN, \seq_map_pairwise_function:ccN +% } +% \begin{syntax} +% \cs{seq_map_pairwise_function:NNN} \meta{seq_1} \meta{seq_2} \meta{function} +% \end{syntax} +% Applies \meta{function} to every pair of items +% \meta{seq_1-item}--\meta{seq_2-item} from the two sequences, returning +% items from both sequences from left to right. The \meta{function} +% receives two \texttt{n}-type arguments for each iteration. The mapping +% terminates when +% the end of either sequence is reached (\emph{i.e.}~whichever sequence has +% fewer items determines how many iterations +% occur). +% \end{function} +% % \begin{function}[rEXP, updated = 2012-06-29]{\seq_map_break:} % \begin{syntax} % \cs{seq_map_break:} @@ -1513,6 +1549,113 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\@@_int_eval:w} +% Useful to more quickly go through items. +% \begin{macrocode} +\cs_new_eq:NN \@@_int_eval:w \tex_numexpr:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[noTF]{\seq_set_item:Nnn, \seq_set_item:cnn, \seq_gset_item:Nnn, \seq_gset_item:cnn} +% \begin{macro}{\@@_set_item:NnnNN, \@@_set_item:nnNNNN, \@@_set_item_false:nnNNNN, \@@_set_item:nNnnNNNN} +% \begin{macro}[rEXP]{\@@_set_item:wn, \@@_set_item_end:w} +% The conditionals are distinguished from the |Nnn| versions by the +% last argument \cs{use_ii:nn} vs \cs{use_i:nn}. +% \begin{macrocode} +\cs_new_protected:Npn \seq_set_item:Nnn #1#2#3 + { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_set:Nx \use_i:nn } +\cs_new_protected:Npn \seq_gset_item:Nnn #1#2#3 + { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_gset:Nx \use_i:nn } +\cs_generate_variant:Nn \seq_set_item:Nnn { c } +\cs_generate_variant:Nn \seq_gset_item:Nnn { c } +\prg_new_protected_conditional:Npnn \seq_set_item:Nnn #1#2#3 { TF , T , F } + { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_set:Nx \use_ii:nn } +\prg_new_protected_conditional:Npnn \seq_gset_item:Nnn #1#2#3 { TF , T , F } + { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_gset:Nx \use_ii:nn } +\prg_generate_conditional_variant:Nnn \seq_set_item:Nnn { c } { TF , T , F } +\prg_generate_conditional_variant:Nnn \seq_gset_item:Nnn { c } { TF , T , F } +% \end{macrocode} +% Save the item to be stored and evaluate the position and the sequence +% length only once. Then depending on the sign of the position, check +% that it is not bigger than the length (in absolute value) nor zero. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_item:NnnNN #1#2#3 + { + \tl_set:Nn \l_@@_internal_a_tl { \@@_item:n {#3} } + \exp_args:Nff \@@_set_item:nnNNNN + { \int_eval:n {#2} } { \seq_count:N #1 } #1 \use_none:nn + } +\cs_new_protected:Npn \@@_set_item:nnNNNN #1#2 + { + \int_compare:nNnTF {#1} > 0 + { \int_compare:nNnF {#1} > {#2} { \@@_set_item:nNnnNNNN { #1 - 1 } } } + { + \int_compare:nNnF {#1} < {-#2} + { + \int_compare:nNnF {#1} = 0 + { \@@_set_item:nNnnNNNN { #2 + #1 } } + } + } + \@@_set_item_false:nnNNNN {#1} {#2} + } +% \end{macrocode} +% If the position is not ok, \cs{@@_set_item_false:nnNNNN} calls an +% error or returns \texttt{false} (depending on the \cs{use_i:nn} vs +% \cs{use_ii:nn} argument mentioned above). +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_item_false:nnNNNN #1#2#3#4#5#6 + { + #6 + { + \msg_error:nnxxx { seq } { item-too-large } + { \token_to_str:N #3 } {#2} {#1} + } + { \prg_return_false: } + } +% \end{macrocode} +% If the position is ok, \cs{@@_set_item:nNnnNNNN} makes the assignment +% and returns \texttt{true} (in the case of conditionnals). Here |#1| +% is an integer expression (position minus one), it needs to be +% evaluated. The sequence |#5| starts with \cs{s_@@} (even if empty), +% which stops the integer expression and is absorbed by it. The +% \cs{if_meaning:w} test is slightly faster than an integer test (but +% only works when testing against zero, hence the offset we chose in +% the position). When we are done skipping items, insert the saved +% item \cs{l_@@_internal_a_tl}. For |put| functions the last argument +% of \cs{@@_set_item_end:w} is \cs{use_none:nn} and it absorbs the +% item |#2| that we are removing: this is only useful for the |pop| +% functions. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_item:nNnnNNNN #1#2#3#4#5#6#7#8 + { + #7 #5 + { + \s_@@ + \exp_after:wN \@@_set_item:wn + \int_value:w \@@_int_eval:w #1 + #5 \s_@@_stop #6 + } + #8 { } { \prg_return_true: } + } +\cs_new:Npn \@@_set_item:wn #1 \@@_item:n #2 + { + \if_meaning:w 0 #1 \@@_set_item_end:w \fi: + \exp_not:n { \@@_item:n {#2} } + \exp_after:wN \@@_set_item:wn + \int_value:w \@@_int_eval:w #1 - 1 \s_@@ + } +\cs_new:Npn \@@_set_item_end:w #1 \exp_not:n #2 #3 \s_@@ #4 \s_@@_stop #5 + { + #1 + \exp_not:o \l_@@_internal_a_tl + \exp_not:n {#4} + #5 #2 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro} % {\seq_reverse:N, \seq_reverse:c, \seq_greverse:N, \seq_greverse:c} % \begin{macro}{\@@_reverse:NN} @@ -2160,6 +2303,53 @@ % \end{macrocode} % \end{macro} % +% \begin{macro} +% { +% \seq_map_pairwise_function:NNN, \seq_map_pairwise_function:NcN, +% \seq_map_pairwise_function:cNN, \seq_map_pairwise_function:ccN +% } +% \begin{macro} +% { +% \@@_map_pairwise_function:wNN, \@@_map_pairwise_function:wNw, +% \@@_map_pairwise_function:Nnnwnn +% } +% The idea is to first expand both sequences, adding the +% usual |{ ? \prg_break: } { }| to the end of each one. This is +% most conveniently done in two steps using an auxiliary function. +% The mapping then throws away the first tokens of |#2| and |#5|, +% which for items in both sequences are \cs{s_@@} +% \cs{@@_item:n}. The function to be mapped are then be applied to +% the two entries. When the code hits the end of one of the +% sequences, the break material stops the entire loop and tidy up. +% This avoids needing to find the count of the two sequences, or +% worrying about which is longer. +% \begin{macrocode} +\cs_new:Npn \seq_map_pairwise_function:NNN #1#2#3 + { \exp_after:wN \@@_map_pairwise_function:wNN #2 \s_@@_stop #1 #3 } +\cs_new:Npn \@@_map_pairwise_function:wNN \s_@@ #1 \s_@@_stop #2#3 + { + \exp_after:wN \@@_map_pairwise_function:wNw #2 \s_@@_stop #3 + #1 { ? \prg_break: } { } + \prg_break_point: + } +\cs_new:Npn \@@_map_pairwise_function:wNw \s_@@ #1 \s_@@_stop #2 + { + \@@_map_pairwise_function:Nnnwnn #2 + #1 { ? \prg_break: } { } + \s_@@_stop + } +\cs_new:Npn \@@_map_pairwise_function:Nnnwnn #1#2#3#4 \s_@@_stop #5#6 + { + \use_none:n #2 + \use_none:n #5 + #1 {#3} {#6} + \@@_map_pairwise_function:Nnnwnn #1 #4 \s_@@_stop + } +\cs_generate_variant:Nn \seq_map_pairwise_function:NNN { Nc , c , cc } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}{\seq_set_map_x:NNn, \seq_gset_map_x:NNn} % \begin{macro}{\@@_set_map_x:NNNn} % Very similar to \cs{seq_set_filter:NNn}. We could actually |