diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3seq.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3seq.dtx | 2681 |
1 files changed, 0 insertions, 2681 deletions
diff --git a/macros/latex/contrib/l3kernel/l3seq.dtx b/macros/latex/contrib/l3kernel/l3seq.dtx deleted file mode 100644 index 5334e8fd88..0000000000 --- a/macros/latex/contrib/l3kernel/l3seq.dtx +++ /dev/null @@ -1,2681 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3seq.dtx -% -% Copyright (C) 1990-2024 The LaTeX Project -% -% It may be distributed and/or modified under the conditions of the -% LaTeX Project Public License (LPPL), either version 1.3c of this -% license or (at your option) any later version. The latest version -% of this license is in the file -% -% https://www.latex-project.org/lppl.txt -% -% This file is part of the "l3kernel bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -%</driver> -% \fi -% -% \title{^^A -% The \pkg{l3seq} module\\ Sequences and stacks^^A -% } -% -% \author{^^A -% The \LaTeX{} Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% -% \date{Released 2024-03-14} -% -% \maketitle -% -% \begin{documentation} -% -% \LaTeX3 implements a \enquote{sequence} data type, which contain -% an ordered list of entries which may contain any \meta{balanced text}. -% It is possible to map functions to sequences such that the function -% is applied to every item in the sequence. -% -% Sequences are also used to implement stack functions in \LaTeX3. This -% is achieved using a number of dedicated stack functions. -% -% \section{Creating and initialising sequences} -% -% \begin{function}{\seq_new:N, \seq_new:c} -% \begin{syntax} -% \cs{seq_new:N} \meta{seq~var} -% \end{syntax} -% Creates a new \meta{seq~var} or raises an error if the name is -% already taken. The declaration is global. The \meta{seq~var} -% initially contains no items. -% \end{function} -% -% \begin{function}{\seq_clear:N, \seq_clear:c, \seq_gclear:N, \seq_gclear:c} -% \begin{syntax} -% \cs{seq_clear:N} \meta{seq~var} -% \end{syntax} -% Clears all items from the \meta{seq~var}. -% \end{function} -% -% \begin{function} -% {\seq_clear_new:N, \seq_clear_new:c, \seq_gclear_new:N, \seq_gclear_new:c} -% \begin{syntax} -% \cs{seq_clear_new:N} \meta{seq~var} -% \end{syntax} -% Ensures that the \meta{seq~var} exists globally by applying -% \cs{seq_new:N} if necessary, then applies -% \cs[index=seq_clear:N]{seq_(g)clear:N} to leave -% the \meta{seq~var} empty. -% \end{function} -% -% \begin{function} -% { -% \seq_set_eq:NN, \seq_set_eq:cN, \seq_set_eq:Nc, \seq_set_eq:cc, -% \seq_gset_eq:NN, \seq_gset_eq:cN, \seq_gset_eq:Nc, \seq_gset_eq:cc -% } -% \begin{syntax} -% \cs{seq_set_eq:NN} \meta{seq~var_1} \meta{seq~var_2} -% \end{syntax} -% Sets the content of \meta{seq~var_1} equal to that of -% \meta{seq~var_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{seq~var} \meta{comma-list} -% \end{syntax} -% Converts the data in the \meta{comma list} into a \meta{seq~var}: -% the original \meta{comma list} is unchanged. -% \end{function} -% -% \begin{function}[added = 2017-11-28] -% {\seq_const_from_clist:Nn, \seq_const_from_clist:cn} -% \begin{syntax} -% \cs{seq_const_from_clist:Nn} \meta{seq~var} \Arg{comma-list} -% \end{syntax} -% Creates a new constant \meta{seq~var} or raises an error if the name -% is already taken. The \meta{seq~var} is set globally to contain the -% items in the \meta{comma list}. -% \end{function} -% -% \begin{function}[added = 2011-08-15, updated = 2012-07-02] -% { -% \seq_set_split:Nnn , -% \seq_set_split:NVn , \seq_set_split:NnV , \seq_set_split:NVV , -% \seq_set_split:Nne , \seq_set_split:Nee , -% \seq_gset_split:Nnn, -% \seq_gset_split:NVn , \seq_gset_split:NnV, \seq_gset_split:NVV, -% \seq_gset_split:Nne , \seq_gset_split:Nee -% } -% \begin{syntax} -% \cs{seq_set_split:Nnn} \meta{seq~var} \Arg{delimiter} \Arg{token list} -% \end{syntax} -% Splits the \meta{token list} into \meta{items} separated -% by \meta{delimiter}, and assigns the result to the \meta{seq~var}. -% Spaces on both sides of each \meta{item} are ignored, -% then one set of outer braces is removed (if any); -% this space trimming behaviour is identical to that of -% \pkg{l3clist} functions. Empty \meta{items} are preserved by -% \cs{seq_set_split:Nnn}, and can be removed afterwards using -% \cs{seq_remove_all:Nn} \meta{seq~var} |{}|. -% The \meta{delimiter} may not contain |{|, |}| or |#| -% (assuming \TeX{}'s normal category code r\'egime). -% If the \meta{delimiter} is empty, the \meta{token list} is split -% into \meta{items} as a \meta{token list}. -% See also \cs{seq_set_split_keep_spaces:Nnn}, which omits space stripping. -% \end{function} -% -% \begin{function}[added = 2021-03-24] -% { -% \seq_set_split_keep_spaces:Nnn , \seq_set_split_keep_spaces:NnV , -% \seq_gset_split_keep_spaces:Nnn, \seq_gset_split_keep_spaces:NnV -% } -% \begin{syntax} -% \cs{seq_set_split_keep_spaces:Nnn} \meta{seq~var} \Arg{delimiter} \Arg{token list} -% \end{syntax} -% Splits the \meta{token list} into \meta{items} separated -% by \meta{delimiter}, and assigns the result to the \meta{seq~var}. -% One set of outer braces is removed (if any) but any surrounding spaces -% are retained: any braces \emph{inside} one or more spaces are -% therefore kept. Empty \meta{items} are preserved by -% \cs{seq_set_split_keep_spaces:Nnn}, and can be removed afterwards using -% \cs{seq_remove_all:Nn} \meta{seq~var} |{}|. -% The \meta{delimiter} may not contain |{|, |}| or |#| -% (assuming \TeX{}'s normal category code r\'egime). -% If the \meta{delimiter} is empty, the \meta{token list} is split -% into \meta{items} as a \meta{token list}. -% See also \cs{seq_set_split:Nnn}, which removes spaces around the delimiters. -% \end{function} -% -% \begin{function}[added = 2012-06-15] -% {\seq_set_filter:NNn, \seq_gset_filter:NNn} -% \begin{syntax} -% \cs{seq_set_filter:NNn} \meta{seq~var_1} \meta{seq~var_2} \Arg{inline boolexpr} -% \end{syntax} -% Evaluates the \meta{inline boolexpr} for every \meta{item} stored -% within the \meta{seq~var_2}. The \meta{inline boolexpr} -% receives the \meta{item} as |#1|. The sequence of all \meta{items} -% for which the \meta{inline boolexpr} evaluated to \texttt{true} -% is assigned to \meta{seq~var_1}. -% \begin{texnote} -% Contrarily to other mapping functions, \cs{seq_map_break:} cannot -% be used in this function, and would lead to low-level \TeX{} errors. -% \end{texnote} -% \end{function} -% -% \begin{function} -% {\seq_concat:NNN, \seq_concat:ccc, \seq_gconcat:NNN, \seq_gconcat:ccc} -% \begin{syntax} -% \cs{seq_concat:NNN} \meta{seq~var_1} \meta{seq~var_2} \meta{seq~var_3} -% \end{syntax} -% Concatenates the content of \meta{seq~var_2} and \meta{seq~var_3} -% together and saves the result in \meta{seq~var_1}. The items in -% \meta{seq~var_2} are placed at the left side of the new sequence. -% \end{function} -% -% \begin{function}[EXP, pTF, added=2012-03-03] -% {\seq_if_exist:N, \seq_if_exist:c} -% \begin{syntax} -% \cs{seq_if_exist_p:N} \meta{seq~var} -% \cs{seq_if_exist:NTF} \meta{seq~var} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests whether the \meta{seq~var} is currently defined. This does not -% check that the \meta{seq~var} really is a sequence variable. -% \end{function} -% -% \section{Appending data to sequences} -% -% \begin{function}{ -% \seq_put_left:Nn, \seq_put_left:NV, \seq_put_left:Nv, \seq_put_left:Ne, -% \seq_put_left:No, -% \seq_put_left:cn, \seq_put_left:cV, \seq_put_left:cv, \seq_put_left:ce, -% \seq_put_left:co, -% \seq_gput_left:Nn, \seq_gput_left:NV, \seq_gput_left:Nv, \seq_gput_left:Ne, -% \seq_gput_left:No, -% \seq_gput_left:cn, \seq_gput_left:cV, \seq_gput_left:cv, \seq_gput_left:ce, -% \seq_gput_left:co -% } -% \begin{syntax} -% \cs{seq_put_left:Nn} \meta{seq~var} \Arg{item} -% \end{syntax} -% Appends the \meta{item} to the left of the \meta{seq~var}. -% \end{function} -% -% \begin{function}{ -% \seq_put_right:Nn, \seq_put_right:NV, \seq_put_right:Nv, \seq_put_right:Ne, -% \seq_put_right:No, -% \seq_put_right:cn, \seq_put_right:cV, \seq_put_right:cv, \seq_put_right:ce, -% \seq_put_right:co, -% \seq_gput_right:Nn, \seq_gput_right:NV, \seq_gput_right:Nv, \seq_gput_right:Ne, -% \seq_gput_right:No, -% \seq_gput_right:cn, \seq_gput_right:cV, \seq_gput_right:cv, \seq_gput_right:ce, -% \seq_gput_right:co, -% } -% \begin{syntax} -% \cs{seq_put_right:Nn} \meta{seq~var} \Arg{item} -% \end{syntax} -% Appends the \meta{item} to the right of the \meta{seq~var}. -% \end{function} -% -% \section{Recovering items from sequences} -% -% Items can be recovered from either the left or the right of sequences. -% For implementation reasons, the actions at the left of the sequence are -% faster than those acting on the right. These functions all assign the -% recovered material locally, \emph{i.e.}~setting the -% \meta{token list variable} used with \cs{tl_set:Nn} and \emph{never} -% \cs{tl_gset:Nn}. -% -% \begin{function}[updated = 2012-05-14]{\seq_get_left:NN, \seq_get_left:cN} -% \begin{syntax} -% \cs{seq_get_left:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Stores the left-most item from a \meta{seq~var} in the -% \meta{token list variable} without removing it from the -% \meta{seq~var}. The \meta{token list variable} is assigned locally. -% If \meta{seq~var} is empty the \meta{token list variable} -% is set to the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-19]{\seq_get_right:NN, \seq_get_right:cN} -% \begin{syntax} -% \cs{seq_get_right:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Stores the right-most item from a \meta{seq~var} in the -% \meta{token list variable} without removing it from the -% \meta{seq~var}. The \meta{token list variable} is assigned locally. -% If \meta{seq~var} is empty the \meta{token list variable} -% is set to the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-14]{\seq_pop_left:NN, \seq_pop_left:cN} -% \begin{syntax} -% \cs{seq_pop_left:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the left-most item from a \meta{seq~var} into the -% \meta{token list variable}, \emph{i.e.}~removes the item from the -% sequence and stores it in the \meta{token list variable}. -% Both of the variables are assigned locally. If \meta{seq~var} is -% empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-14]{\seq_gpop_left:NN, \seq_gpop_left:cN} -% \begin{syntax} -% \cs{seq_gpop_left:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the left-most item from a \meta{seq~var} into the -% \meta{token list variable}, \emph{i.e.}~removes the item from the -% sequence and stores it in the \meta{token list variable}. -% The \meta{seq~var} is modified globally, while the assignment of -% the \meta{token list variable} is local. -% If \meta{seq~var} is empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-19]{\seq_pop_right:NN, \seq_pop_right:cN} -% \begin{syntax} -% \cs{seq_pop_right:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the right-most item from a \meta{seq~var} into the -% \meta{token list variable}, \emph{i.e.}~removes the item from the -% sequence and stores it in the \meta{token list variable}. -% Both of the variables are assigned locally. If \meta{seq~var} is -% empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-19]{\seq_gpop_right:NN, \seq_gpop_right:cN} -% \begin{syntax} -% \cs{seq_gpop_right:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the right-most item from a \meta{seq~var} into the -% \meta{token list variable}, \emph{i.e.}~removes the item from the -% sequence and stores it in the \meta{token list variable}. -% The \meta{seq~var} is modified globally, while the assignment of -% the \meta{token list variable} is local. -% If \meta{seq~var} is empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[added = 2014-07-17, EXP] -% { -% \seq_item:Nn, \seq_item:NV, \seq_item:Ne, -% \seq_item:cn, \seq_item:cV, \seq_item:ce -% } -% \begin{syntax} -% \cs{seq_item:Nn} \meta{seq~var} \Arg{integer expression} -% \end{syntax} -% Indexing items in the \meta{seq~var} from~$1$ at the top (left), this -% function evaluates the \meta{integer expression} and leaves 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. If the \meta{integer expression} -% is larger than the number of items in the \meta{seq~var} (as -% calculated by \cs{seq_count:N}) then the function expands to -% nothing. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the \meta{item} -% does not expand further when appearing in an \texttt{e}-type -% or \texttt{x}-type argument expansion. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP, added = 2016-12-06]{\seq_rand_item:N, \seq_rand_item:c} -% \begin{syntax} -% \cs{seq_rand_item:N} \meta{seq~var} -% \end{syntax} -% Selects a pseudo-random item of the \meta{seq~var}. If the -% \meta{seq~var} is empty the result is empty. -% This is not available in older versions of \XeTeX{}. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the \meta{item} -% does not expand further when appearing in an \texttt{e}-type -% or \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 -% with recovery of an item from the sequence. They offer increased readability -% and performance over separate testing and recovery phases. -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19] -% {\seq_get_left:NN, \seq_get_left:cN} -% \begin{syntax} -% \cs{seq_get_left:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, stores the left-most item from the -% \meta{seq~var} -% in the \meta{token list variable} without removing it from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% The \meta{token list variable} is assigned locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-19] -% {\seq_get_right:NN, \seq_get_right:cN} -% \begin{syntax} -% \cs{seq_get_right:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, stores the right-most item from the -% \meta{seq~var} -% in the \meta{token list variable} without removing it from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% The \meta{token list variable} is assigned locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19] -% {\seq_pop_left:NN, \seq_pop_left:cN} -% \begin{syntax} -% \cs{seq_pop_left:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the left-most item from the -% \meta{seq~var} -% in the \meta{token list variable}, \emph{i.e.}~removes the item from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% Both the \meta{seq~var} and the \meta{token list variable} are assigned -% locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19] -% {\seq_gpop_left:NN, \seq_gpop_left:cN} -% \begin{syntax} -% \cs{seq_gpop_left:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the left-most item from the \meta{seq~var} -% in the \meta{token list variable}, \emph{i.e.}~removes the item from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% The \meta{seq~var} is modified globally, while the \meta{token list variable} -% is assigned locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-19] -% {\seq_pop_right:NN, \seq_pop_right:cN} -% \begin{syntax} -% \cs{seq_pop_right:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the right-most item from the \meta{seq~var} -% in the \meta{token list variable}, \emph{i.e.}~removes the item from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% Both the \meta{seq~var} and the \meta{token list variable} are assigned -% locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-19] -% {\seq_gpop_right:NN, \seq_gpop_right:cN} -% \begin{syntax} -% \cs{seq_gpop_right:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the right-most item from the \meta{seq~var} -% in the \meta{token list variable}, \emph{i.e.}~removes the item from the -% \meta{seq~var}, then leaves the \meta{true code} in the input stream. -% The \meta{seq~var} is modified globally, while the -% \meta{token list variable} is assigned locally. -% \end{function} -% -% \section{Modifying sequences} -% -% While sequences are normally used as ordered lists, it may be -% necessary to modify the content. The functions here may be used -% to update sequences, while retaining the order of the unaffected -% entries. -% -% \begin{function} -% { -% \seq_remove_duplicates:N, \seq_remove_duplicates:c, -% \seq_gremove_duplicates:N, \seq_gremove_duplicates:c -% } -% \begin{syntax} -% \cs{seq_remove_duplicates:N} \meta{seq~var} -% \end{syntax} -% Removes duplicate items from the \meta{seq~var}, leaving the -% left most copy of each item in the \meta{seq~var}. The \meta{item} -% comparison takes place on a token basis, as for \cs{tl_if_eq:nnTF}. -% \begin{texnote} -% This function iterates through every item in the \meta{seq~var} and -% does a comparison with the \meta{items} already checked. It is therefore -% relatively slow with large sequences. -% \end{texnote} -% \end{function} -% -% \begin{function} -% { -% \seq_remove_all:Nn, \seq_remove_all:NV, \seq_remove_all:Ne, -% \seq_remove_all:cn, \seq_remove_all:cV, \seq_remove_all:ce, -% \seq_gremove_all:Nn, \seq_gremove_all:NV, \seq_gremove_all:Ne, -% \seq_gremove_all:cn, \seq_gremove_all:cV, \seq_gremove_all:ce -% } -% \begin{syntax} -% \cs{seq_remove_all:Nn} \meta{seq~var} \Arg{item} -% \end{syntax} -% Removes every occurrence of \meta{item} from the \meta{seq~var}. -% The \meta{item} comparison takes place on a token basis, as for -% \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{seq~var} 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{seq~var}, 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{seq~var} 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, -% \seq_greverse:N, \seq_greverse:c -% } -% \begin{syntax} -% \cs{seq_reverse:N} \meta{seq~var} -% \end{syntax} -% Reverses the order of the items stored in the \meta{seq~var}. -% \end{function} -% -% \begin{function}[added = 2017-02-06] -% {\seq_sort:Nn, \seq_sort:cn, \seq_gsort:Nn, \seq_gsort:cn} -% \begin{syntax} -% \cs{seq_sort:Nn} \meta{seq~var} \Arg{comparison code} -% \end{syntax} -% Sorts the items in the \meta{seq~var} according to the -% \meta{comparison code}, and assigns the result to -% \meta{seq~var}. The details of sorting comparison are -% described in Section~\ref{sec:l3sort:mech}. -% \end{function} -% -% \begin{function}[added = 2018-04-29] -% {\seq_shuffle:N, \seq_shuffle:c, \seq_gshuffle:N, \seq_gshuffle:c} -% \begin{syntax} -% \cs{seq_shuffle:N} \meta{seq~var} -% \end{syntax} -% Sets the \meta{seq~var} to the result of placing the items of the -% \meta{seq~var} in a random order. Each item is (roughly) as likely -% to end up in any given position. -% \begin{texnote} -% For sequences with more than $13$ items or so, only a small -% proportion of all possible permutations can be reached, because -% the random seed \cs{sys_rand_seed:} only has $28$-bits. The use -% of \tn{toks} internally means that sequences with more than -% $32767$ or $65535$ items (depending on the engine) cannot be -% shuffled. -% \end{texnote} -% \end{function} -% -% \section{Sequence conditionals} -% -% \begin{function}[EXP,pTF]{\seq_if_empty:N, \seq_if_empty:c} -% \begin{syntax} -% \cs{seq_if_empty_p:N} \meta{seq~var} -% \cs{seq_if_empty:NTF} \meta{seq~var} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{seq~var} is empty (containing no items). -% \end{function} -% -% \begin{function}[TF] -% { -% \seq_if_in:Nn, \seq_if_in:NV, \seq_if_in:Nv, \seq_if_in:Ne, -% \seq_if_in:No, -% \seq_if_in:cn, \seq_if_in:cV, \seq_if_in:cv, \seq_if_in:ce, -% \seq_if_in:co, -% } -% \begin{syntax} -% \cs{seq_if_in:NnTF} \meta{seq~var} \Arg{item} \Arg{true code} \Arg{false code} -% \end{syntax} -% Tests if the \meta{item} is present in the \meta{seq~var}. -% \end{function} -% -% \section{Mapping over sequences} -% -% All mappings are done at the current group level, \emph{i.e.}~any -% local assignments made by the \meta{function} or \meta{code} discussed -% below remain in effect after the loop. -% -% \begin{function}[rEXP, updated = 2012-06-29] -% {\seq_map_function:NN, \seq_map_function:cN} -% \begin{syntax} -% \cs{seq_map_function:NN} \meta{seq~var} \meta{function} -% \end{syntax} -% Applies \meta{function} to every \meta{item} stored in the -% \meta{seq~var}. The \meta{function} will receive one argument for -% each iteration. The \meta{items} are returned from left to right. -% To pass further arguments to the \meta{function}, see -% \cs{seq_map_tokens:Nn}. -% The function \cs{seq_map_inline:Nn} is faster than -% \cs{seq_map_function:NN} for sequences with more than about~$10$ -% items. -% \end{function} -% -% \begin{function}[updated = 2012-06-29] -% {\seq_map_inline:Nn, \seq_map_inline:cn} -% \begin{syntax} -% \cs{seq_map_inline:Nn} \meta{seq~var} \Arg{inline function} -% \end{syntax} -% Applies \meta{inline function} to every \meta{item} stored -% within the \meta{seq~var}. The \meta{inline function} should -% consist of code which will receive the \meta{item} as |#1|. -% The \meta{items} are returned from left to right. -% \end{function} -% -% \begin{function}[rEXP, added = 2019-08-30] -% {\seq_map_tokens:Nn, \seq_map_tokens:cn} -% \begin{syntax} -% \cs{seq_map_tokens:Nn} \meta{seq~var} \Arg{code} -% \end{syntax} -% Analogue of \cs{seq_map_function:NN} which maps several tokens -% instead of a single function. The \meta{code} receives each item in -% the \meta{seq~var} as a trailing brace group. For instance, -% \begin{verbatim} -% \seq_map_tokens:Nn \l_my_seq { \prg_replicate:nn { 2 } } -% \end{verbatim} -% expands to twice each item in the \meta{seq~var}: for each item in -% |\l_my_seq| the function \cs{prg_replicate:nn} receives |2| and -% \meta{item} as its two arguments. The function -% \cs{seq_map_inline:Nn} is typically faster but it is not expandable. -% \end{function} -% -% \begin{function}[updated = 2012-06-29] -% { -% \seq_map_variable:NNn, \seq_map_variable:Ncn, -% \seq_map_variable:cNn, \seq_map_variable:ccn -% } -% \begin{syntax} -% \cs{seq_map_variable:NNn} \meta{seq~var} \meta{variable} \Arg{code} -% \end{syntax} -% Stores each \meta{item} of the \meta{seq~var} in turn in the (token -% list) \meta{variable} and applies the \meta{code}. The \meta{code} -% will usually make use of the \meta{variable}, but this is not -% enforced. The assignments to the \meta{variable} are local. Its -% value after the loop is the last \meta{item} in the \meta{seq~var}, -% or its original value if the \meta{seq~var} is empty. The -% \meta{items} are returned from left to right. -% \end{function} -% -% \begin{function}[rEXP,added = 2018-05-03]{\seq_map_indexed_function:NN} -% \begin{syntax} -% \cs{seq_map_indexed_function:NN} \meta{seq~var} \meta{function} -% \end{syntax} -% Applies \meta{function} to every entry in the \meta{seq~var}. -% The \meta{function} should have signature |:nn|. It -% receives two arguments for each iteration: the \meta{index} (namely -% |1| for the first entry, then |2| and so on) and the \meta{item}. -% \end{function} -% -% \begin{function}[added = 2018-05-03]{\seq_map_indexed_inline:Nn} -% \begin{syntax} -% \cs{seq_map_indexed_inline:Nn} \meta{seq~var} \Arg{inline function} -% \end{syntax} -% Applies \meta{inline function} to every entry in the \meta{seq~var}. -% The \meta{inline function} should consist of code which -% receives the \meta{index} (namely |1| for the first entry, then |2| -% 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:} -% \end{syntax} -% Used to terminate a \cs[no-index]{seq_map_\ldots} function before all -% entries in the \meta{seq~var} have been processed. This -% normally takes place within a conditional statement, for example -% \begin{verbatim} -% \seq_map_inline:Nn \l_my_seq -% { -% \str_if_eq:nnTF { #1 } { bingo } -% { \seq_map_break: } -% { -% % Do something useful -% } -% } -% \end{verbatim} -% Use outside of a \cs[no-index]{seq_map_\ldots} scenario leads to low -% level \TeX{} errors. -% \begin{texnote} -% When the mapping is broken, additional tokens may be inserted -% before further items are taken -% from the input stream. This depends on the design of the mapping -% function. -% \end{texnote} -% \end{function} -% -% \begin{function}[rEXP, updated = 2012-06-29]{\seq_map_break:n} -% \begin{syntax} -% \cs{seq_map_break:n} \Arg{code} -% \end{syntax} -% Used to terminate a \cs[no-index]{seq_map_\ldots} function before all -% entries in the \meta{seq~var} have been processed, inserting -% the \meta{code} after the mapping has ended. This -% normally takes place within a conditional statement, for example -% \begin{verbatim} -% \seq_map_inline:Nn \l_my_seq -% { -% \str_if_eq:nnTF { #1 } { bingo } -% { \seq_map_break:n { <code> } } -% { -% % Do something useful -% } -% } -% \end{verbatim} -% Use outside of a \cs[no-index]{seq_map_\ldots} scenario leads to low -% level \TeX{} errors. -% \begin{texnote} -% When the mapping is broken, additional tokens may be inserted -% before the \meta{code} is -% inserted into the input stream. -% This depends on the design of the mapping function. -% \end{texnote} -% \end{function} -% -% \begin{function}[added = 2011-12-22, updated = 2020-07-16] -% {\seq_set_map:NNn, \seq_gset_map:NNn} -% \begin{syntax} -% \cs{seq_set_map:NNn} \meta{seq~var_1} \meta{seq~var_2} \Arg{inline function} -% \end{syntax} -% Applies \meta{inline function} to every \meta{item} stored -% within the \meta{seq~var_2}. The \meta{inline function} should -% consist of code which will receive the \meta{item} as |#1|. -% The sequence resulting applying \meta{inline function} to each -% \meta{item} is assigned to \meta{seq~var_1}. -% \begin{texnote} -% Contrarily to other mapping functions, \cs{seq_map_break:} cannot -% be used in this function, and would lead to low-level \TeX{} errors. -% \end{texnote} -% \end{function} -% -% \begin{function}[added = 2020-07-16, updated = 2023-10-26] -% {\seq_set_map_e:NNn, \seq_gset_map_e:NNn} -% \begin{syntax} -% \cs{seq_set_map_e:NNn} \meta{seq~var_1} \meta{seq~var_2} \Arg{inline function} -% \end{syntax} -% Applies \meta{inline function} to every \meta{item} stored -% within the \meta{seq~var_2}. The \meta{inline function} should -% consist of code which will receive the \meta{item} as |#1|. -% The sequence resulting from \texttt{e}-expanding -% \meta{inline function} applied to each \meta{item} -% is assigned to \meta{seq~var_1}. As such, the code -% in \meta{inline function} should be expandable. -% \begin{texnote} -% Contrarily to other mapping functions, \cs{seq_map_break:} cannot -% be used in this function, and would lead to low-level \TeX{} errors. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP, added = 2012-07-13]{\seq_count:N, \seq_count:c} -% \begin{syntax} -% \cs{seq_count:N} \meta{seq~var} -% \end{syntax} -% Leaves the number of items in the \meta{seq~var} in the input -% stream as an \meta{integer denotation}. The total number of items -% in a \meta{seq~var} includes those which are empty and duplicates, -% \emph{i.e.}~every item in a \meta{seq~var} is unique. -% \end{function} -% -% \section{Using the content of sequences directly} -% -% \begin{function}[EXP, added = 2013-05-26]{\seq_use:Nnnn, \seq_use:cnnn} -% \begin{syntax} -% \cs{seq_use:Nnnn} \meta{seq~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two} -% \end{syntax} -% Places the contents of the \meta{seq~var} in the input stream, with -% the appropriate \meta{separator} between the items. Namely, if the -% sequence has more than two items, the \meta{separator between more -% than two} is placed between each pair of items except the last, -% for which the \meta{separator between final two} is used. If the -% sequence has exactly two items, then they are placed in the input stream -% separated by the \meta{separator between two}. If the sequence has -% a single item, it is placed in the input stream, and an empty sequence -% produces no output. An error is raised if the variable does -% not exist or if it is invalid. -% -% For example, -% \begin{verbatim} -% \seq_set_split:Nnn \l_tmpa_seq { | } { a | b | c | {de} | f } -% \seq_use:Nnnn \l_tmpa_seq { ~and~ } { ,~ } { ,~and~ } -% \end{verbatim} -% inserts \enquote{\texttt{a, b, c, de, and f}} in the input -% stream. The first separator argument is not used in this case -% because the sequence has more than $2$ items. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the \meta{items} -% do not expand further when appearing in an \texttt{e}-type -% or \texttt{x}-type argument expansion. -% \end{texnote} -% \end{function} -% -% \begin{function}[EXP, added = 2013-05-26]{\seq_use:Nn, \seq_use:cn} -% \begin{syntax} -% \cs{seq_use:Nn} \meta{seq~var} \Arg{separator} -% \end{syntax} -% Places the contents of the \meta{seq~var} in the input stream, with -% the \meta{separator} between the items. If the sequence has -% a single item, it is placed in the input stream with no \meta{separator}, -% and an empty sequence produces no output. An error is raised if -% the variable does not exist or if it is invalid. -% -% For example, -% \begin{verbatim} -% \seq_set_split:Nnn \l_tmpa_seq { | } { a | b | c | {de} | f } -% \seq_use:Nn \l_tmpa_seq { ~and~ } -% \end{verbatim} -% inserts \enquote{\texttt{a and b and c and de and f}} in the input -% stream. -% \begin{texnote} -% The result is returned within the \tn{unexpanded} -% primitive (\cs{exp_not:n}), which means that the \meta{items} -% do not expand further when appearing in an \texttt{e}-type -% or \texttt{x}-type argument expansion. -% \end{texnote} -% \end{function} -% -% \section{Sequences as stacks} -% -% Sequences can be used as stacks, where data is pushed to and popped -% from the top of the sequence. (The left of a sequence is the top, for -% performance reasons.) The stack functions for sequences are not -% intended to be mixed with the general ordered data functions detailed -% in the previous section: a sequence should either be used as an -% ordered data type or as a stack, but not in both ways. -% -% \begin{function}[updated = 2012-05-14]{\seq_get:NN, \seq_get:cN} -% \begin{syntax} -% \cs{seq_get:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Reads the top item from a \meta{seq~var} into the -% \meta{token list variable} without removing it from the -% \meta{seq~var}. The \meta{token list variable} is assigned locally. -% If \meta{seq~var} is empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-14]{\seq_pop:NN, \seq_pop:cN} -% \begin{syntax} -% \cs{seq_pop:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the top item from a \meta{seq~var} into the -% \meta{token list variable}. Both of the variables are assigned -% locally. If \meta{seq~var} is empty the \meta{token list variable} -% is set to the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[updated = 2012-05-14]{\seq_gpop:NN, \seq_gpop:cN} -% \begin{syntax} -% \cs{seq_gpop:NN} \meta{seq~var} \meta{token list variable} -% \end{syntax} -% Pops the top item from a \meta{seq~var} into the -% \meta{token list variable}. The \meta{seq~var} is modified globally, -% while the \meta{token list variable} is assigned locally. If -% \meta{seq~var} is empty the \meta{token list variable} is set to -% the special marker \cs{q_no_value}. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_get:NN, \seq_get:cN} -% \begin{syntax} -% \cs{seq_get:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, stores the top item from a -% \meta{seq~var} in the \meta{token list variable} without removing it from -% the \meta{seq~var}. The \meta{token list variable} is assigned locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_pop:NN, \seq_pop:cN} -% \begin{syntax} -% \cs{seq_pop:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the top item from the -% \meta{seq~var} in the \meta{token list variable}, \emph{i.e.}~removes the -% item from the \meta{seq~var}. Both the \meta{seq~var} and the -% \meta{token list variable} are assigned locally. -% \end{function} -% -% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_gpop:NN, \seq_gpop:cN} -% \begin{syntax} -% \cs{seq_gpop:NNTF} \meta{seq~var} \meta{token list variable} \Arg{true code} \Arg{false code} -% \end{syntax} -% If the \meta{seq~var} is empty, leaves the \meta{false code} in the -% input stream. The value of the \meta{token list variable} is -% not defined in this case and should not be relied upon. If the -% \meta{seq~var} is non-empty, pops the top item from the \meta{seq~var} -% in the \meta{token list variable}, \emph{i.e.}~removes the item from the -% \meta{seq~var}. The \meta{seq~var} is modified globally, while the -% \meta{token list variable} is assigned locally. -% \end{function} -% -% \begin{function} -% { -% \seq_push:Nn, \seq_push:NV, \seq_push:Nv, \seq_push:Ne, -% \seq_push:No, -% \seq_push:cn, \seq_push:cV, \seq_push:cv, \seq_push:ce, -% \seq_push:co, -% \seq_gpush:Nn, \seq_gpush:NV, \seq_gpush:Nv, \seq_gpush:Ne, -% \seq_gpush:No, -% \seq_gpush:cn, \seq_gpush:cV, \seq_gpush:cv, \seq_gpush:ce, -% \seq_gpush:co -% } -% \begin{syntax} -% \cs{seq_push:Nn} \meta{seq~var} \Arg{item} -% \end{syntax} -% Adds the \Arg{item} to the top of the \meta{seq~var}. -% \end{function} -% -% \section{Sequences as sets} -% -% Sequences can also be used as sets, such that all of their items are -% distinct. Usage of sequences as sets is not currently widespread, -% hence no specific set function is provided. Instead, it is explained -% here how common set operations can be performed by combining several -% functions described in earlier sections. When using sequences to -% implement sets, one should be careful not to rely on the order of -% items in the sequence representing the set. -% -% Sets should not contain several occurrences of a given item. To make -% sure that a \meta{seq~var} only has distinct items, use -% \cs{seq_remove_duplicates:N} \meta{seq~var}. This function -% is relatively slow, and to avoid performance issues one should only -% use it when necessary. -% -% Some operations on a set \meta{seq~var} are straightforward. For -% instance, \cs{seq_count:N} \meta{seq~var} expands to the number of -% items, while \cs{seq_if_in:NnTF} \meta{seq~var} \Arg{item} tests if -% the \meta{item} is in the set. -% -% Adding an \meta{item} to a set \meta{seq~var} can be done by appending -% it to the \meta{seq~var} if it is not already in the \meta{seq~var}: -% \begin{quote}\ttfamily\parskip=0pt\obeylines -% \cs{seq_if_in:NnF} \meta{seq~var} \Arg{item} -% | |\{ \cs{seq_put_right:Nn} \meta{seq~var} \Arg{item} \} -% \end{quote} -% Removing an \meta{item} from a set \meta{seq~var} can be done using -% \cs{seq_remove_all:Nn}, -% \begin{quote}\ttfamily -% \cs{seq_remove_all:Nn} \meta{seq~var} \Arg{item} -% \end{quote} -% -% The intersection of two sets \meta{seq~var_1} and \meta{seq~var_2} can -% be stored into \meta{seq~var_3} by collecting items of -% \meta{seq~var_1} which are in \meta{seq~var_2}. -% \begin{quote}\ttfamily\parskip=0pt\obeylines -% \cs{seq_clear:N} \meta{seq~var_3} -% \cs{seq_map_inline:Nn} \meta{seq~var_1} -% | |\{ -% | |\cs{seq_if_in:NnT} \meta{seq~var_2} \{\#1\} -% | |\{ \cs{seq_put_right:Nn} \meta{seq~var_3} \{\#1\} \} -% | |\} -% \end{quote} -% The code as written here only works if \meta{seq~var_3} is different -% from the other two sequence variables. To cover all cases, items -% should first be collected in a sequence -% |\l__|\meta{pkg}|_internal_seq|, then \meta{seq~var_3} should be set -% equal to this internal sequence. The same remark applies to other set -% functions. -% -% The union of two sets \meta{seq~var_1} and \meta{seq~var_2} can be -% stored into \meta{seq~var_3} through -% \begin{quote}\ttfamily -% \cs{seq_concat:NNN} \meta{seq~var_3} \meta{seq~var_1} \meta{seq~var_2} \\ -% \cs{seq_remove_duplicates:N} \meta{seq~var_3} -% \end{quote} -% or by adding items to (a copy of) \meta{seq~var_1} one by one -% \begin{quote}\ttfamily\parskip=0pt\obeylines -% \cs{seq_set_eq:NN} \meta{seq~var_3} \meta{seq~var_1} -% \cs{seq_map_inline:Nn} \meta{seq~var_2} -% | |\{ -% | |\cs{seq_if_in:NnF} \meta{seq~var_3} \{\#1\} -% | |\{ \cs{seq_put_right:Nn} \meta{seq~var_3} \{\#1\} \} -% | |\} -% \end{quote} -% The second approach is faster than the first when the \meta{seq~var_2} -% is short compared to \meta{seq~var_1}. -% -% The difference of two sets \meta{seq~var_1} and \meta{seq~var_2} can -% be stored into \meta{seq~var_3} by removing items of the -% \meta{seq~var_2} from (a copy of) the \meta{seq~var_1} one by one. -% \begin{quote}\ttfamily\parskip=0pt\obeylines -% \cs{seq_set_eq:NN} \meta{seq~var_3} \meta{seq~var_1} -% \cs{seq_map_inline:Nn} \meta{seq~var_2} -% | |\{ \cs{seq_remove_all:Nn} \meta{seq~var_3} \{\#1\} \} -% \end{quote} -% -% The symmetric difference of two sets \meta{seq~var_1} and -% \meta{seq~var_2} can be stored into \meta{seq~var_3} by computing the -% difference between \meta{seq~var_1} and \meta{seq~var_2} and storing -% the result as |\l__|\meta{pkg}|_internal_seq|, then the difference -% between \meta{seq~var_2} and \meta{seq~var_1}, and finally -% concatenating the two differences to get the symmetric differences. -% \begin{quote}\ttfamily\parskip=0pt\obeylines -% \cs{seq_set_eq:NN} |\l__|\meta{pkg}|_internal_seq| \meta{seq~var_1} -% \cs{seq_map_inline:Nn} \meta{seq~var_2} -% | |\{ \cs{seq_remove_all:Nn} |\l__|\meta{pkg}|_internal_seq| \{\#1\} \} -% \cs{seq_set_eq:NN} \meta{seq~var_3} \meta{seq~var_2} -% \cs{seq_map_inline:Nn} \meta{seq~var_1} -% | |\{ \cs{seq_remove_all:Nn} \meta{seq~var_3} \{\#1\} \} -% \cs{seq_concat:NNN} \meta{seq~var_3} \meta{seq~var_3} |\l__|\meta{pkg}|_internal_seq| -% \end{quote} -% -% \section{Constant and scratch sequences} -% -% \begin{variable}[added = 2012-07-02]{\c_empty_seq} -% Constant that is always empty. -% \end{variable} -% -% \begin{variable}[added = 2012-04-26]{\l_tmpa_seq, \l_tmpb_seq} -% Scratch sequences for local assignment. These are never used by -% the kernel code, and so are safe for use with any \LaTeX3-defined -% function. However, they may be overwritten by other non-kernel -% code and so should only be used for short-term storage. -% \end{variable} -% -% \begin{variable}[added = 2012-04-26]{\g_tmpa_seq, \g_tmpb_seq} -% Scratch sequences for global assignment. These are never used by -% the kernel code, and so are safe for use with any \LaTeX3-defined -% function. However, they may be overwritten by other non-kernel -% code and so should only be used for short-term storage. -% \end{variable} -% -% \section{Viewing sequences} -% -% \begin{function}[updated = 2021-04-29]{\seq_show:N, \seq_show:c} -% \begin{syntax} -% \cs{seq_show:N} \meta{seq~var} -% \end{syntax} -% Displays the entries in the \meta{seq~var} in the terminal. -% \end{function} -% -% \begin{function}[added = 2014-08-12, updated = 2021-04-29]{\seq_log:N, \seq_log:c} -% \begin{syntax} -% \cs{seq_log:N} \meta{seq~var} -% \end{syntax} -% Writes the entries in the \meta{seq~var} in the log file. -% \end{function} -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3seq} implementation} -% -% \TestFiles{m3seq002,m3seq003} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \begin{macrocode} -%<@@=seq> -% \end{macrocode} -% -% A sequence is a control sequence whose top-level expansion is of the -% form \enquote{\cs{s_@@} \cs{@@_item:n} \marg{item_1} \ldots -% \cs{@@_item:n} \marg{item_n}}, with a leading scan -% mark followed by $n$~items of the same form. An -% earlier implementation used the structure \enquote{\cs{seq_elt:w} -% \meta{item_1} \cs{seq_elt_end:} \ldots \cs{seq_elt:w} \meta{item_n} -% \cs{seq_elt_end:}}. This allowed rapid searching using a delimited -% function, but was not suitable for items containing |{|, |}| and |#| -% tokens, and also lead to the loss of surrounding braces around items -% -% \begin{function}[EXP]{\@@_item:n} -% \begin{syntax} -% \cs{@@_item:n} \Arg{item} -% \end{syntax} -% The internal token used to begin each sequence entry. If expanded -% outside of a mapping or manipulation function, an error is -% raised. The definition should always be set globally. -% \end{function} -% -% \begin{function}{\@@_push_item_def:n, \@@_push_item_def:e} -% \begin{syntax} -% \cs{@@_push_item_def:n} \Arg{code} -% \end{syntax} -% Saves the definition of \cs{@@_item:n} and redefines it to -% accept one parameter and expand to \meta{code}. This function -% should always be balanced by use of \cs{@@_pop_item_def:}. -% \end{function} -% -% \begin{function}{\@@_pop_item_def:} -% \begin{syntax} -% \cs{@@_pop_item_def:} -% \end{syntax} -% Restores the definition of \cs{@@_item:n} most recently saved by -% \cs{@@_push_item_def:n}. This function should always be used in -% a balanced pair with \cs{@@_push_item_def:n}. -% \end{function} -% -% \begin{variable}{\s_@@} -% This private scan mark. -% \begin{macrocode} -\scan_new:N \s_@@ -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\s_@@_mark,\s_@@_stop} -% Private scan marks. -% \begin{macrocode} -\scan_new:N \s_@@_mark -\scan_new:N \s_@@_stop -% \end{macrocode} -% \end{variable} -% -% \begin{macro}[EXP]{\@@_item:n} -% The delimiter is always defined, but when used incorrectly simply -% removes its argument and hits an undefined control sequence to -% raise an error. -% \begin{macrocode} -\cs_new:Npn \@@_item:n - { - \msg_expandable_error:nn { seq } { misused } - \use_none:n - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\l_@@_internal_a_tl, \l_@@_internal_b_tl} -% Scratch space for various internal uses. -% \begin{macrocode} -\tl_new:N \l_@@_internal_a_tl -\tl_new:N \l_@@_internal_b_tl -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\@@_tmp:w} -% Scratch function for internal use. -% \begin{macrocode} -\cs_new_eq:NN \@@_tmp:w ? -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\c_empty_seq} -% A sequence with no item, following the structure mentioned above. -% \begin{macrocode} -\tl_const:Nn \c_empty_seq { \s_@@ } -% \end{macrocode} -% \end{variable} -% -% \subsection{Allocation and initialisation} -% -% \begin{macro}{\seq_new:N, \seq_new:c} -% \UnitTested -% Sequences are initialized to \cs{c_empty_seq}. -% \begin{macrocode} -\cs_new_protected:Npn \seq_new:N #1 - { - \__kernel_chk_if_free_cs:N #1 - \cs_gset_eq:NN #1 \c_empty_seq - } -\cs_generate_variant:Nn \seq_new:N { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\seq_clear:N, \seq_clear:c} -% \UnitTested -% \begin{macro}{\seq_gclear:N, \seq_gclear:c} -% \UnitTested -% Clearing a sequence is similar to setting it equal to the empty one. -% \begin{macrocode} -\cs_new_protected:Npn \seq_clear:N #1 - { \seq_set_eq:NN #1 \c_empty_seq } -\cs_generate_variant:Nn \seq_clear:N { c } -\cs_new_protected:Npn \seq_gclear:N #1 - { \seq_gset_eq:NN #1 \c_empty_seq } -\cs_generate_variant:Nn \seq_gclear:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_clear_new:N, \seq_clear_new:c} -% \UnitTested -% \begin{macro}{\seq_gclear_new:N, \seq_gclear_new:c} -% \UnitTested -% Once again we copy code from the token list functions. -% \begin{macrocode} -\cs_new_protected:Npn \seq_clear_new:N #1 - { \seq_if_exist:NTF #1 { \seq_clear:N #1 } { \seq_new:N #1 } } -\cs_generate_variant:Nn \seq_clear_new:N { c } -\cs_new_protected:Npn \seq_gclear_new:N #1 - { \seq_if_exist:NTF #1 { \seq_gclear:N #1 } { \seq_new:N #1 } } -\cs_generate_variant:Nn \seq_gclear_new:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_set_eq:NN, \seq_set_eq:cN, \seq_set_eq:Nc, \seq_set_eq:cc} -% \UnitTested -% \begin{macro} -% {\seq_gset_eq:NN, \seq_gset_eq:cN, \seq_gset_eq:Nc, \seq_gset_eq:cc} -% \UnitTested -% Copying a sequence is the same as copying the underlying token list. -% \begin{macrocode} -\cs_new_eq:NN \seq_set_eq:NN \tl_set_eq:NN -\cs_new_eq:NN \seq_set_eq:Nc \tl_set_eq:Nc -\cs_new_eq:NN \seq_set_eq:cN \tl_set_eq:cN -\cs_new_eq:NN \seq_set_eq:cc \tl_set_eq:cc -\cs_new_eq:NN \seq_gset_eq:NN \tl_gset_eq:NN -\cs_new_eq:NN \seq_gset_eq:Nc \tl_gset_eq:Nc -\cs_new_eq:NN \seq_gset_eq:cN \tl_gset_eq:cN -\cs_new_eq:NN \seq_gset_eq:cc \tl_gset_eq:cc -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \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 - { - \__kernel_tl_set:Nx #1 - { \s_@@ \clist_map_function:NN #2 \@@_wrap_item:n } - } -\cs_new_protected:Npn \seq_set_from_clist:Nn #1#2 - { - \__kernel_tl_set:Nx #1 - { \s_@@ \clist_map_function:nN {#2} \@@_wrap_item:n } - } -\cs_new_protected:Npn \seq_gset_from_clist:NN #1#2 - { - \__kernel_tl_gset:Nx #1 - { \s_@@ \clist_map_function:NN #2 \@@_wrap_item:n } - } -\cs_new_protected:Npn \seq_gset_from_clist:Nn #1#2 - { - \__kernel_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_const_from_clist:Nn, \seq_const_from_clist:cn} -% Almost identical to \cs{seq_set_from_clist:Nn}. -% \begin{macrocode} -\cs_new_protected:Npn \seq_const_from_clist:Nn #1#2 - { - \tl_const:Ne #1 - { \s_@@ \clist_map_function:nN {#2} \@@_wrap_item:n } - } -\cs_generate_variant:Nn \seq_const_from_clist:Nn { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \seq_set_split:Nnn , -% \seq_set_split:NVn , \seq_set_split:NnV , \seq_set_split:NVV , -% \seq_set_split:Nne , \seq_set_split:Nee , -% \seq_set_split:Nnx , \seq_set_split:Nxx , -% \seq_gset_split:Nnn, -% \seq_gset_split:NVn, \seq_gset_split:NnV, \seq_gset_split:NVV, -% \seq_gset_split:Nne, \seq_gset_split:Nee, -% \seq_gset_split:Nnx, \seq_gset_split:Nxx -% } -% \begin{macro} -% { -% \seq_set_split_keep_spaces:Nnn , \seq_set_split_keep_spaces:NnV , -% \seq_gset_split_keep_spaces:Nnn, \seq_gset_split_keep_spaces:NnV -% } -% \begin{macro}{\@@_set_split:NNnn} -% \begin{macro} -% { -% \@@_set_split:Nw, \@@_set_split:w, -% \@@_set_split_end: -% } -% When the separator is empty, everything is very simple, just map -% \cs{@@_wrap_item:n} through the items of the last argument. -% For non-trivial separators, the goal is to split a given token list -% at the marker, strip spaces from each item, and remove one set of -% outer braces if after removing leading and trailing -% spaces the item is enclosed within braces. After -% \cs{tl_replace_all:Nnn}, the token list \cs{l_@@_internal_a_tl} -% is a repetition of the pattern -% \cs{@@_set_split:Nw} \cs{prg_do_nothing:} -% \meta{item with spaces} \cs{@@_set_split_end:}. -% Then, \texttt{e}-expansion causes \cs{@@_set_split:Nw} -% to trim spaces, and leaves its result as -% \cs{@@_set_split:w} \meta{trimmed item} -% \cs{@@_set_split_end:}. This is then converted -% to the \pkg{l3seq} internal structure by another -% \texttt{e}-expansion. In the first step, we insert -% \cs{prg_do_nothing:} to avoid losing braces too early: -% that would cause space trimming to act within those -% lost braces. The second step is solely there to strip -% braces which are outermost after space trimming. -% \begin{macrocode} -\cs_new_protected:Npn \seq_set_split:Nnn - { \@@_set_split:NNNnn \__kernel_tl_set:Nx \tl_trim_spaces:n } -\cs_new_protected:Npn \seq_gset_split:Nnn - { \@@_set_split:NNNnn \__kernel_tl_gset:Nx \tl_trim_spaces:n } -\cs_new_protected:Npn \seq_set_split_keep_spaces:Nnn - { \@@_set_split:NNNnn \__kernel_tl_set:Nx \exp_not:n } -\cs_new_protected:Npn \seq_gset_split_keep_spaces:Nnn - { \@@_set_split:NNNnn \__kernel_tl_gset:Nx \exp_not:n } -\cs_new_protected:Npn \@@_set_split:NNNnn #1#2#3#4#5 - { - \tl_if_empty:nTF {#4} - { - \tl_set:Nn \l_@@_internal_a_tl - { \tl_map_function:nN {#5} \@@_wrap_item:n } - } - { - \tl_set:Nn \l_@@_internal_a_tl - { - \@@_set_split:Nw #2 \prg_do_nothing: - #5 - \@@_set_split_end: - } - \tl_replace_all:Nnn \l_@@_internal_a_tl {#4} - { - \@@_set_split_end: - \@@_set_split:Nw #2 \prg_do_nothing: - } - \__kernel_tl_set:Nx \l_@@_internal_a_tl { \l_@@_internal_a_tl } - } - #1 #3 { \s_@@ \l_@@_internal_a_tl } - } -\cs_new:Npn \@@_set_split:Nw #1#2 \@@_set_split_end: - { - \exp_not:N \@@_set_split:w - \exp_args:No #1 {#2} - \exp_not:N \@@_set_split_end: - } -\cs_new:Npn \@@_set_split:w #1 \@@_set_split_end: - { \@@_wrap_item:n {#1} } -\cs_generate_variant:Nn \seq_set_split:Nnn { NV , NnV , NVV , Nne , Nee } -\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx , Nxx } -\cs_generate_variant:Nn \seq_gset_split:Nnn { NV , NnV , NVV , Nne , Nee } -\cs_generate_variant:Nn \seq_gset_split:Nnn { Nnx , Nxx } -\cs_generate_variant:Nn \seq_set_split_keep_spaces:Nnn { NnV } -\cs_generate_variant:Nn \seq_gset_split_keep_spaces:Nnn { NnV } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_set_filter:NNn, \seq_gset_filter:NNn} -% \begin{macro}{\@@_set_filter:NNNn} -% Similar to \cs{seq_map_inline:Nn}, without a -% \cs{prg_break_point:} because the user's code -% is performed within the evaluation of a boolean expression, -% and skipping out of that would break horribly. -% The \cs{@@_wrap_item:n} function inserts the relevant -% \cs{@@_item:n} without expansion in the input stream, -% hence in the \texttt{e}-expanding assignment. -% \begin{macrocode} -\cs_new_protected:Npn \seq_set_filter:NNn - { \@@_set_filter:NNNn \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_gset_filter:NNn - { \@@_set_filter:NNNn \__kernel_tl_gset:Nx } -\cs_new_protected:Npn \@@_set_filter:NNNn #1#2#3#4 - { - \@@_push_item_def:n { \bool_if:nT {#4} { \@@_wrap_item:n {##1} } } - #1 #2 { #3 } - \@@_pop_item_def: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_concat:NNN, \seq_concat:ccc} -% \UnitTested -% \begin{macro}{\seq_gconcat:NNN, \seq_gconcat:ccc} -% \UnitTested -% When concatenating sequences, one must remove the leading \cs{s_@@} -% of the second sequence. The result starts with \cs{s_@@} (of the -% first sequence), which stops \texttt{f}-expansion. -% \begin{macrocode} -\cs_new_protected:Npn \seq_concat:NNN #1#2#3 - { \tl_set:Nf #1 { \exp_after:wN \use_i:nn \exp_after:wN #2 #3 } } -\cs_new_protected:Npn \seq_gconcat:NNN #1#2#3 - { \tl_gset:Nf #1 { \exp_after:wN \use_i:nn \exp_after:wN #2 #3 } } -\cs_generate_variant:Nn \seq_concat:NNN { ccc } -\cs_generate_variant:Nn \seq_gconcat:NNN { ccc } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[pTF]{\seq_if_exist:N, \seq_if_exist:c} -% Copies of the \texttt{cs} functions defined in \pkg{l3basics}. -% \begin{macrocode} -\prg_new_eq_conditional:NNn \seq_if_exist:N \cs_if_exist:N - { TF , T , F , p } -\prg_new_eq_conditional:NNn \seq_if_exist:c \cs_if_exist:c - { TF , T , F , p } -% \end{macrocode} -% \end{macro} -% -% \subsection{Appending data to either end} -% -% \begin{macro}{ -% \seq_put_left:Nn, \seq_put_left:NV, \seq_put_left:Nv, \seq_put_left:Ne, -% \seq_put_left:No, \seq_put_left:Nx, -% \seq_put_left:cn, \seq_put_left:cV, \seq_put_left:cv,\seq_put_left:ce, -% \seq_put_left:co, \seq_put_left:cx -% } -% \UnitTested -% \begin{macro}{ -% \seq_gput_left:Nn, \seq_gput_left:NV, \seq_gput_left:Nv, \seq_gput_left:Ne, -% \seq_gput_left:No, \seq_gput_left:Nx, -% \seq_gput_left:cn, \seq_gput_left:cV, \seq_gput_left:cv, \seq_gput_left:ce, -% \seq_gput_left:co, \seq_gput_left:cx -% } -% \begin{macro}[EXP]{\@@_put_left_aux:w} -% When adding to the left of a sequence, remove \cs{s_@@}. This is -% done by \cs{@@_put_left_aux:w}, which also stops -% \texttt{f}-expansion. -% \begin{macrocode} -\cs_new_protected:Npn \seq_put_left:Nn #1#2 - { - \__kernel_tl_set:Nx #1 - { - \exp_not:n { \s_@@ \@@_item:n {#2} } - \exp_not:f { \exp_after:wN \@@_put_left_aux:w #1 } - } - } -\cs_new_protected:Npn \seq_gput_left:Nn #1#2 - { - \__kernel_tl_gset:Nx #1 - { - \exp_not:n { \s_@@ \@@_item:n {#2} } - \exp_not:f { \exp_after:wN \@@_put_left_aux:w #1 } - } - } -\cs_new:Npn \@@_put_left_aux:w \s_@@ { \exp_stop_f: } -\cs_generate_variant:Nn \seq_put_left:Nn { NV , Nv , Ne , No , Nx } -\cs_generate_variant:Nn \seq_put_left:Nn { c , cV , cv , ce , co ,cx } -\cs_generate_variant:Nn \seq_gput_left:Nn { NV , Nv , Ne , No , Nx } -\cs_generate_variant:Nn \seq_gput_left:Nn { c , cV , cv , ce , co , cx } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% { -% \seq_put_right:Nn, \seq_put_right:NV, \seq_put_right:Nv, \seq_put_right:Ne, -% \seq_put_right:No, \seq_put_right:Nx, -% \seq_put_right:cn, \seq_put_right:cV, \seq_put_right:cv, \seq_put_right:cx, -% \seq_put_right:co, \seq_put_right:cx -% } -% \UnitTested -% \begin{macro} -% { -% \seq_gput_right:Nn, \seq_gput_right:NV, \seq_gput_right:Nv, \seq_gput_right:Ne, -% \seq_gput_right:No, \seq_gput_right:Nx, -% \seq_gput_right:cn, \seq_gput_right:cV, \seq_gput_right:cv, \seq_gput_right:ce, -% \seq_gput_right:co, \seq_gput_right:cx -% } -% Since there is no trailing marker, adding an item to the right of a -% sequence simply means wrapping it in \cs{@@_item:n}. -% \begin{macrocode} -\cs_new_protected:Npn \seq_put_right:Nn #1#2 - { \tl_put_right:Nn #1 { \@@_item:n {#2} } } -\cs_new_protected:Npn \seq_gput_right:Nn #1#2 - { \tl_gput_right:Nn #1 { \@@_item:n {#2} } } -\cs_generate_variant:Nn \seq_put_right:Nn { NV , Nv , Ne , No , Nx } -\cs_generate_variant:Nn \seq_put_right:Nn { c , cV , cv , ce , co , cx } -\cs_generate_variant:Nn \seq_gput_right:Nn { NV , Nv , Ne , No , Nx } -\cs_generate_variant:Nn \seq_gput_right:Nn { c , cV , cv , ce , co , cx } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Modifying sequences} -% -% \begin{macro}{\@@_wrap_item:n} -% This function converts its argument to a proper sequence item -% in an \texttt{e}-expansion context. -% \begin{macrocode} -\cs_new:Npn \@@_wrap_item:n #1 { \exp_not:n { \@@_item:n {#1} } } -% \end{macrocode} -% \end{macro} -% -% \begin{variable}{\l_@@_remove_seq} -% An internal sequence for the removal routines. -% \begin{macrocode} -\seq_new:N \l_@@_remove_seq -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\seq_remove_duplicates:N, \seq_remove_duplicates:c} -% \UnitTested -% \begin{macro}{\seq_gremove_duplicates:N, \seq_gremove_duplicates:c} -% \UnitTested -% \begin{macro}{\@@_remove_duplicates:NN} -% Removing duplicates means making a new list then copying it. -% \begin{macrocode} -\cs_new_protected:Npn \seq_remove_duplicates:N - { \@@_remove_duplicates:NN \seq_set_eq:NN } -\cs_new_protected:Npn \seq_gremove_duplicates:N - { \@@_remove_duplicates:NN \seq_gset_eq:NN } -\cs_new_protected:Npn \@@_remove_duplicates:NN #1#2 - { - \seq_clear:N \l_@@_remove_seq - \seq_map_inline:Nn #2 - { - \seq_if_in:NnF \l_@@_remove_seq {##1} - { \seq_put_right:Nn \l_@@_remove_seq {##1} } - } - #1 #2 \l_@@_remove_seq - } -\cs_generate_variant:Nn \seq_remove_duplicates:N { c } -\cs_generate_variant:Nn \seq_gremove_duplicates:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% { -% \seq_remove_all:Nn, \seq_remove_all:NV, \seq_remove_all:Ne, -% \seq_remove_all:Nx, -% \seq_remove_all:cn, \seq_remove_all:cV, \seq_remove_all:ce, -% \seq_remove_all:cx, -% } -% \UnitTested -% \begin{macro} -% { -% \seq_gremove_all:Nn, \seq_gremove_all:NV, \seq_gremove_all:Ne, -% \seq_gremove_all:Nx, -% \seq_gremove_all:cn, \seq_gremove_all:cV, \seq_gremove_all:ce, -% \seq_gremove_all:Nx -% } -% \UnitTested -% \begin{macro}{\@@_remove_all_aux:NNn} -% The idea of the code here is to avoid a relatively expensive addition of -% items one at a time to an intermediate sequence. -% The approach taken is therefore similar to -% that in \cs{@@_pop_right:NNN}, using a \enquote{flexible} -% \texttt{e}-type expansion to do most of the work. As \cs{tl_if_eq:nnT} -% is not expandable, a two-part strategy is needed. First, the -% \texttt{e}-type expansion uses \cs{str_if_eq:nnT} to find potential -% matches. If one is found, the expansion is halted and the necessary -% set up takes place to use the \cs{tl_if_eq:NNT} test. The \texttt{e}-type -% is started again, including all of the items copied already. This -% happens repeatedly until the entire sequence has been scanned. The code -% is set up to avoid needing an intermediate scratch list: the lead-off -% \texttt{e}-type expansion (|#1 #2 {#2}|) ensures that nothing is lost. -% \begin{macrocode} -\cs_new_protected:Npn \seq_remove_all:Nn - { \@@_remove_all_aux:NNn \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_gremove_all:Nn - { \@@_remove_all_aux:NNn \__kernel_tl_gset:Nx } -\cs_new_protected:Npn \@@_remove_all_aux:NNn #1#2#3 - { - \@@_push_item_def:n - { - \str_if_eq:nnT {##1} {#3} - { - \if_false: { \fi: } - \tl_set:Nn \l_@@_internal_b_tl {##1} - #1 #2 - { \if_false: } \fi: - \exp_not:o {#2} - \tl_if_eq:NNT \l_@@_internal_a_tl \l_@@_internal_b_tl - { \use_none:nn } - } - \@@_wrap_item:n {##1} - } - \tl_set:Nn \l_@@_internal_a_tl {#3} - #1 #2 {#2} - \@@_pop_item_def: - } -\cs_generate_variant:Nn \seq_remove_all:Nn { NV , Ne , c , cV , ce } -\cs_generate_variant:Nn \seq_remove_all:Nn { Nx , cx } -\cs_generate_variant:Nn \seq_gremove_all:Nn { NV , Ne , c , cV , ce } -\cs_generate_variant:Nn \seq_gremove_all:Nn { Nx , cx } -% \end{macrocode} -% \end{macro} -% \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:nneee { 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} -% \begin{macro}[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:Npn \seq_reverse:N - { \@@_reverse:NN \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_greverse:N - { \@@_reverse:NN \__kernel_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} -% -% \begin{macro}{\seq_sort:Nn, \seq_sort:cn, \seq_gsort:Nn, \seq_gsort:cn} -% Implemented in \pkg{l3sort}. -% \end{macro} -% -% \subsection{Sequence conditionals} -% -% \begin{macro}[pTF]{\seq_if_empty:N, \seq_if_empty:c} -% \UnitTested -% Similar to token lists, we compare with the empty sequence. -% \begin{macrocode} -\prg_new_conditional:Npnn \seq_if_empty:N #1 { p , T , F , TF } - { - \if_meaning:w #1 \c_empty_seq - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\prg_generate_conditional_variant:Nnn \seq_if_empty:N - { c } { p , T , F , TF } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\seq_shuffle:N, \seq_shuffle:c, \seq_gshuffle:N, \seq_gshuffle:c} -% \begin{macro}{\@@_shuffle:NN} -% \begin{macro}{\@@_shuffle_item:n} -% \begin{variable}{\g_@@_internal_seq} -% We apply the Fisher--Yates shuffle, storing items in \tn{toks} -% registers. We use the primitive \cs{tex_uniformdeviate:D} for -% speed reasons. Its non-uniformity is of order its argument divided -% by $2^{28}$, not too bad for small lists. For sequences with more -% than $13$ elements there are more possible permutations than -% possible seeds ($13!>2^{28}$) so the question of uniformity is -% somewhat moot. The integer variables are declared in \pkg{l3int}: -% load-order issues. -% \begin{macrocode} -\seq_new:N \g_@@_internal_seq -\cs_new_protected:Npn \seq_shuffle:N { \@@_shuffle:NN \seq_set_eq:NN } -\cs_new_protected:Npn \seq_gshuffle:N { \@@_shuffle:NN \seq_gset_eq:NN } -\cs_new_protected:Npn \@@_shuffle:NN #1#2 - { - \int_compare:nNnTF { \seq_count:N #2 } > \c_max_register_int - { - \msg_error:nne { seq } { shuffle-too-large } - { \token_to_str:N #2 } - } - { - \group_begin: - \int_zero:N \l_@@_internal_a_int - \@@_push_item_def: - \cs_gset_eq:NN \@@_item:n \@@_shuffle_item:n - #2 - \@@_pop_item_def: - \seq_gclear:N \g_@@_internal_seq - \int_step_inline:nn \l_@@_internal_a_int - { - \seq_gput_right:Ne \g_@@_internal_seq - { \tex_the:D \tex_toks:D ##1 } - } - \group_end: - #1 #2 \g_@@_internal_seq - \seq_gclear:N \g_@@_internal_seq - } - } -\cs_new_protected:Npn \@@_shuffle_item:n - { - \int_incr:N \l_@@_internal_a_int - \int_set:Nn \l_@@_internal_b_int - { 1 + \tex_uniformdeviate:D \l_@@_internal_a_int } - \tex_toks:D \l_@@_internal_a_int - = \tex_toks:D \l_@@_internal_b_int - \tex_toks:D \l_@@_internal_b_int - } -\cs_generate_variant:Nn \seq_shuffle:N { c } -\cs_generate_variant:Nn \seq_gshuffle:N { c } -% \end{macrocode} -% \end{variable} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[TF] -% { -% \seq_if_in:Nn, \seq_if_in:NV, \seq_if_in:Nv, \seq_if_in:Ne, -% \seq_if_in:No, \seq_if_in:Nx, -% \seq_if_in:cn, \seq_if_in:cV, \seq_if_in:cv,\seq_if_in:ce, -% \seq_if_in:co, \seq_if_in:cx -% } -% \UnitTested -% \begin{macro}{\@@_if_in:} -% The approach here is to define \cs{@@_item:n} to compare its -% argument with the test sequence. If the two items are equal, the -% mapping is terminated and \cs{group_end:} \cs{prg_return_true:} -% is inserted after skipping over the rest of the recursion. On the -% other hand, if there is no match then the loop breaks, returning -% \cs{prg_return_false:}. -% Everything is inside a group so that \cs{@@_item:n} is preserved -% in nested situations. -% \begin{macrocode} -\prg_new_protected_conditional:Npnn \seq_if_in:Nn #1#2 - { T , F , TF } - { - \group_begin: - \tl_set:Nn \l_@@_internal_a_tl {#2} - \cs_set_protected:Npn \@@_item:n ##1 - { - \tl_set:Nn \l_@@_internal_b_tl {##1} - \if_meaning:w \l_@@_internal_a_tl \l_@@_internal_b_tl - \exp_after:wN \@@_if_in: - \fi: - } - #1 - \group_end: - \prg_return_false: - \prg_break_point: - } -\cs_new:Npn \@@_if_in: - { \prg_break:n { \group_end: \prg_return_true: } } -\prg_generate_conditional_variant:Nnn \seq_if_in:Nn - { NV , Nv , Ne , No , Nx , c , cV , cv , ce , co , cx } { T , F , TF } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Recovering data from sequences} -% -% \begin{macro}{\@@_pop:NNNN, \@@_pop_TF:NNNN} -% The two \texttt{pop} functions share their emptiness tests. We also -% use a common emptiness test for all branching \texttt{get} and -% \texttt{pop} functions. -% \begin{macrocode} -\cs_new_protected:Npn \@@_pop:NNNN #1#2#3#4 - { - \if_meaning:w #3 \c_empty_seq - \tl_set:Nn #4 { \q_no_value } - \else: - #1#2#3#4 - \fi: - } -\cs_new_protected:Npn \@@_pop_TF:NNNN #1#2#3#4 - { - \if_meaning:w #3 \c_empty_seq - % \tl_set:Nn #4 { \q_no_value } - \prg_return_false: - \else: - #1#2#3#4 - \prg_return_true: - \fi: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\seq_get_left:NN, \seq_get_left:cN} -% \UnitTested -% \begin{macro}{\@@_get_left:wnw} -% Getting an item from the left of a sequence is pretty easy: just -% trim off the first item after \cs{@@_item:n} at the start. We -% append a \cs{q_no_value} item to cover the case of an empty sequence -% \begin{macrocode} -\cs_new_protected:Npn \seq_get_left:NN #1#2 - { - \__kernel_tl_set:Nx #2 - { - \exp_after:wN \@@_get_left:wnw - #1 \@@_item:n { \q_no_value } \s_@@_stop - } - } -\cs_new:Npn \@@_get_left:wnw #1 \@@_item:n #2#3 \s_@@_stop - { \exp_not:n {#2} } -\cs_generate_variant:Nn \seq_get_left:NN { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_pop_left:NN, \seq_pop_left:cN} -% \UnitTested -% \begin{macro}{\seq_gpop_left:NN, \seq_gpop_left:cN} -% \UnitTested -% \begin{macro}{\@@_pop_left:NNN, \@@_pop_left:wnwNNN} -% The approach to popping an item is pretty similar to that to get -% an item, with the only difference being that the sequence itself has -% to be redefined. This makes it more sensible to use an auxiliary -% function for the local and global cases. -% \begin{macrocode} -\cs_new_protected:Npn \seq_pop_left:NN - { \@@_pop:NNNN \@@_pop_left:NNN \tl_set:Nn } -\cs_new_protected:Npn \seq_gpop_left:NN - { \@@_pop:NNNN \@@_pop_left:NNN \tl_gset:Nn } -\cs_new_protected:Npn \@@_pop_left:NNN #1#2#3 - { \exp_after:wN \@@_pop_left:wnwNNN #2 \s_@@_stop #1#2#3 } -\cs_new_protected:Npn \@@_pop_left:wnwNNN - #1 \@@_item:n #2#3 \s_@@_stop #4#5#6 - { - #4 #5 { #1 #3 } - \tl_set:Nn #6 {#2} - } -\cs_generate_variant:Nn \seq_pop_left:NN { c } -\cs_generate_variant:Nn \seq_gpop_left:NN { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_get_right:NN, \seq_get_right:cN} -% \UnitTested -% \begin{macro}[EXP]{\@@_get_right_loop:nw, \@@_get_right_end:NnN} -% First remove \cs{s_@@} and prepend \cs{q_no_value}. The first -% argument of \cs{@@_get_right_loop:nw} is the last item found, and -% the second argument is empty until the end of the loop, where it is -% code that applies \cs{exp_not:n} to the last item and ends the loop. -% \begin{macrocode} -\cs_new_protected:Npn \seq_get_right:NN #1#2 - { - \__kernel_tl_set:Nx #2 - { - \exp_after:wN \use_i_ii:nnn - \exp_after:wN \@@_get_right_loop:nw - \exp_after:wN \q_no_value - #1 - \@@_get_right_end:NnN \@@_item:n - } - } -\cs_new:Npn \@@_get_right_loop:nw #1#2 \@@_item:n - { - #2 \use_none:n {#1} - \@@_get_right_loop:nw - } -\cs_new:Npn \@@_get_right_end:NnN #1#2#3 { \exp_not:n {#2} } -\cs_generate_variant:Nn \seq_get_right:NN { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_pop_right:NN, \seq_pop_right:cN} -% \UnitTested -% \begin{macro}{\seq_gpop_right:NN, \seq_gpop_right:cN} -% \UnitTested -% \begin{macro}{\@@_pop_right:NNN, \@@_pop_right_loop:nn} -% The approach to popping from the right is a bit more involved, but does -% use some of the same ideas as getting from the right. What is needed is a -% \enquote{flexible length} way to set a token list variable. This is -% supplied by the |{ \if_false: } \fi:| \ldots -% |\if_false: { \fi: }| construct. Using an \texttt{e}-type -% expansion and a \enquote{non-expanding} definition for \cs{@@_item:n}, -% the left-most $n - 1$ entries in a sequence of $n$ items are stored -% back in the sequence. That needs a loop of unknown length, hence using the -% strange \cs{if_false:} way of including braces. When the last item -% of the sequence is reached, the closing brace for the assignment is -% inserted, and |\tl_set:Nn #3| is inserted in front of the final -% entry. This therefore does the pop assignment. One more iteration -% is performed, with an empty argument and \cs{use_none:nn}, which -% finally stops the loop. -% \begin{macrocode} -\cs_new_protected:Npn \seq_pop_right:NN - { \@@_pop:NNNN \@@_pop_right:NNN \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_gpop_right:NN - { \@@_pop:NNNN \@@_pop_right:NNN \__kernel_tl_gset:Nx } -\cs_new_protected:Npn \@@_pop_right:NNN #1#2#3 - { - \cs_set_eq:NN \@@_tmp:w \@@_item:n - \cs_set_eq:NN \@@_item:n \scan_stop: - #1 #2 - { \if_false: } \fi: \s_@@ - \exp_after:wN \use_i:nnn - \exp_after:wN \@@_pop_right_loop:nn - #2 - { - \if_false: { \fi: } - \__kernel_tl_set:Nx #3 - } - { } \use_none:nn - \cs_set_eq:NN \@@_item:n \@@_tmp:w - } -\cs_new:Npn \@@_pop_right_loop:nn #1#2 - { - #2 { \exp_not:n {#1} } - \@@_pop_right_loop:nn - } -\cs_generate_variant:Nn \seq_pop_right:NN { c } -\cs_generate_variant:Nn \seq_gpop_right:NN { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[TF]{\seq_get_left:NN, \seq_get_left:cN} -% \begin{macro}[TF]{\seq_get_right:NN, \seq_get_right:cN} -% Getting from the left or right with a check on the results. The -% first argument to \cs{@@_pop_TF:NNNN} is left unused. -% \begin{macrocode} -\prg_new_protected_conditional:Npnn \seq_get_left:NN #1#2 { T , F , TF } - { \@@_pop_TF:NNNN \prg_do_nothing: \seq_get_left:NN #1#2 } -\prg_new_protected_conditional:Npnn \seq_get_right:NN #1#2 { T , F , TF } - { \@@_pop_TF:NNNN \prg_do_nothing: \seq_get_right:NN #1#2 } -\prg_generate_conditional_variant:Nnn \seq_get_left:NN - { c } { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_get_right:NN - { c } { T , F , TF } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[TF]{\seq_pop_left:NN, \seq_pop_left:cN} -% \begin{macro}[TF]{\seq_gpop_left:NN, \seq_gpop_left:cN} -% \begin{macro}[TF]{\seq_pop_right:NN, \seq_pop_right:cN} -% \begin{macro}[TF]{\seq_gpop_right:NN, \seq_gpop_right:cN} -% More or less the same for popping. -% \begin{macrocode} -\prg_new_protected_conditional:Npnn \seq_pop_left:NN #1#2 - { T , F , TF } - { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_set:Nn #1 #2 } -\prg_new_protected_conditional:Npnn \seq_gpop_left:NN #1#2 - { T , F , TF } - { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_gset:Nn #1 #2 } -\prg_new_protected_conditional:Npnn \seq_pop_right:NN #1#2 - { T , F , TF } - { \@@_pop_TF:NNNN \@@_pop_right:NNN \__kernel_tl_set:Nx #1 #2 } -\prg_new_protected_conditional:Npnn \seq_gpop_right:NN #1#2 - { T , F , TF } - { \@@_pop_TF:NNNN \@@_pop_right:NNN \__kernel_tl_gset:Nx #1 #2 } -\prg_generate_conditional_variant:Nnn \seq_pop_left:NN { c } - { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_gpop_left:NN { c } - { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_pop_right:NN { c } - { T , F , TF } -\prg_generate_conditional_variant:Nnn \seq_gpop_right:NN { c } - { T , F , TF } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% {\seq_item:Nn, \seq_item:NV, \seq_item:Ne, \seq_item:cn, \seq_item:cV, \seq_item:ce} -% \begin{macro}{\@@_item:wNn, \@@_item:nN, \@@_item:nwn} -% 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 argument delimited by \cs{@@_item:n} is \cs{prg_break:} instead -% of being empty, terminating the loop and returning nothing at all. -% \begin{macrocode} -\cs_new:Npn \seq_item:Nn #1 - { \exp_after:wN \@@_item:wNn #1 \s_@@_stop #1 } -\cs_new:Npn \@@_item:wNn \s_@@ #1 \s_@@_stop #2#3 - { - \exp_args:Nf \@@_item:nwn - { \exp_args:Nf \@@_item:nN { \int_eval:n {#3} } #2 } - #1 - \prg_break: \@@_item:n { } - \prg_break_point: - } -\cs_new:Npn \@@_item:nN #1#2 - { - \int_compare:nNnTF {#1} < 0 - { \int_eval:n { \seq_count:N #2 + 1 + #1 } } - {#1} - } -\cs_new:Npn \@@_item:nwn #1#2 \@@_item:n #3 - { - #2 - \int_compare:nNnTF {#1} = 1 - { \prg_break:n { \exp_not:n {#3} } } - { \exp_args:Nf \@@_item:nwn { \int_eval:n { #1 - 1 } } } - } -\cs_generate_variant:Nn \seq_item:Nn { NV , Ne , c , cV , ce } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_rand_item:N, \seq_rand_item:c} -% Importantly, \cs{seq_item:Nn} only evaluates its argument once. -% \begin{macrocode} -\cs_new:Npn \seq_rand_item:N #1 - { - \seq_if_empty:NF #1 - { \seq_item:Nn #1 { \int_rand:nn { 1 } { \seq_count:N #1 } } } - } -\cs_generate_variant:Nn \seq_rand_item:N { c } -% \end{macrocode} -% \end{macro} -% -% \subsection{Mapping over sequences} -% -% \begin{macro}{\seq_map_break:} -% \UnitTested -% \begin{macro}{\seq_map_break:n} -% \UnitTested -% To break a function, the special token \cs{prg_break_point:Nn} is -% used to find the end of the code. Any ending code is then inserted -% before the return value of \cs{seq_map_break:n} is inserted. -% \begin{macrocode} -\cs_new:Npn \seq_map_break: - { \prg_map_break:Nn \seq_map_break: { } } -\cs_new:Npn \seq_map_break:n - { \prg_map_break:Nn \seq_map_break: } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_map_function:NN, \seq_map_function:cN} -% \UnitTested -% \begin{macro}[rEXP]{\@@_map_function:Nw} -% The idea here is to apply the code of |#2| to each item in the -% sequence without altering the definition of \cs{@@_item:n}. The -% even-numbered arguments of \cs{@@_map_function:Nw} delimited by -% \cs{@@_item:n} are almost always empty, except -% at the end of the loop where it is \cs{prg_break:}. This allows to -% break the loop without needing to do a (relatively-expensive) quark -% test. -% \begin{macrocode} -\cs_new:Npn \seq_map_function:NN #1#2 - { - \exp_after:wN \use_i_ii:nnn - \exp_after:wN \@@_map_function:Nw - \exp_after:wN #2 - #1 - \prg_break: - \@@_item:n { } \@@_item:n { } \@@_item:n { } \@@_item:n { } - \prg_break_point: - \prg_break_point:Nn \seq_map_break: { } - } -\cs_new:Npn \@@_map_function:Nw #1 - #2 \@@_item:n #3 - #4 \@@_item:n #5 - #6 \@@_item:n #7 - #8 \@@_item:n #9 - { - #2 #1 {#3} - #4 #1 {#5} - #6 #1 {#7} - #8 #1 {#9} - \@@_map_function:Nw #1 - } -\cs_generate_variant:Nn \seq_map_function:NN { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_push_item_def:n, \@@_push_item_def:e} -% \begin{macro}{\@@_push_item_def:} -% \begin{macro}{\@@_pop_item_def:} -% The definition of \cs{@@_item:n} needs to be saved and restored at -% various points within the mapping and manipulation code. That is handled -% here: as always, this approach uses global assignments. -% \begin{macrocode} -\cs_new_protected:Npn \@@_push_item_def:n - { - \@@_push_item_def: - \cs_gset:Npn \@@_item:n ##1 - } -\cs_new_protected:Npn \@@_push_item_def:e - { - \@@_push_item_def: - \cs_gset:Npe \@@_item:n ##1 - } -\cs_new_protected:Npn \@@_push_item_def: - { - \int_gincr:N \g__kernel_prg_map_int - \cs_gset_eq:cN { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - \@@_item:n - } -\cs_new_protected:Npn \@@_pop_item_def: - { - \cs_gset_eq:Nc \@@_item:n - { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - \int_gdecr:N \g__kernel_prg_map_int - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_map_inline:Nn, \seq_map_inline:cn} -% \UnitTested -% The idea here is that \cs{@@_item:n} is already \enquote{applied} to -% each item in a sequence, and so an in-line mapping is just a case of -% redefining \cs{@@_item:n}. -% \begin{macrocode} -\cs_new_protected:Npn \seq_map_inline:Nn #1#2 - { - \@@_push_item_def:n {#2} - #1 - \prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } - } -\cs_generate_variant:Nn \seq_map_inline:Nn { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\seq_map_tokens:Nn, \seq_map_tokens:cn} -% \begin{macro}{\@@_map_tokens:nw} -% This is based on the function mapping but using the same tricks as -% described for \cs{prop_map_tokens:Nn}. The idea is to remove the leading -% \cs{s_@@} and apply the tokens such that they are safe with the -% break points, hence the \cs{use:n}. -% \begin{macrocode} -\cs_new:Npn \seq_map_tokens:Nn #1#2 - { - \exp_last_unbraced:Nno - \use_i:nn { \@@_map_tokens:nw {#2} } #1 - \prg_break: - \@@_item:n { } \@@_item:n { } \@@_item:n { } \@@_item:n { } - \prg_break_point: - \prg_break_point:Nn \seq_map_break: { } - } -\cs_generate_variant:Nn \seq_map_tokens:Nn { c } -\cs_new:Npn \@@_map_tokens:nw #1 - #2 \@@_item:n #3 - #4 \@@_item:n #5 - #6 \@@_item:n #7 - #8 \@@_item:n #9 - { - #2 \use:n {#1} {#3} - #4 \use:n {#1} {#5} - #6 \use:n {#1} {#7} - #8 \use:n {#1} {#9} - \@@_map_tokens:nw {#1} - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% { -% \seq_map_variable:NNn, \seq_map_variable:Ncn, -% \seq_map_variable:cNn, \seq_map_variable:ccn -% } -% \UnitTested -% This is just a specialised version of the in-line mapping function, -% using an \texttt{e}-type expansion for the code set up so that the -% number of |#| tokens required is as expected. -% \begin{macrocode} -\cs_new_protected:Npn \seq_map_variable:NNn #1#2#3 - { - \@@_push_item_def:e - { - \tl_set:Nn \exp_not:N #2 {##1} - \exp_not:n {#3} - } - #1 - \prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: } - } -\cs_generate_variant:Nn \seq_map_variable:NNn { Nc } -\cs_generate_variant:Nn \seq_map_variable:NNn { c , cc } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \seq_map_indexed_function:NN, \seq_map_indexed_inline:Nn, -% \@@_map_indexed:nNN, \@@_map_indexed:Nw -% } -% Similar to \cs{seq_map_function:NN} but we keep track of the item -% index as a |;|-delimited argument of \cs{@@_map_indexed:Nw}. -% \begin{macrocode} -\cs_new:Npn \seq_map_indexed_function:NN #1#2 - { - \@@_map_indexed:NN #1#2 - \prg_break_point:Nn \seq_map_break: { } - } -\cs_new_protected:Npn \seq_map_indexed_inline:Nn #1#2 - { - \int_gincr:N \g__kernel_prg_map_int - \cs_gset_protected:cpn - { @@_map_ \int_use:N \g__kernel_prg_map_int :w } ##1##2 {#2} - \exp_args:NNc \@@_map_indexed:NN #1 - { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - \prg_break_point:Nn \seq_map_break: - { \int_gdecr:N \g__kernel_prg_map_int } - } -\cs_new:Npn \@@_map_indexed:NN #1#2 - { - \exp_after:wN \@@_map_indexed:Nw - \exp_after:wN #2 - \int_value:w 1 - \exp_after:wN \use_i:nn - \exp_after:wN ; - #1 - \prg_break: \@@_item:n { } \prg_break_point: - } -\cs_new:Npn \@@_map_indexed:Nw #1#2 ; #3 \@@_item:n #4 - { - #3 - #1 {#2} {#4} - \exp_after:wN \@@_map_indexed:Nw - \exp_after:wN #1 - \int_value:w \int_eval:w 1 + #2 ; - } -% \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_e:NNn, \seq_gset_map_e:NNn} -% \begin{macro}{\@@_set_map_e:NNNn} -% Very similar to \cs{seq_set_filter:NNn}. We could actually -% merge the two within a single function, but it would have weird -% semantics. -% \begin{macrocode} -\cs_new_protected:Npn \seq_set_map_e:NNn - { \@@_set_map_e:NNNn \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_gset_map_e:NNn - { \@@_set_map_e:NNNn \__kernel_tl_gset:Nx } -\cs_new_protected:Npn \@@_set_map_e:NNNn #1#2#3#4 - { - \@@_push_item_def:n { \exp_not:N \@@_item:n {#4} } - #1 #2 { #3 } - \@@_pop_item_def: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_set_map:NNn, \seq_gset_map:NNn} -% \begin{macro}{\@@_set_map:NNNn} -% Similar to \cs{seq_set_map_e:NNn}, but prevents expansion of the -% <inline function>. -% \begin{macrocode} -\cs_new_protected:Npn \seq_set_map:NNn - { \@@_set_map:NNNn \__kernel_tl_set:Nx } -\cs_new_protected:Npn \seq_gset_map:NNn - { \@@_set_map:NNNn \__kernel_tl_gset:Nx } -\cs_new_protected:Npn \@@_set_map:NNNn #1#2#3#4 - { - \@@_push_item_def:n { \exp_not:n { \@@_item:n {#4} } } - #1 #2 { #3 } - \@@_pop_item_def: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_count:N, \seq_count:c} -% \begin{macro}{\@@_count:w, \@@_count_end:w} -% Since counting the items in a sequence is quite common, we optimize -% it by grabbing $8$~items at a time and correspondingly adding $8$ to -% an integer expression. At the end of the loop, |#9| is -% \cs{@@_count_end:w} instead of being empty. It removes |8+| and -% instead places the number of \cs{@@_item:n} that \cs{@@_count:w} -% grabbed before reaching the end of the sequence. -% \begin{macrocode} -\cs_new:Npn \seq_count:N #1 - { - \int_eval:n - { - \exp_after:wN \use_i:nn - \exp_after:wN \@@_count:w - #1 - \@@_count_end:w \@@_item:n 7 - \@@_count_end:w \@@_item:n 6 - \@@_count_end:w \@@_item:n 5 - \@@_count_end:w \@@_item:n 4 - \@@_count_end:w \@@_item:n 3 - \@@_count_end:w \@@_item:n 2 - \@@_count_end:w \@@_item:n 1 - \@@_count_end:w \@@_item:n 0 - \prg_break_point: - } - } -\cs_new:Npn \@@_count:w - #1 \@@_item:n #2 \@@_item:n #3 \@@_item:n #4 \@@_item:n - #5 \@@_item:n #6 \@@_item:n #7 \@@_item:n #8 #9 \@@_item:n - { #9 8 + \@@_count:w } -\cs_new:Npn \@@_count_end:w 8 + \@@_count:w #1#2 \prg_break_point: {#1} -\cs_generate_variant:Nn \seq_count:N { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Using sequences} -% -% \begin{macro}[EXP]{\seq_use:Nnnn, \seq_use:cnnn} -% \begin{macro}[EXP] -% {\@@_use:NNnNnn, \@@_use_setup:w, \@@_use:nwwwwnwn, \@@_use:nwwn} -% \begin{macro}[EXP]{\seq_use:Nn, \seq_use:cn} -% See \cs{clist_use:Nnnn} for a general explanation. The main -% difference is that we use \cs{@@_item:n} as a delimiter rather than -% commas. We also need to add \cs{@@_item:n} at various places, and -% \cs{s_@@}. -% \begin{macrocode} -\cs_new:Npn \seq_use:Nnnn #1#2#3#4 - { - \seq_if_exist:NTF #1 - { - \int_case:nnF { \seq_count:N #1 } - { - { 0 } { } - { 1 } { \exp_after:wN \@@_use:NNnNnn #1 ? { } { } } - { 2 } { \exp_after:wN \@@_use:NNnNnn #1 {#2} } - } - { - \exp_after:wN \@@_use_setup:w #1 \@@_item:n - \s_@@_mark { \@@_use:nwwwwnwn {#3} } - \s_@@_mark { \@@_use:nwwn {#4} } - \s_@@_stop { } - } - } - { - \msg_expandable_error:nnn - { kernel } { bad-variable } {#1} - } - } -\cs_generate_variant:Nn \seq_use:Nnnn { c } -\cs_new:Npn \@@_use:NNnNnn #1#2#3#4#5#6 { \exp_not:n { #3 #6 #5 } } -\cs_new:Npn \@@_use_setup:w \s_@@ { \@@_use:nwwwwnwn { } } -\cs_new:Npn \@@_use:nwwwwnwn - #1 \@@_item:n #2 \@@_item:n #3 \@@_item:n #4#5 - \s_@@_mark #6#7 \s_@@_stop #8 - { - #6 \@@_item:n {#3} \@@_item:n {#4} #5 - \s_@@_mark {#6} #7 \s_@@_stop { #8 #1 #2 } - } -\cs_new:Npn \@@_use:nwwn #1 \@@_item:n #2 #3 \s_@@_stop #4 - { \exp_not:n { #4 #1 #2 } } -\cs_new:Npn \seq_use:Nn #1#2 - { \seq_use:Nnnn #1 {#2} {#2} {#2} } -\cs_generate_variant:Nn \seq_use:Nn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsection{Sequence stacks} -% -% The same functions as for sequences, but with the correct naming. -% -% \begin{macro}{ -% \seq_push:Nn, \seq_push:NV, \seq_push:Nv, \seq_push:Ne, -% \seq_push:No, \seq_push:Nx, -% \seq_push:cn, \seq_push:cV, \seq_push:cv, \seq_push:ce, -% \seq_push:co, \seq_push:cx -% } -% \UnitTested -% \begin{macro}{ -% \seq_gpush:Nn, \seq_gpush:NV, \seq_gpush:Nv, \seq_gpush:Ne, -% \seq_gpush:No, \seq_gpush:Nx, -% \seq_gpush:cn, \seq_gpush:cV, \seq_gpush:cv, \seq_gpush:ce, -% \seq_gpush:co, \seq_gpush:cx -% } -% \UnitTested -% Pushing to a sequence is the same as adding on the left. -% \begin{macrocode} -\cs_new_eq:NN \seq_push:Nn \seq_put_left:Nn -\cs_generate_variant:Nn \seq_push:Nn { NV , Nv , Ne , c , cV , cv , ce } -\cs_generate_variant:Nn \seq_push:Nn { No , Nx , co , cx } -\cs_new_eq:NN \seq_gpush:Nn \seq_gput_left:Nn -\cs_generate_variant:Nn \seq_gpush:Nn { NV , Nv , Ne , c , cV , cv , ce } -\cs_generate_variant:Nn \seq_gpush:Nn { No , Nx , co , cx } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\seq_get:NN, \seq_get:cN} -% \UnitTested -% \begin{macro}{\seq_pop:NN, \seq_pop:cN} -% \UnitTested -% \begin{macro}{\seq_gpop:NN, \seq_gpop:cN} -% \UnitTested -% In most cases, getting items from the stack does not need to specify -% that this is from the left. So alias are provided. -% \begin{macrocode} -\cs_new_eq:NN \seq_get:NN \seq_get_left:NN -\cs_new_eq:NN \seq_get:cN \seq_get_left:cN -\cs_new_eq:NN \seq_pop:NN \seq_pop_left:NN -\cs_new_eq:NN \seq_pop:cN \seq_pop_left:cN -\cs_new_eq:NN \seq_gpop:NN \seq_gpop_left:NN -\cs_new_eq:NN \seq_gpop:cN \seq_gpop_left:cN -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[TF]{\seq_get:NN, \seq_get:cN} -% \begin{macro}[TF]{\seq_pop:NN, \seq_pop:cN} -% \begin{macro}[TF]{\seq_gpop:NN, \seq_gpop:cN} -% More copies. -% \begin{macrocode} -\prg_new_eq_conditional:NNn \seq_get:NN \seq_get_left:NN { T , F , TF } -\prg_new_eq_conditional:NNn \seq_get:cN \seq_get_left:cN { T , F , TF } -\prg_new_eq_conditional:NNn \seq_pop:NN \seq_pop_left:NN { T , F , TF } -\prg_new_eq_conditional:NNn \seq_pop:cN \seq_pop_left:cN { T , F , TF } -\prg_new_eq_conditional:NNn \seq_gpop:NN \seq_gpop_left:NN { T , F , TF } -\prg_new_eq_conditional:NNn \seq_gpop:cN \seq_gpop_left:cN { T , F , TF } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsection{Viewing sequences} -% -% \begin{macro}{\seq_show:N, \seq_show:c, \seq_log:N, \seq_log:c, \@@_show:NN} -% \begin{macro}[rEXP]{\@@_show_validate:nn} -% \UnitTested -% Apply the general \cs{__kernel_chk_tl_type:NnnT}. -% \begin{macrocode} -\cs_new_protected:Npn \seq_show:N { \@@_show:NN \msg_show:nneeee } -\cs_generate_variant:Nn \seq_show:N { c } -\cs_new_protected:Npn \seq_log:N { \@@_show:NN \msg_log:nneeee } -\cs_generate_variant:Nn \seq_log:N { c } -\cs_new_protected:Npn \@@_show:NN #1#2 - { - \__kernel_chk_tl_type:NnnT #2 { seq } - { - \s_@@ - \exp_after:wN \use_i:nn \exp_after:wN \@@_show_validate:nn #2 - \q_recursion_tail \q_recursion_tail \q_recursion_stop - } - { - #1 { seq } { show } - { \token_to_str:N #2 } - { \seq_map_function:NN #2 \msg_show_item:n } - { } { } - } - } -\cs_new:Npn \@@_show_validate:nn #1#2 - { - \quark_if_recursion_tail_stop:n {#2} - \@@_wrap_item:n {#2} - \@@_show_validate:nn - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Scratch sequences} -% -% \begin{variable}{\l_tmpa_seq, \l_tmpb_seq, \g_tmpa_seq, \g_tmpb_seq} -% Temporary comma list variables. -% \begin{macrocode} -\seq_new:N \l_tmpa_seq -\seq_new:N \l_tmpb_seq -\seq_new:N \g_tmpa_seq -\seq_new:N \g_tmpb_seq -% \end{macrocode} -% \end{variable} -% -% \begin{macrocode} -%</package> -% \end{macrocode} -% -% \end{implementation} -% -% \PrintIndex |