% \iffalse
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Modified from l3seq.dtx (LaTeX3 project) by Bruno Le Floch.
%%
%% The original code was under the LPPL, so I guess that one as well.
%%
%% If it is merged as l3seq, the preamble (until and including the title)
%% should be reverted to the current l3seq one.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%<*driver|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: seq-one-braces.dtx 1879 2010-03-29 17:48:38Z bruno $
          {Sequences and stacks with one marker, braced elements.}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{\filename.\filenameext}
\end{document}
%</driver> 
% \fi
%
%
% \title{The \textsf{seq-one-braces} package based on 
%   \textsf{l3seq}\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Sequences}
% \author{\Team{} --- modified by Bruno Le Floch}
% \date{\filedate}
% \maketitle
% \tableofcontents
%
% 
% \begin{documentation}
%
% \LaTeX3 implements a data type called `sequences'. These are special
% token lists that can be accessed via special functions on the `left'.
% Appending tokens is possible at both ends. Appended token lists can be
% accessed only as a union.  The token lists that form the individual
% items of a sequence might contain any tokens except one internal
% functions that is used to structure sequences (see section internal
% functions below).\footnote{Bruno: double-check that.} 
% It is also possible to map functions on such
% sequences so that they are executed for every item on the sequence.
%
% The defined functions are not orthogonal in the sense that every
% possible variation possible is actually available. If you need a new
% variant use the expansion functions described in the package
% \texttt{l3expan} to build it.
%
% Adding items to the left of a sequence can currently be done with
% either something like "\seq_put_left:Nn" or with a ``stack'' function
% like "\seq_push:Nn" which has the same effect.
%
% \section{Functions for creating/initialising sequences}
%
% \begin{function}{ \seq_new:N, \seq_new:c }
% \begin{syntax}
%    "\seq_new:N" <sequence>
% \end{syntax}
% Defines <sequence> to be a variable of type "seq".
% \end{function}
%
% \begin{function}{ \seq_clear:N, \seq_clear:c,
%                  \seq_gclear:N, \seq_gclear:c }
% \begin{syntax}
%   "\seq_clear:N"  <sequence>
% \end{syntax}
% These functions locally or globally clear <sequence>.
% \end{function}
%
% \begin{function}{ \seq_clear_new:N, \seq_clear_new:c,
%                  \seq_gclear_new:N, \seq_gclear_new:c }
% \begin{syntax}
%   "\seq_clear_new:N"  <sequence>
% \end{syntax}
% These functions locally or globally clear <sequence> if it exists or 
% otherwise allocates it.
% \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}
%   "\seq_set_eq:NN" <seq1> <seq2>
%   "\seq_gset_eq:NN" <seq1> <seq2>
% \end{syntax}
% Functions that locally or globally make <seq1> identical to <seq2>.
% \end{function}
%
% \begin{function}{\seq_concat:NNN,  \seq_concat:ccc,
%                  \seq_gconcat:NNN, \seq_gconcat:ccc}
% \begin{syntax}
%   "\seq_concat:NNN"  <seq1> <seq2> <seq3>
%   "\seq_gconcat:NNN" <seq1> <seq2> <seq3>
% \end{syntax}
% Function that conatenates <seq2> and <seq3> and 
% locally or globally assigns the result to <seq1>.
% \end{function}
%
% \section{Adding data to sequences}
%
% \begin{function}{\seq_put_left:Nn,  \seq_put_left:NV,  
%                  \seq_put_left:No,  \seq_put_left:Nx,
%                  \seq_put_left:cn,  \seq_put_left:cV,  
%                  \seq_put_left:co}
% \begin{syntax}
%   "\seq_put_left:Nn" <sequence> <token list>
% \end{syntax}
% Locally  appends <token list> as a single item to the left
% of <sequence>. <token list> might get expanded before
% appending according to the variant.
% \end{function}
%
% \begin{function}{\seq_put_right:Nn, \seq_put_right:NV, 
%                  \seq_put_right:No, \seq_put_right:Nx,
%                  \seq_put_right:cn, \seq_put_right:cV,
%                  \seq_put_right:co}
% \begin{syntax}
%   "\seq_put_right:Nn" <sequence> <token list>
% \end{syntax}
% Locally  appends <token list> as a single item to the right
% of <sequence>. <token list> might get expanded before
% appending according to the variant.
% \end{function}
%
% \begin{function}{\seq_gput_left:Nn, \seq_gput_left:NV, 
%                  \seq_gput_left:No, \seq_gput_left:Nx,
%                  \seq_gput_left:cn, \seq_gput_left:cV, 
%                  \seq_gput_left:co}
% \begin{syntax}
%   "\seq_gput_left:Nn" <sequence> <token list>
% \end{syntax}
% Globally appends <token list> as a single item to the left
% of <sequence>.
% \end{function}
%
% \begin{function}{\seq_gput_right:Nn, \seq_gput_right:NV, 
%                  \seq_gput_right:No, \seq_gput_right:Nx,
%                  \seq_gput_right:cn, \seq_gput_right:cV,
%                  \seq_gput_right:co}
% \begin{syntax}
%   "\seq_gput_right:Nn" <sequence> <token list>
% \end{syntax}
% Globally appends <token list> as a single item to the right
% of <sequence>.
% \end{function}
%
%
% \section{Getting and popping elements from sequences}
%
% It is always faster to map a function over all the items 
% of a seq in one go using one of the "\seq_map" functions
% than to get the items one by one manually by repeatedly 
% using one of the "\seq_get" or "\seq_pop" functions. Of
% course, in some situations you will have to use the
% "\seq_get" and "\seq_pop" family anyways.
%
% Also, accessing a sequence on the left is faster than 
% accessing it from the right.
% 
% \begin{function}{\seq_get_left:NN,
%                  \seq_gget_left:NN,
%                  \seq_get_left_with:Nn}
% \begin{syntax}
%    "\seq_get_left:NN" <sequence> <tl var.>
%    "\seq_get_left_with:Nn" <sequence> <assignment code>
% \end{syntax}
% Functions that assign the left-most item of <sequence> to the
% token list variable <tl var.> or using the <assignment code>.
% The item is not removed from <sequence>! 
% 
% The "_get:" functions perform the assignment locally,
% and the "_gget:" functions perform the assignment globally.
% The function "\seq_get_left_with:Nn" can be used for fancier 
% assignments. For instance, one could have
% \begin{quote}
%   "\seq_get_left_with:Nn" <sequence> "{\cs_gset:Npn \cs_head:n #1}" 
% \end{quote}
% to define "\cs_head:n" to globally take one argument, with a 
% replacement text given by the head of <sequence>.
%
% Bruno: should "\seq_get_left_with" be converted to some "map_left_item"
% function, and made expandable?
% \end{function}
%
%
% \begin{function}{\seq_pop_left:N,
%                  \seq_gpop_left:N,
%                  \seq_pop_left_with:Nn,
%                  \seq_gpop_left_with:Nn}
% \begin{syntax}
%    "\seq_pop_left:N" <sequence> 
%    "\seq_pop_left_with:Nn" <sequence> <assignment code>
% \end{syntax}
% Functions that remove the left-most item of <sequence> 
% (locally for "_pop" and globally for "_gpop"), and assign
% it using <assignment code>. The former construction
% "\seq_pop_left:NN" <sequence> <tl var.> can be written as
% "\seq_pop_left_with:Nn" <sequence> "{\tl_set:Nn" <tl var.> "}".
%
% Bruno: not too happy with that, but it seems better than 
% forcing local assignments to <tl var.>.
% \end{function}
%
%
% \begin{function}{\seq_get_right:NN,
%                  \seq_gget_right:NN,
%                  \seq_get_right_with:Nn}
% \begin{syntax}
%   "\seq_get_right:NN" <sequence> <tl var.>
%   "\seq_get_right_with:Nn" <sequence> \marg{assignment code}
% \end{syntax}
% Same as "\seq_get:NN" et al., except that they assign the 
% right-most element of <sequence>. These functions are slower 
% (how much?), and accessing sequences from the left should be
% preferred.
% \end{function}
%
% \begin{function}{\seq_pop_right:N,
%                  \seq_gpop_right:N,
%                  \seq_pop_right_with:Nn,
%                  \seq_gpop_right_with:Nn,
%                  \seq_pop_right_aux:NNn}
% \begin{syntax}
%   "\seq_gpop_right:N" \meta{sequence}
%   "\seq_gpop_right_with:Nn" \meta{sequence} \marg{assignment code}
% \end{syntax}
% Earlier, there was a "\seq_(g)pop_right:NN", but the name did
% not make it clear that the assignment of the right-most element
% was always local. Their effect can be achieved with 
% "\seq_(g)pop_right_with:Nn" \meta{sequence} "{\tl_set:Nn" \meta{tl-var.} "}".
% \end{function}
% 
% 
% \section{Mapping on sequences}
% 
% \begin{function}{ \seq_map_function:Nn,
%                   \seq_map_function:cn}
% \begin{syntax}
%    "\seq_map_function:Nn" <sequence> <function>
% \end{syntax}
% This function applies <function> (which must be a function with one
% argument, but can be composed of several tokens) to every item of
% <sequence>. <function> is not executed within a sub-group so that
% side effects can be achieved locally. The operation is
% expandable.\footnote{Bruno: nesting?}
%
% In the current implementation the next functions are more 
% efficient and should be preferred if expandability is not an 
% issue.
% \end{function}
%
% \begin{function}{\seq_map_variable:NNn,
%                  \seq_map_variable:cNn}
% \begin{syntax}
%   "\seq_map_variable:NNn" <sequence> <tl var.> \Arg{code using tl var.}
% \end{syntax}
% Every element in <sequence> is assigned to <tl var.> and then <code
% using tl var.> is executed. The operation is not expandable which means
% that it can't be used within write operations etc.\footnote{Bruno: 
%   nesting?}
% \end{function}
% 
% \begin{function}{\seq_map_inline:Nn,
%                  \seq_map_inline:cn}
% \begin{syntax}
%   "\seq_map_inline:Nn" <sequence> \Arg{inline function}
% \end{syntax}
% Applies <inline function> (which should be the direct coding for a
% function with one argument (i.e.\ use "#1" as the place holder for
% this argument)) to every item of <sequence>.  <inline function> is not
% executed within a sub-group so that side effects can be achieved locally.
% The operation is not expandable which means that it can't be used
% within write operations etc.\footnote{Bruno: nesting?}
% \end{function}
%
% \begin{function}{ \seq_break:, \seq_break:n }
% \begin{syntax}
%   "\seq_break:n" \marg{code}
% \end{syntax}
% These functions are used to break out of a mapping 
% function at the point of execution. "\seq_break:n"
% breaks out places \meta{code} \emph{after} doing
% whichever operations are needed to clean up the mapping.
% \end{function}
%
%
% \section{Predicates and conditionals}
%
% \begin{function}{ \seq_if_empty_p:N / (EXP) | 
%                   \seq_if_empty_p:c / (EXP) }
% \begin{syntax}
%   "\seq_if_empty_p:N" <sequence>
% \end{syntax}
% This predicate returns `true' if <sequence> is `empty' i.e., doesn't
% contain any items. Note that this is `false' even if the <sequence> only
% contains a single empty item.
% \end{function}
%
% \begin{function}{ \seq_if_empty:N / (TF) |
%                   \seq_if_empty:c / (TF) }
% \begin{syntax}
%   "\seq_if_empty:NTF" <sequence> \Arg{true code} \Arg{false code}
% \end{syntax}
% Set of conditionals that test whether or not a particular <sequence>
% is empty and if so executes either <true code> or <false code>.
% \end{function}
%
% \begin{function}{ \seq_if_in:Nn / (TF) |
%                   \seq_if_in:NV / (TF) |
%                   \seq_if_in:cn / (TF) |
%                   \seq_if_in:cV / (TF) |
%                   \seq_if_in:co / (TF) |
%                   \seq_if_in:cx / (TF) }
% \begin{syntax}
%   "\seq_if_in:NnTF" <sequence> \Arg{item} \Arg{true code} \Arg{false code}
% \end{syntax}
% Functions that test if <item> is in <sequence>. Depending on the result
% either <true code> or <false code> is executed.
% \end{function}
%
% \begin{function}{ \seq_if_in_str:Nn / (TF) }
% \begin{syntax}
%   "\seq_if_in_str:NnTF" <sequence> \Arg{item} \Arg{true code} \Arg{false code}
% \end{syntax}
% Faster than "\seq_if_in:Nn", but items are compared after
% being passed through "\tl_to_str:n", possibly leading to some false
% positives (catcodes are not compared). Only use these functions if
% speed is an issue, or if you know that the items in your sequence
% are harmless (e.g. sequences of integers).
%
% Also, in some very rare cases where an item contains something
% that looks like the internal function "\seq_elt:n", there can
% be more false positives.
% \end{function}
%
%
% \section{Misc}
% 
% \begin{function}{ \seq_show:N |
%                   \seq_show:c }
% \begin{syntax}
%   "\seq_show:N" <sequence>
% \end{syntax}
% Function that pauses the compilation and displays <seq> in the terminal
% output and in the log file. (Usually used for diagnostic purposes.)
% \end{function}
%
% \begin{function}{ \seq_display:N |
%                   \seq_display:c }
% \begin{syntax}
%   "\seq_display:N" <sequence>
% \end{syntax}
% As with "\seq_show:N" but pretty prints the output one line per element.
% \end{function}
%
% 
% \begin{function}{ \seq_remove_all_in:Nn,
%                   \seq_gremove_all_in:Nn}
% \begin{syntax}
%   "\seq_gremove_all_in:Nn" <sequence> \marg{item}
% \end{syntax}
% Functions that remove every occurence of <item> in <sequence>,
% locally or globally.
% \end{function}
%
%
% \begin{function}{ \seq_remove_duplicates:N,
%                   \seq_gremove_duplicates:N,
%                   \seq_remove_str_duplicates:N,
%                   \seq_gremove_str_duplicates:N }
% \begin{syntax}
%   "\seq_gremove_duplicates:N" <sequence>
% \end{syntax}
% Function that removes any duplicate entries in <sequence>. 
% The "_str" functions are faster, but only compare strings (i.e.,
% the result of "\tl_to_str:n"), and might consider as duplicates 
% two elements which in fact differ. See "\seq_if_in_str:Nn" for
% more on this.
% \end{function}
%
%
% \section{Internal functions}
%
% \begin{function}{\seq_if_empty_err:N,
%                  \seq_if_empty_err_break:N}
% \begin{syntax}
%   "\seq_if_empty_err:N" <sequence>
% \end{syntax}
% Signals an \LaTeX3 error if <sequence> is empty. The 
% "_break" variant attempts to recover by jumping to the
% end of the current seq function (using "\seq_break:").
% \end{function}
%
% \begin{function}{\seq_pop_left_aux:Nnn}
% \begin{syntax}
%   "\seq_pop_left_aux:Nnn" <sequence> <def> <assignment code> 
% \end{syntax}
% Function that assigns the left-most <item> of <sequence> using
% <assignment code> \marg{item} and assigns the tail to <sequence>
% using <def>.
% \end{function}
%
% \begin{function}{\seq_get_left_aux:w,
%                  \seq_pop_left_aux:w}
% Functions used to implement put and get operations. They  are not for
% meant for direct use.
% \end{function}
%
% \begin{function}{ \seq_tmp:w,  \seq_elt:n }
%   "\seq_elt:n" is the back-bone of sequences. Both 
%   "\seq_elt:n" and "\seq_tmp:w" get special meanings during
%   mapping operations. They are otherwise defined to produce
%   an error when expanded.
% \end{function}
%
% \begin{function}{ \seq_break_point:n }
%   Flag placed at the point where "\seq_break:" should 
%   jump to. It takes one argument, which is used to clean
%   up the mapping before the code given by the user 
%   (typically, cleaning up involves restoring the former 
%   definition of "\seq_elt:n" and "\seq_tmp:w").
% \end{function}
%
% \begin{function}{\seq_map_inline_last:Nnn,
%                  \use_ii_bi_repeat:nn}
% \begin{syntax}
%   "\seq_map_inline_last:Nnn" \meta{sequence} 
%   \marg{inline function} \marg{last inline function}
% \end{syntax}
% Applies \meta{inline function} to each item of \meta{sequence} 
% (given as "#1") except the last, and \meta{last inline function}
% on the last item. Mainly used to implement the "pop_right" and
% "get_right" operations.
% \end{function}
%
% \begin{function}{\use_ii_i:nn}
% Exchanges its two arguments (removing one set of outer braces if present).
% \end{function}
% 
%
% \section{Functions for `Sequence Stacks'}
%
% Special sequences in \LaTeX3 are `stacks' with their usual operations
% of `push', `pop', and `top'. They are internally implemented as
% sequences and share some of the functions (like "\seq_new:N" etc.)
%
% \begin{function}{\seq_push:Nn,  \seq_push:NV,
%                  \seq_push:No,  \seq_push:cn,
%                  \seq_gpush:Nn, \seq_gpush:NV,
%                  \seq_gpush:No, \seq_gpush:Nv,
%                  \seq_gpush:Nx,
%                  \seq_gpush:cn, \seq_gpush:cV}
% \begin{syntax}
%   "\seq_push:Nn" <stack> \Arg{token list}
% \end{syntax}
% Locally or globally pushes <token list> as a single item onto the
% <stack>. These are synonyms for "\seq_put_left"
% \end{function}
%
%
% \begin{function}{\seq_get:NN, \seq_gget:NN, \seq_get_with:Nn}
% \begin{syntax}
%    "\seq_get:NN" <stack> <tl var.>
% \end{syntax}
% Functions that assign the top item of <stack> to the <tl var.>.
% Item is \emph{not} removed from <stack>! These are synonyms for
% the "\seq_get_left" family of functions.
% \end{function}
%
% \begin{function}{\seq_pop:N,       \seq_gpop:N, 
%                  \seq_pop_with:Nn, \seq_gpop_with:Nn}
% \begin{syntax}
%   "\seq_pop:N" <stack>
%   "\seq_pop_with:Nn" <stack> <assignment code>
% \end{syntax}
% Remove the top item of the <stack> locally or globally, 
% and assign it using <assignment code>. These functions
% are synonyms of the corresponding "\seq_pop_left" 
% functions.
% \end{function}
%
% \end{documentation}
%
%
%
% \begin{implementation}
%
% \section{\pkg{l3seq} implementation}
%
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\filename}{\filedate}{\fileversion}{\filedescription}
\package_check_loaded_expl:
%</package>
%    \end{macrocode}
%
% A sequence is a control sequence whose top-level expansion is 
% of the form `|\seq_elt:n| \marg{text$\sb1$} \ldots{}
% |\seq_elt:n| \marg{text$\sb{n}$} \ldots'. 
%
% Another choice would be to store each item as "\seq_elt:w" 
% \meta{item} "\seq_elt_end:" instead of "\seq_elt:n" \marg{item}.
% The main argument for that other possibility is that it allows 
% efficient searching of an item using delimited arguments. However,
% this will only work if the item that is searched for does not 
% contain braces nor the macro parameter character "#". Also, using
% explicit delimiters as "\seq_elt:w \meta{item} \seq_elt_end:" leads
% to endless trouble with brace stripping (when an item happens to be
% surrounded by braces).
% 
% We thus store elements as "\seq_elt:n" \marg{item}. There are two
% methods for searching items in the sequence, either in a fully 
% robust way (comparing items with "\tl_if_eq:nn"), or in a fast
% way by working with the result of "\tl_to_str:N". See "\seq_if_in_str:Nn"
% for details.
%
% \begin{macro}{\seq_elt:n}
%    We allocate the delimiter and make it an error if executed.
%    However, it removes its argument (the item of the sequence)
%    to help recover from the error.
%    \begin{macrocode}
%<*initex|package>
\cs_new:Npn \seq_elt:n #1 {\ERROR}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\use_ii_i:nn}
% Convenient macro to shuffle arguments around.
%    \begin{macrocode}
\cs_new:Npn \use_ii_i:nn #1 #2 { #2 #1 }
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Allocating and initialisation}
%
% \begin{macro}{\seq_new:N}
% \begin{macro}{\seq_new:c}
%    Sequences are implemented using token lists.
%    \begin{macrocode}
\cs_new_eq:NN \seq_new:N \tl_new:N
\cs_new_eq:NN \seq_new:c \tl_new:c
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_clear:N}
% \begin{macro}{\seq_clear:c}
% \begin{macro}{\seq_gclear:N}
% \begin{macro}{\seq_gclear:c}
%    Clearing a sequence is the same as clearing a token list.
%    \begin{macrocode}
\cs_new_eq:NN \seq_clear:N  \tl_clear:N
\cs_new_eq:NN \seq_clear:c  \tl_clear:c
\cs_new_eq:NN \seq_gclear:N \tl_gclear:N
\cs_new_eq:NN \seq_gclear:c \tl_gclear:c
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_clear_new:N}
% \begin{macro}{\seq_clear_new:c}
% \begin{macro}{\seq_gclear_new:N}
% \begin{macro}{\seq_gclear_new:c}
%    Clearing a sequence is the same as clearing a token list.
%    \begin{macrocode}
\cs_new_eq:NN \seq_clear_new:N  \tl_clear_new:N
\cs_new_eq:NN \seq_clear_new:c  \tl_clear_new:c
\cs_new_eq:NN \seq_gclear_new:N \tl_gclear_new:N
\cs_new_eq:NN \seq_gclear_new:c \tl_gclear_new:c
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}   
%                              
% \begin{macro}{\seq_set_eq:NN}
% \begin{macro}{\seq_set_eq:Nc} 
% \begin{macro}{\seq_set_eq:cN}
% \begin{macro}{\seq_set_eq:cc} 
%    We can set one "seq" equal to another.
%    \begin{macrocode}                
\cs_new_eq:NN \seq_set_eq:NN \cs_set_eq:NN   
\cs_new_eq:NN \seq_set_eq:cN \cs_set_eq:cN   
\cs_new_eq:NN \seq_set_eq:Nc \cs_set_eq:Nc   
\cs_new_eq:NN \seq_set_eq:cc \cs_set_eq:cc                        
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_gset_eq:NN}
% \begin{macro}{\seq_gset_eq:cN}
% \begin{macro}{\seq_gset_eq:Nc}
% \begin{macro}{\seq_gset_eq:cc}
%    And of course globally which seems to be needed far more
%    often.\footnote{To save a bit of space these functions could be made
%    identical to those from the tl or clist module. Bruno: I don't 
%    understand this comment.}
%    \begin{macrocode}
\cs_new_eq:NN \seq_gset_eq:NN \cs_gset_eq:NN
\cs_new_eq:NN \seq_gset_eq:cN \cs_gset_eq:cN
\cs_new_eq:NN \seq_gset_eq:Nc \cs_gset_eq:Nc
\cs_new_eq:NN \seq_gset_eq:cc \cs_gset_eq:cc
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_concat:NNN,\seq_concat:ccc}
% \begin{syntax}
%   "\seq_concat:NNN" \m{seq~1} \m{seq~2} \m{seq~3} 
% \end{syntax}
% will locally assign \m{seq~1} the concatenation of \m{seq~2} and \m{seq~3}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_concat:NNN #1#2#3 {
  \tl_set:Nx #1 { \exp_not:V #2 \exp_not:V #3 }
}
\cs_generate_variant:Nn \seq_concat:NNN {ccc}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\seq_gconcat:NNN,\seq_gconcat:ccc}
% \begin{syntax}
%   "\seq_gconcat:NNN" \m{seq~1} \m{seq~2} \m{seq~3}
% \end{syntax}
% will globally assign \m{seq~1} the concatenation of \m{seq~2} and \m{seq~3}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_gconcat:NNN #1#2#3 {
  \tl_gset:Nx #1 { \exp_not:V #2 \exp_not:V #3 }
}
\cs_generate_variant:Nn \seq_gconcat:NNN {ccc}
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Putting data in}
%
% \begin{macro}{\seq_put_left:Nn,  \seq_put_left:NV,  
%               \seq_put_left:No,  \seq_put_left:Nx,
%               \seq_put_left:cn,  \seq_put_left:cV,  
%               \seq_put_left:co,
%               \seq_put_right:Nn, \seq_put_right:No, 
%               \seq_put_right:NV, \seq_put_right:Nx,
%               \seq_put_right:cn, \seq_put_right:cV, 
%               \seq_put_right:co}
% Here are the usual operations for adding to the left and 
% right, simply using the corresponding "tl" functions.\footnote{Bruno:
%   The implementation was much more complicated. Am I missing something?} 
%    \begin{macrocode}
\cs_new_protected:Npn \seq_put_left:Nn #1#2 {
  \tl_put_left:Nn #1 {\seq_elt:n {#2} }
}
\cs_new_protected:Npn \seq_put_right:Nn #1#2{
  \tl_put_right:Nn #1 {\seq_elt:n {#2} }
}
\cs_generate_variant:Nn \seq_put_left:Nn {NV,No,Nx,cn,cV,co}
\cs_generate_variant:Nn \seq_put_right:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
%
% 
% 
% \begin{macro}{\seq_gput_left:Nn,  \seq_gput_left:NV,  
%               \seq_gput_left:No,  \seq_gput_left:Nx,
%               \seq_gput_left:cn,  \seq_gput_left:cV,  
%               \seq_gput_left:co,
%               \seq_gput_right:Nn, \seq_gput_right:NV, 
%               \seq_gput_right:No, \seq_gput_right:Nx,
%               \seq_gput_right:cn, \seq_gput_right:cV, 
%               \seq_gput_right:co}
%    \begin{macrocode}
\cs_new_protected:Npn \seq_gput_left:Nn {
%<*check>
  \pref_global_chk:
%</check>
%<*!check> 
  \pref_global:D
%</!check>
  \seq_put_left:Nn
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new_protected:Npn \seq_gput_right:Nn {
%<*check>
  \pref_global_chk:
%</check>
%<*!check> 
  \pref_global:D
%</!check>
  \seq_put_right:Nn
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_generate_variant:Nn \seq_gput_left:Nn {NV,No,Nx,cn,cV,co}
\cs_generate_variant:Nn \seq_gput_right:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
%
%
%
% \subsection{Mapping}
% 
% Many of the operations on sequences are done by mapping through 
% the sequence, so we give the code for those mapping functions 
% early on. As always, three types of mappings: "function", "inline", 
% and "variable". The "function" variant is expandable, the other
% two are not (but they should be faster, because they do not need 
% to test for the end of the sequence). 
%
% I haven't thought yet about nesting.
% 
% \begin{macro}{\seq_break:,
%               \seq_break:n}
% Terminate a mapping function at the point of execution. The latter
% takes an argument to be executed after cleaning up the map.
%    \begin{macrocode}
\cs_new:Npn \seq_break:     #1 \seq_break_point:n #2 {#2}
\cs_new:Npn \seq_break:n #1 #2 \seq_break_point:n #3 {#3 #1}
%    \end{macrocode}
% The argument of "\seq_break_point:n" is always executed before the 
% code provided by the user as an argument of "\seq_break:n". This
% way, the maps can be exited cleanly, and they leave no token after
% the user's code. 
%
% In case the map is not exited via a break, "\seq_break_point:n" simply
% uses its argument. Thus, in every case the argument of 
% "\seq_break_point:n" will be executed.
%    \begin{macrocode}
\cs_new_eq:NN \seq_break_point:n \use:n
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\seq_map_inline:Nn,
%               \seq_map_inline:cn}
% \begin{syntax}
%   "\seq_map_inline:Nn" \meta{sequence} \Arg{inline function}
% \end{syntax}
%  Applies \meta{inline function} to every item in the \meta{sequence}. 
%  The \meta{inline function} should consist of code which will receive
%  the item as "#1". The items in the \meta{sequence} are supplied to the
%  \meta{inline function} reading from the left to the right.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_map_inline:Nn #1#2 {
  \cs_set:Npn \seq_elt:n ##1 {#2}
  #1 
  \seq_break_point:n {\cs_set:Npn \seq_elt:n #1 {\ERROR}}
}
\cs_generate_variant:Nn \seq_map_inline:Nn {c}
%    \end{macrocode}
% The last line in the definition is there to allow breaking the 
% mapping with "\seq_break:" or "\seq_break:n". Bruno: Maybe we 
% should make some general breaking system?
% \end{macro}
%
%
%
% \begin{macro}{\seq_map_variable:NNn,
%               \seq_map_variable:cNn}
% \begin{syntax}
%   "\seq_map_variable:NNn" \meta{sequence} \meta{variable} \marg{function}
% \end{syntax}
% Applies \meta{function} to every item in the \meta{sequence}. The
% item is stored as \meta{variable} before being running \meta{function}.
% The items in the \meta{sequence} are read from left to right.
% 
% The code is essentially the same as for "_map_inline", except that we 
% use "\cs_set:Npx" and "\exp_not:n" so that the user does not need to
% double "#".
%    \begin{macrocode}
\cs_new_protected:Npn \seq_map_variable:NNn #1 #2 #3 {
  \cs_set:Npx \seq_elt:n ##1 { \exp_not:n{\tl_set:Nn #2} {##1} \exp_not:n{#3} }
  #1 
  \seq_break_point:n {\cs_set:Npn \seq_elt:n #1 {\ERROR}}
}
\cs_generate_variant:Nn \seq_map_variable:NNn {c}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\seq_map_function:Nn,
%               \seq_map_function:cn}
% \begin{syntax}
%   "\seq_map_function:Nn" \meta{sequence} \marg{function}
% \end{syntax}
% Applies \meta{function} to every \meta{item} in the 
% \meta{sequence}. Namely, runs \meta{function} \marg{item}
% for each \meta{item} in the \meta{sequence}, from left to 
% right. If the \meta{function} is expandable, this mapping
% will also be. 
%
% Note that \meta{function} can be composed of several tokens!
%    \begin{macrocode}
\cs_new:Npn \seq_map_function:Nn #1 #2 {
  \exp_args:NV \use_ii_i:nn #1 { \seq_map_function_aux:nNn {#2} }
  %\exp_last_unbraced:NnV \seq_map_function_aux:nNn {#2} #1
  \q_recursion_tail {} \q_recursion_stop
  \seq_break_point:n {}
}
\cs_new:Npn \seq_map_function_aux:nNn #1 #2 #3 {
  \quark_if_recursion_tail_stop:N #2
  \use:n {#1 {#3}} 
  \seq_map_function_aux:nNn {#1}
}
%    \end{macrocode}
% 
% Bruno: I'd like to switch all the \cs{..._map_function:NN} 
% commands in expl3 to \texttt{:Nn}.
%    \begin{macrocode}
\cs_generate_variant:Nn \seq_map_function:Nn {c}
%    \end{macrocode}
%
% \begin{texnote}
%   This never expands to \meta{function} \marg{item$\sb1$} \ldots{}
%   \meta{function} \marg{item$\sb n$}, unlike "\prg_replicate:nn".
% \end{texnote}
%
% \end{macro}
%
%
%
% \begin{macro}{\seq_map_inline_last:Nnn,
%               \use_ii_bi_repeat:nn}
% \begin{syntax}
%   "\seq_map_inline_last:Nnn" \meta{sequence} 
%   \Arg{inline function} \Arg{last inline function}
% \end{syntax}
% This function is mainly meant to implement the operations to get and 
% pop items from the right of the \meta{sequence}. Same as
% "\seq_map_inline:Nn", except that we apply \meta{last inline function} 
% to the last element of the \meta{sequence} (instead of the
% \meta{inline function}). It is slightly less efficient.
% 
% At each step in the recursion, we grab one brace group followed by
% either "\seq_elt:n", "\seq_tmp:w", or "\use:n", and we apply that 
% second function to the brace group, then repeat. No need to check 
% for the end of the sequence, since it is automatically triggered
% when swapping the last argument to "\use:n {\seq_break:}".
%
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_map_inline_last:Nnn #1 #2 #3 {
  \cs_set:Npn \seq_elt:n ##1 {#2}
  \cs_set:Npn \seq_tmp:w ##1 {#3}
  \exp_after:wN \exp_after:wN \exp_after:wN \use_ii_bi_repeat:nn 
       \exp_after:wN \use_none:n #1 \seq_tmp:w {\seq_break:} \use:n
  \seq_break_point:n {
    \cs_set:Npn \seq_tmp:w {\ERROR}
    \cs_set:Npn \seq_elt:n #1 {\ERROR}
  }
}
\cs_new:Npn \use_ii_bi_repeat:nn #1 #2 { #2 {#1} \use_ii_bi_repeat:nn }
%    \end{macrocode}
% \end{macro}
% 
%
%
% \subsection{Getting data out}
%
% \subsubsection{From the left (quick)}
%
% \begin{macro}{\seq_get_left:NN,
%               \seq_gget_left:NN,
%               \seq_get_left_with:Nn,
%               \seq_get_left_aux:w}
% \begin{syntax}
%   "\seq_get_left:NN" \meta{sequence} \meta{variable}
%   "\seq_get_left_with:Nn" \meta{sequence} \marg{cmds}
% \end{syntax}
% "\seq_get_left:NN" assigns the left-most element of 
% \meta{sequence} to \meta{variable} using "\tl_set:Nn"
% (hence locally). The "_gget" function does 
% the assignment globally, using "\tl_gset:Nn".
% 
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_get_left:NN #1 #2 {
  \seq_get_left_with:Nn #1 {\tl_set:Nn #2}
}
\cs_new_protected_nopar:Npn \seq_gget_left:NN #1 #2 {
  \seq_get_left_with:Nn #1 {\tl_gset:Nn #2}
}
%    \end{macrocode}
% 
% This is based on the more general "\seq_get_left_with:Nn", 
% which just places \meta{cmds} (presumably an assignment) 
% in front of the left-most element of \meta{sequence}
% (enclosed within braces). That function is meant to be
% used for instance when manipulating sequences whose items
% are a particular type of objects, say, floating points.
% \begin{quote}
%   "\seq_get_left_with:Nn" \meta{sequence} "{\fp_set:Nn" \meta{fp-var} "}"
% \end{quote}
%    \begin{macrocode}
\cs_new_protected:Npn \seq_get_left_with:Nn #1 #2 {
  \seq_if_empty_err_break:N #1 
  \exp_after:wN \seq_get_left_aux:w #1 \q_stop {#2}
  \seq_break_point:n {}
}
\cs_new_protected:Npn \seq_get_left_aux:w \seq_elt:n #1 #2 \q_stop #3 { 
  #3 {#1} 
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\seq_pop_left:N,        \seq_gpop_left:N,
%               \seq_pop_left_with:Nn,  \seq_gpop_left_with:Nn,
%               \seq_pop_left_aux:Nnn,  \seq_pop_left_aux:w}
% \begin{syntax}
%   |\seq_pop_left_aux:Nnn| \meta{sequence} \meta{def} \marg{assignment code}
% \end{syntax}
% applies \meta{assignment code} to the left-most \meta{item} of
% \meta{sequence} in the form \meta{assignment code} \marg{item},
% and assigns the tail of \meta{sequence} to \meta{sequence} using
% \meta{def}. This is used to implement all of the "pop_left" functions.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_pop_left_aux:Nnn #1 #2 #3 {
  \seq_if_empty_err_break:N #1
  \exp_after:wN \seq_pop_left_aux:w #1 \q_stop #1 {#2} {#3}
  \seq_break_point:n {}
}
\cs_new_protected:Npn \seq_pop_left_aux:w \seq_elt:n #1 #2\q_stop #3#4#5 {
  #4 #3 {#2}
  #5    {#1}
}
%    \end{macrocode}
% We can then implement the various "pop_left" functions.
%    \begin{macrocode}
\cs_new:Npn \seq_pop_left:N #1 {
  \seq_pop_left_aux:Nnn #1 {\tl_set:Nn} {\use_none:n}
}
\cs_new:Npn \seq_gpop_left:N #1 {
  \seq_pop_left_aux:Nnn #1 {\tl_gset:Nn} {\use_none:n}
}
\cs_new:Npn \seq_pop_left_with:Nn #1 #2 {
  \seq_pop_left_aux:Nnn #1 {\tl_set:Nn} {#2}
}
\cs_new:Npn \seq_gpop_left_with:Nn #1 #2 {
  \seq_pop_left_aux:Nnn #1 {\tl_gset:Nn} {#2} 
}
%    \end{macrocode} 
% \end{macro}
%
% 
% \subsubsection{From the right (slower)}
% 
% If possible, access the data from the left (see previous section):
% functions which access sequences from the right are slower.
% 
% \begin{macro}{\seq_get_right:NN,
%               \seq_gget_right:NN,
%               \seq_get_right_with:Nn}
% \begin{syntax}
%   "\seq_get_right_with:Nn" \meta{sequence} \marg{assignment}
% \end{syntax}
% Assigns the last element of \meta{sequence} using \meta{assignment}.
% For instance the \meta{assignment} could be "\int_set:Nx \l_tmpa_int".
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_get_right:NN #1#2 {
  \seq_get_right_with:Nn #1 {\tl_set:Nn #2} 
}
\cs_new_protected_nopar:Npn \seq_gget_right:NN #1#2 {
  \seq_get_right_with:Nn #1 {\tl_gset:Nn #2} 
}
\cs_new_protected_nopar:Npn \seq_get_right_with:Nn #1 #2 {
  \seq_map_inline_last:Nnn #1 {} {#2 {##1}}
}
%    \end{macrocode}
% \end{macro} 
% 
% \begin{macro}{\seq_pop_right:N,
%               \seq_gpop_right:N,
%               \seq_pop_right_with:Nn,
%               \seq_gpop_right_with:Nn,
%               \seq_pop_right_aux:NNn}
% \begin{syntax}
%   "\seq_gpop_right:N" \meta{sequence}
%   "\seq_gpop_right_with:Nn" \meta{sequence} \marg{assignment}
% \end{syntax}
% Removes globally the right-most element from \meta{sequence}, and
% assigns that element using \meta{assignment}. Bruno: I don't provide
% "\seq_(g)pop_right:NN" which existed earlier, since their name does
% not make it clear whether the assignment of the tail is global or local.
% 
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_pop_right:N #1 {
  \seq_pop_right_aux:NNn #1 \cs_set_nopar:Npx {\use_none:n}
}
\cs_new_protected_nopar:Npn \seq_gpop_right:N #1 {
  \seq_pop_right_aux:NNn #1 \cs_gset_nopar:Npx {\use_none:n}
}
\cs_new_protected_nopar:Npn \seq_pop_right_with:Nn #1 #2 {
  \seq_pop_right_aux:NNn #1 \cs_set_nopar:Npx {#2}
}
\cs_new_protected_nopar:Npn \seq_gpop_right_with:Nn #1 #2 {
  \seq_pop_right_aux:NNn #1 \cs_gset_nopar:Npx {#2}
}
%    \end{macrocode}
% 
% "\seq_pop_right_aux:NNn #1 #2 {#3}" removes the last element from
% the sequence "#1", and assigns the result back to "#1" locally or
% globally depending on "#2". It then runs "#3" \marg{last item}.
%
% Putting the elements in the resulting sequence one by one using
% "\seq_put_right:Nn" is very slow (quadratic in the size of the 
% sequence). Instead, we store the elements all in one go, using
% the fact that a code like
% \begin{quote}
% "\cs_set_nopar:Npx" \meta{sequence} "{\if_false:}\fi:"      \\
% "\exp_not:n" \marg{item$\sb1$}                       \\
% \ldots{}                                             \\
% "\exp_not:n" \marg{item$\sb {n-1}$}                  \\
%  "\if_false:{\fi:}" \meta{function} \marg{item$\sb n$}
% \end{quote}
% will store the $n-1$ first items in \meta{sequence}, and apply the
% \meta{function} to \marg{item$\sb n$}. The code is rather cryptic,
% but it should take a time linear in the size of the sequence.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_pop_right_aux:NNn #1#2#3 {
  \seq_if_empty_err_break:N #1
  \cs_set:Npn \seq_elt:n ##1 { \exp_not:n{\seq_elt:n {##1}} }
  \cs_set:Npn \seq_tmp:w ##1 { 
    \if_false: { \fi: } % close the assignment
    #3 {##1}            % assign the right-most element
  }
  #2 #1 { \if_false: }\fi:
  \exp_after:wN \exp_after:wN \exp_after:wN \use_ii_bi_repeat:nn 
       \exp_after:wN \use_none:n #1 \seq_tmp:w {\seq_break:} \use:n
  \seq_break_point:n {
    \cs_set:Npn \seq_tmp:w {\ERROR}
    \cs_set:Npn \seq_elt:n #1 {\ERROR}
  }
}
%    \end{macrocode} 
% \end{macro} 
%
%
% \subsection{Predicates and conditionals}
%
% \begin{macro}{\seq_if_empty_p:N,\seq_if_empty_p:c}
% \begin{macro}[TF]{\seq_if_empty:N,\seq_if_empty:c}
%    A predicate which evaluates to |\c_true_bool| iff the sequence is empty.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \seq_if_empty:N \tl_if_empty:N {p,TF,T,F}
\prg_new_eq_conditional:NNn \seq_if_empty:c \tl_if_empty:c {p,TF,T,F}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\seq_if_empty_err:N,
%               \seq_if_empty_err_break:N}
% \begin{syntax}
%   "\seq_if_empty_err_break:N" \meta{sequence}
% \end{syntax}
% Signals an error if the \meta{sequence} is empty.\footnote{Bruno: 
%   think about what to do in an expansion context.}
% The "_break" variant should be preferred: if the sequence is empty,
% it also skips to the next "\seq_break_point:n", allowing better 
% error recovery if used correctly.
% 
%    \begin{macrocode}
\cs_new_nopar:Npn \seq_if_empty_err:N #1 {
  \if_meaning:w #1 \c_empty_tl
    \tl_clear:N \l_kernel_testa_tl % catch prefixes
    \msg_kernel_bug:x {Empty~sequence~`\token_to_str:N#1'}
  \fi:
}
\cs_new_nopar:Npn \seq_if_empty_err_break:N #1 {
  \if_meaning:w #1 \c_empty_tl
    \tl_clear:N \l_kernel_testa_tl % catch prefixes
    \msg_kernel_bug:x {Empty~sequence~`\token_to_str:N#1'}
    \exp_after:wN \seq_break:
  \fi:
}
%    \end{macrocode}
% 
% Bruno: a previous comment on these functions, which I don't understand.
% \begin{quote}
%   As I said before, I don't think we need to provide checks for this
%   kind of error, since it is a severe internal macro package error
%   that can not be produced by the user directly. Can it? So the
%   next line of code should be probably removed.
%   (Will: I have no idea what this comment means.)
% \end{quote}
%
% \end{macro}
%
% \begin{macro}[TF]{\seq_if_in:Nn, \seq_if_in:NV,
%                   \seq_if_in:cn, \seq_if_in:cV,
%                   \seq_if_in:co,\seq_if_in:cx}
% \begin{syntax}
% "\seq_if_in:NnTF" \m{seq}\m{item} \m{true~case} \m{false~case}
% \end{syntax}
% will check whether \m{item} is in \m{seq} and then either execute
% the \m{true~case} or the \m{false~case}.
% 
% We define "\seq_elt:n" to compare its argument with the item we
% are looking for, and then execute the sequence. If the two items
% are equal, then we are done: break, and return true. If the item
% was not found after going through the whole sequence, we break
% and return false. 
% 
% The whole test is inside a group, so that it can be used in cases
% where the definition of "\seq_elt:n" should be preserved (e.g.
% the "remove_duplicates" functions). The group is always closed
% before returning either true or false: see the implementation 
% of "\seq_break_point:n".
%    
%    \begin{macrocode}
\tl_new:N \l_seq_tmpa_tl
\tl_new:N \l_seq_tmpb_tl
\prg_new_protected_conditional:Npnn \seq_if_in:Nn #1 #2 {TF,T,F} {
  \group_begin:
  \tl_set:Nn \l_seq_tmpa_tl {#2}
  \cs_set:Npn \seq_elt:n ##1 {
    \tl_set:Nn \l_seq_tmpb_tl {##1}
    \if_meaning:w \l_seq_tmpa_tl \l_seq_tmpb_tl
    \use_i_after_fi:nw 
    \seq_break:n {\prg_return_true:}
    \fi:
  }
  #1 
  \seq_break:n {\prg_return_false:}
  \seq_break_point:n {\group_end:}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_generate_variant:Nn \seq_if_in:NnTF { NV, cV, co, cn, cx}
\cs_generate_variant:Nn \seq_if_in:NnT  { NV, cV, co, cn, cx}
\cs_generate_variant:Nn \seq_if_in:NnF  { NV, cV, co, cn, cx}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[TF]{\seq_if_in_str:Nn}
% \begin{syntax}
%   "\seq_if_in_str:NnTF" \m{seq}\m{item} \m{true~case} \m{false~case}
% \end{syntax}
% will check whether \m{item} is in \m{seq} and then either execute
% the \m{true~case} or the \m{false~case}.
%    
% Important notice: this test is faster than "\seq_if_in:NnTF", but
% \emph{less robust}: \m{item} is passed through "\tl_to_str:n" before 
% being compared. We use delimited arguments.
% 
% Again, the test is performed inside a group, to avoid potential problems
% with nesting.
%    \begin{macrocode}
\prg_new_protected_conditional:Npnn \seq_if_in_str:Nn #1 #2 {TF,T,F} {
  \group_begin:
  \exp_after:wN \cs_set:Npn \exp_after:wN \seq_tmp:w 
  \exp_after:wN ## \exp_after:wN 1 \tl_to_str:n {\seq_elt:n {#2}} ##2 \q_stop
  {
    \group_end:
    \tl_if_empty:nTF {##2} {\prg_return_false:} {\prg_return_true:}
  }
  \exp_after:wN \seq_tmp:w 
      \tl_to_str:n \exp_after:wN {#1\seq_elt:n {#2}} \q_stop
}
%    \end{macrocode}
% \end{macro}
% 
% 
%
% \subsection{Misc}
%
% \begin{macro}{\seq_show:N, \seq_show:c}
%    \begin{macrocode}
\cs_new_eq:NN \seq_show:N \tl_show:N
\cs_new_eq:NN \seq_show:c \tl_show:c
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\seq_display:N, \seq_display:c}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_display:N #1 {
  \iow_term:x { Sequence~\token_to_str:N #1~contains~
                   the~elements~(without~outer~braces): }
  \toks_clear:N \l_tmpa_toks
  \seq_map_inline:Nn #1 {
    \toks_if_empty:NF  \l_tmpa_toks {
      \toks_put_right:Nx \l_tmpa_toks {^^J>~}
    }
    \toks_put_right:Nx \l_tmpa_toks {
      \c_space_tl \iow_char:N \{ \exp_not:n {##1} \iow_char:N \}
    }
  }
  \toks_show:N \l_tmpa_toks
}
\cs_generate_variant:Nn \seq_display:N {c}
%    \end{macrocode}
% \end{macro}
% 
% 
% \begin{macro}[aux]{\l_seq_remove_seq}
%   A common scratch space for the removal routines.
%    \begin{macrocode}
\seq_new:N \l_seq_remove_seq
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\seq_remove_all_in:Nn}
% This seems to be used in "l3file.dtx" under the name
% "\seq_remove_element:Nn". The version here is quite inefficient.
% It would be better to go through the list once, find at which
% position(s) the item appears, and then do a trick similar to
% the efficient implementation of "\seq_pop_right" functions.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_remove_all_in:Nn #1 #2 {
  \seq_clear:N \l_seq_remove_seq
  \seq_map_inline:Nn #1 {
    \tl_if_eq:nnF {#2} {##1} {\seq_put_right:Nn \l_seq_remove_seq {##1} }
  }
  \seq_set_eq:NN #1 \l_seq_remove_seq
}
\cs_new_protected:Npn \seq_gremove_all_in:Nn #1 #2 {
  \seq_clear:N \l_seq_remove_seq
  \seq_map_inline:Nn #1 {
    \tl_if_eq:nnF {#2} {##1} {\seq_put_right:Nn \l_seq_remove_seq {##1} }
  }
  \seq_gset_eq:NN #1 \l_seq_remove_seq
}
%    \end{macrocode}
% \end{macro}
% 
% 
% \begin{macro}[aux]{\seq_remove_duplicates_aux:NNN}
% \begin{macro}[aux]{\seq_remove_duplicates_aux:Nn}
% \begin{macro}{\seq_remove_duplicates:N,
%               \seq_gremove_duplicates:N,
%               \seq_remove_str_duplicates:N,
%               \seq_gremove_str_duplicates:N}
% Copied from "\clist_remove_duplicates", with a small
% modification to get the "_str" variants in the same go.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_remove_duplicates_aux:NNN #1 #2 #3 {
  \seq_clear:N \l_seq_remove_seq
  \seq_map_function:Nn #3 {\seq_remove_duplicates_aux:Nn #1}
  #2 #3 \l_seq_remove_seq
}
\cs_new_protected:Npn \seq_remove_duplicates_aux:Nn #1 #2 {
  #1 \l_seq_remove_seq {#2} {
    \seq_put_right:Nn \l_seq_remove_seq {#2}
  }
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_remove_duplicates:N {
  \seq_remove_duplicates_aux:NNN \seq_if_in:NnF \seq_set_eq:NN }
\cs_new_protected_nopar:Npn \seq_gremove_duplicates:N {
  \seq_remove_duplicates_aux:NNN \seq_if_in:NnF \seq_gset_eq:NN }
\cs_new_protected_nopar:Npn \seq_remove_str_duplicates:N {
  \seq_remove_duplicates_aux:NNN \seq_if_in_str:NnF \seq_set_eq:NN }
\cs_new_protected_nopar:Npn \seq_gremove_str_duplicates:N {
  \seq_remove_duplicates_aux:NNN \seq_if_in_str:NnF \seq_gset_eq:NN }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \subsection{Sequence stacks}
%
% 
% \begin{macro}{\seq_push:Nn,
%               \seq_push:NV,
%               \seq_push:No,
%               \seq_push:cn,
%               \seq_pop:N,
%               \seq_pop_with:Nn}
% Since sequences can be used as stacks, we ought to have both 
% `push' and `pop'. They are nothing more then new
% names for old functions.
%    \begin{macrocode}
\cs_new_eq:NN \seq_push:Nn      \seq_put_left:Nn
\cs_new_eq:NN \seq_push:NV      \seq_put_left:NV
\cs_new_eq:NN \seq_push:No      \seq_put_left:No
\cs_new_eq:NN \seq_push:cn      \seq_put_left:cn
\cs_new_eq:NN \seq_pop:N        \seq_pop_left:N
\cs_new_eq:NN \seq_pop_with:Nn  \seq_pop_left_with:Nn
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\seq_gpush:Nn,
%               \seq_gpush:NV,
%               \seq_gpush:No,
%               \seq_gpush:Nx,
%               \seq_gpush:cn,
%               \seq_gpush:cV,
%               \seq_gpush:Nv,
%               \seq_gpop:N, 
%               \seq_gpop_with:Nn}
% I (who?) don't agree with Denys that one needs only local stacks,
% actually I believe that one will probably need the functions
% here more often. "\seq_gpop:NN" was removed, because it is unclear
% that the value is returned locally. Use "\seq_gpop_with:Nn" 
% \meta{sequence} "{\tl_set:Nn" \meta{tl-var.} "}" instead.
% nevertheless returned locally.
%    \begin{macrocode}
\cs_new_eq:NN  \seq_gpush:Nn     \seq_gput_left:Nn
\cs_new_eq:NN  \seq_gpush:NV     \seq_gput_left:NV
\cs_new_eq:NN  \seq_gpush:No     \seq_gput_left:No
\cs_new_eq:NN  \seq_gpush:Nx     \seq_gput_left:Nx
\cs_new_eq:NN  \seq_gpush:cn     \seq_gput_left:cn
\cs_new_eq:NN  \seq_gpush:cV     \seq_gput_left:cV
\cs_generate_variant:Nn \seq_gpush:Nn {Nv}
\cs_new_eq:NN  \seq_gpop:N       \seq_gpop_left:N
\cs_new_eq:NN  \seq_gpop_with:Nn \seq_gpop_left_with:Nn
%    \end{macrocode}
% \end{macro}
% 
%
% \begin{macro}{\seq_get:NN, \seq_gget:NN, \seq_get_with:Nn}
% Looking at the top element of the stack without removing it is
% done with this operation.
%    \begin{macrocode}
\cs_new_eq:NN \seq_get:NN \seq_get_left:NN
\cs_new_eq:NN \seq_gget:NN \seq_gget_left:NN
\cs_new_eq:NN \seq_get_with:Nn \seq_get_left_with:Nn
%    \end{macrocode}
% \end{macro}
%
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
%    Show token usage:
%    \begin{macrocode}
%<*showmemory>
%\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
% \PrintIndex
%
% \endinput
