% \iffalse
%% File: l3clist.dtx Copyright (C) 2005-2008 Frank Mittelbach, LaTeX3 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
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: l3clist.dtx 1441 2009-08-05 19:23:23Z joseph $
       {L3 Experimental comma separated lists}
%\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{l3clist} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Comma separated lists}
% \author{Frank Mittelbach}
% \date{\filedate}
% \maketitle
%
% \begin{documentation}
%
% \LaTeX3 implements a data type called `clist (comma-lists)'. These
% are special
% token lists that can be accessed via special function 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 comma-list might contain any tokens except for commas that
% are used to structure comma-lists (braces are need if commas are
% part of the value).  It is also possible to map functions on such
% comma-lists so that they are executed for every item of the comma-list.
%
% All functions that return items from a comma-list in some \m{tl var.}~assume
% that the \m{tl var.}~is local. See remarks below if you need a global
% returned value.
%
% 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 comma-list can currently be done with
% either something like "\clist_put_left:Nn" or with a ``stack'' function
% like "\clist_push:Nn" which has the same effect. Maybe one should
% therefore remove the ``left'' functions totally.
%
% \section{Functions for creating/initialising comma-lists}
%
% \begin{function}{%
%                  \clist_new:N |
%                  \clist_new:c |
% }
% \begin{syntax}
%    "\clist_new:N" <comma-list>
% \end{syntax}
% Defines <comma-list> to be a variable of type clist.
% \end{function}
%
% \begin{function}{%
%                  \clist_clear:N |
%                  \clist_clear:c |
%                  \clist_gclear:N |
%                  \clist_gclear:c |
% }
% \begin{syntax}
%   "\clist_clear:N"  <comma-list>
% \end{syntax}
% These functions locally or globally clear <comma-list>.
% \end{function}
%
% \begin{function}{ \clist_clear_new:N |
%                   \clist_clear_new:c |
%                   \clist_gclear_new:N |
%                   \clist_gclear_new:c }
% \begin{syntax}
%   "\clist_clear_new:N"  <comma-list>
% \end{syntax}
% These functions locally or globally clear <comma-list> if it exists or 
% otherwise allocates it.
% \end{function}
%
% \begin{function}{ \clist_set_eq:NN |
%                   \clist_set_eq:cN |
%                   \clist_set_eq:Nc |
%                   \clist_set_eq:cc }
% \begin{syntax}
%   "\clist_set_eq:NN" <clist1> <clist2>
% \end{syntax}
% Function that locally makes <clist1> identical to <clist2>.
% \end{function}
%
%
% \begin{function}{ \clist_gset_eq:NN |
%                   \clist_gset_eq:cN |
%                   \clist_gset_eq:Nc |
%                   \clist_gset_eq:cc }
% \begin{syntax}
%   "\clist_gset_eq:NN" <clist1> <clist2>
% \end{syntax}
% Function that globally makes <clist1> identical to <clist2>.
% \end{function}
%
%
% \begin{function}{\clist_set_from_seq:NN|\clist_gset_from_seq:NN}
% \begin{syntax}
% "\clist_set_from_seq:NN" <clist> <seq>
% \end{syntax}
% Transforms sequence <seq> into comma-list variable <clist>.
% \end{function}
%
%
% \section{Putting data in}
%
% \begin{function}{%
%                  \clist_put_left:Nn |
%                  \clist_put_left:NV |
%                  \clist_put_left:No |
%                  \clist_put_left:Nx |
%                  \clist_put_left:cn |
%                  \clist_put_left:co |
%                  \clist_put_left:cV |
% }
% \begin{syntax}
%   "\clist_put_left:Nn" <comma-list> <token list>
% \end{syntax}
% Locally  appends <token list> as a single item to the left
% of <comma-list>. <token list> might get expanded before
% appending according to the variant used.
% \end{function}
%
% \begin{function}{%
%                  \clist_put_right:Nn |
%                  \clist_put_right:No |
%                  \clist_put_right:NV |
%                  \clist_put_right:Nx |
%                  \clist_put_right:cn |
%                  \clist_put_right:co |
%                  \clist_put_right:cV |
% }
% \begin{syntax}
%   "\clist_put_right:Nn" <comma-list> <token list>
% \end{syntax}
% Locally  appends <token list> as a single item to the right
% of <comma-list>. <token list> might get expanded before
% appending according to the variant used.
% \end{function}
%
% \begin{function}{%
%                  \clist_gput_left:Nn |
%                  \clist_gput_left:NV |
%                  \clist_gput_left:No |
%                  \clist_gput_left:Nx |
%                  \clist_gput_left:cn |
%                  \clist_gput_left:cV |
%                  \clist_gput_left:co |
% }
% \begin{syntax}
%   "\clist_gput_left:Nn" <comma-list> <token list>
% \end{syntax}
% Globally appends <token list> as a single item to the 
% right of <comma-list>.
% \end{function}
%
% \begin{function}{%
%                  \clist_gput_right:Nn |
%                  \clist_gput_right:NV |
%                  \clist_gput_right:No |
%                  \clist_gput_right:Nx |
%                  \clist_gput_right:cn |
%                  \clist_gput_right:cV |
%                  \clist_gput_right:co |
% }
% \begin{syntax}
%   "\clist_gput_right:Nn" <comma-list> <token list>
% \end{syntax}
% Globally appends <token list> as a single item to the 
% right of <comma-list>.
% \end{function}
%
% \section{Getting data out}
%
% \begin{function}{ \clist_use:N |
%                   \clist_use:c }
% \begin{syntax}
%   "\clist_use:N" <clist>
% \end{syntax}
% Function that inserts the <clist> into the processing stream. Mainly
% useful if one knows what the <clist> contains, e.g., for displaying
% the content of template parameters.
% \end{function}
%
% \begin{function}{ \clist_show:N |
%                   \clist_show:c }
% \begin{syntax}
%   "\clist_show:N" <clist>
% \end{syntax}
% Function that pauses the compilation and displays <clist> in the terminal
% output and in the log file. (Usually used for diagnostic purposes.)
% \end{function}
%
% \begin{function}{ \clist_display:N |
%                   \clist_display:c }
% \begin{syntax}
%   "\clist_display:N" <clist>
% \end{syntax}
% As with "\clist_show:N" but pretty prints the output one line per element.
% \end{function}
%
% \begin{function}{ \clist_get:NN |
%                   \clist_get:cN }
% \begin{syntax}
%    "\clist_get:NN" <comma-list> <tl var.>
% \end{syntax}
% Functions that locally assign the left-most item of <comma-list> to the
% token list variable <tl var.>. Item is not removed from <comma-list>! If you
% need a global return value you need to code something like this:
% \begin{quote}
%   "\clist_get:NN" <comma-list> "\l_tmpa_tl" \\
%   "\tl_gset_eq:NN" <global tl var.> "\l_tmpa_tl"
% \end{quote}
% But if this kind of construction is used often enough a separate
% function should be provided.
% \end{function}
%
%
% \section{Mapping functions}
%
%
% We provide three types of mapping functions, each with their own
% strengths. The "\clist_map_function:NN" is expandable whereas
% "\clist_map_inline:Nn" type uses "##1" as a placeholder for the
% current item in \m{clist}.  Finally we have the
% "\clist_map_variable:NNn" type which uses a user-defined variable as
% placeholder. Both the |_inline| and |_variable| versions are nestable.
%
%
% \begin{function}{\clist_map_function:NN|
%                  \clist_map_function:cN|
%                  \clist_map_function:nN
% }
% \begin{syntax}
%    "\clist_map_function:NN" <comma-list> <function>
% \end{syntax}
% This function applies <function> (which must be a function with one
% argument) to every item of <comma-list>. <function> is not executed
% within a sub-group so that side effects can be achieved locally. The
% operation is expandable which means that it can be used within write
% operations etc.
% \end{function}
%
% \begin{function}{\clist_map_inline:Nn |
%                  \clist_map_inline:cn |
%                  \clist_map_inline:nn |
% }
% \begin{syntax}
%   "\clist_map_inline:Nn" <comma-list> \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 placeholder for
% this argument)) to every item of <comma-list>.  <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. These functions can be nested.
% \end{function}
%
%
% \begin{function}{\clist_map_variable:NNn |
%                  \clist_map_variable:cNn |
%                  \clist_map_variable:nNn |
% }
% \begin{syntax}
%   "\clist_map_variable:NNn" <comma-list> <temp-var> \Arg{action}
% \end{syntax}
% Assigns <temp-var> to each element in <clist> and then executes
% <action> which should contain <temp-var>. As the
% operation performs an assignment, it is not expandable.
% \begin{texnote}
%   These functions resemble the \LaTeXe{} function \tn{@for} but does
%   not borrow the somewhat strange syntax.
% \end{texnote}
% \end{function}
%
%  \begin{function}{%
%                   \clist_map_break: |
%  }
%  \begin{syntax}
%     "\clist_map_break:"
%  \end{syntax}
%  For breaking out of a loop. To be used inside "TF" type functions as
%  in the example below.
%  \begin{verbatim}
%  \cs_new_nopar:Npn \test_function:n #1 {
%    \intexpr_compare:nTF {#1 > 3} {\clist_map_break:}{``#1''}
%  }
%  \clist_map_function:nN {1,2,3,4,5,6,7,8}\test_function:n
%  \end{verbatim}
%  This would return "``1''``2''``3''".
%  \end{function}
%
%
% \section{Predicates and conditionals}
%
% \begin{function}{ \clist_if_empty_p:N | 
%                   \clist_if_empty_p:c }
% \begin{syntax}
%   "\clist_if_empty_p:N" <comma-list>
% \end{syntax}
% This predicate returns `true' if <comma-list> is `empty' i.e., doesn't
% contain any tokens.
% \end{function}
%
% \begin{function}{ \clist_if_empty:N / (TF)(EXP) |
%                   \clist_if_empty:c / (TF)(EXP)}
% \begin{syntax}
%   "\clist_if_empty:NTF" <comma-list> \Arg{true code} \Arg{false code}
% \end{syntax}
% Set of conditionals that test whether or not a particular <comma-list>
% is empty and if so executes either <true code> or <false code>.
% \end{function}
%
% \begin{function}{ \clist_if_eq_p:NN / (EXP) | 
%                   \clist_if_eq_p:cN / (EXP) | 
%                   \clist_if_eq_p:Nc / (EXP) | 
%                   \clist_if_eq_p:cc / (EXP) }
% \begin{syntax}
%   "\clist_if_eq_p:N" <comma-list1> <comma-list2>
% \end{syntax}
% This predicate returns `true' if the two comma lists are identical.
% \end{function}
%
% \begin{function}{ \clist_if_eq:NN / (TF)(EXP) |
%                   \clist_if_eq:cN / (TF)(EXP) |
%                   \clist_if_eq:Nc / (TF)(EXP) |
%                   \clist_if_eq:cc / (TF)(EXP) }
% \begin{syntax}
%   "\clist_if_eq:NNTF" <comma-list1> <comma-list2> \Arg{true code} \Arg{false code}
% \end{syntax}
% Check if <comma-list1> and <comma-list2> are equal and execute
% either <true code> or <false code> accordingly.
% \end{function}
%
% \begin{function}{ \clist_if_in:Nn / (TF) |
%                   \clist_if_in:NV / (TF) |
%                   \clist_if_in:No / (TF) |
%                   \clist_if_in:cn / (TF) |
%                   \clist_if_in:cV / (TF) |
%                   \clist_if_in:co / (TF) }
% \begin{syntax}
%   "\clist_if_in:NnTF" <comma-list> \Arg{item} \Arg{true code} \Arg{false code}
% \end{syntax}
% Function that tests if <item> is in <comma-list>. Depending on the result
% either <true code> or <false code> is executed.
% \end{function}
%
% \section{Higher level functions}
%
% \begin{function}{ \clist_concat:NNN  |
%                   \clist_concat:ccc  |
%                   \clist_gconcat:NNN |
%                   \clist_gconcat:ccc }
% \begin{syntax}
%   "\clist_gconcat:NNN" <clist1> <clist2> <clist3>
% \end{syntax}
% Function that concatenates <clist2> and <clist3> and locally or globally 
% assigns the result to <clist1>.
% \end{function}
%
%
% \begin{function}{ \clist_remove_duplicates:N  |
%                   \clist_gremove_duplicates:N }
% \begin{syntax}
%   "\clist_gremove_duplicates:N" <clist>
% \end{syntax}
% Function that removes any duplicate entries in <clist>.
% \end{function}
% 
% \begin{function}{ 
%   \clist_remove_element:Nn  |
%   \clist_gremove_element:Nn 
%}
% \begin{syntax}
%   "\clist_gremove_element:Nn" <clist> <element>
% \end{syntax}
% Function that removes <element> from <clist>, if present.
% \begin{texnote}
%   This is similar in concept to \cs{@removeelement}, except that the
%   syntax is clearer and the initial and final lists have the same 
%   name automatically.
% \end{texnote}
% \end{function}
%
% \section{Functions for `comma-list stacks'}
%
% Special comma-lists in \LaTeX3 are `stacks' with their usual operations
% of `push', `pop', and `top'. They are internally implemented as
% comma-lists and share some of the functions (like "\clist_new:N" etc.)
%
%
% \begin{function}{%
%                  \clist_push:Nn |
%                  \clist_push:NV |
%                  \clist_push:No |
%                  \clist_push:cn |
%                  \clist_gpush:Nn |
%                  \clist_gpush:NV |
%                  \clist_gpush:No |
%                  \clist_gpush:cn |
% }
% \begin{syntax}
%   "\clist_push:Nn" <stack> \Arg{token list}
% \end{syntax}
% Locally or globally pushes <token list> as a single item onto the
% <stack>. <token list> might get expanded before the operation.
% \end{function}
%
% \begin{function}{%
%                  \clist_pop:NN |
%                  \clist_pop:cN |
%                  \clist_gpop:NN |
%                  \clist_gpop:cN |
% }
% \begin{syntax}
%    "\clist_pop:NN" <stack> <tl var.>
% \end{syntax}
% Functions that assign the top item of <stack> to the token
% list variable <tl var.> and removes it from <stack>!
% \end{function}
%
% \begin{function}{%
%                  \clist_top:NN |
%                  \clist_top:cN |
% }
% \begin{syntax}
%    "\clist_top:NN" <stack> <tl var.>
% \end{syntax}
% Functions that locally assign the top item of <stack> to the token
% list variable <tl var.>. Item is not removed from <stack>!
% \end{function}
%
% \section{Internal functions}
%
% \begin{function}{\clist_if_empty_err:N}
% \begin{syntax}
%   "\clist_if_empty_err:N" <comma-list>
% \end{syntax}
% Signals an \LaTeX3 error if <comma-list> is empty.
% \end{function}
%
% \begin{function}{\clist_pop_aux:nnNN}
% \begin{syntax}
%   "\clist_pop_aux:nnNN" <assign1> <assign2> <comma-list> <tl var.>
% \end{syntax}
% Function that assigns the left-most item of <comma-list> to <tl var.> using
% <assign1> and assigns the tail to <comma-list> using <assign2>. This
% function could be used to implement a global return function.
% \end{function}
%
% \begin{function}{%
%                  \clist_get_aux:w |
%                  \clist_pop_aux:w |
%                  \clist_pop_auxi:w |
%                  \clist_put_aux:NNnnNn |
% }
%  \begin{syntax}\end{syntax}
% Functions used to implement put and get operations. They  are not for
% meant for direct use.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3clist} implementation}
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\filename}{\filedate}{\fileversion}{\filedescription}
\package_check_loaded_expl:
%</package>
%<*initex|package>
%    \end{macrocode}
%
% \subsection{Allocation and initialisation}
%
% \begin{macro}{\clist_new:N}
% \begin{macro}{\clist_new:c}
%    Comma-Lists are implemented using token lists.
%    \begin{macrocode}
\cs_new_eq:NN \clist_new:N \tl_new:N
\cs_generate_variant:Nn \clist_new:N {c}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_clear:N}
% \begin{macro}{\clist_clear:c}
% \begin{macro}{\clist_gclear:N}
% \begin{macro}{\clist_gclear:c}
%    Clearing a comma-list is the same as clearing a token list.
%    \begin{macrocode}
\cs_new_eq:NN \clist_clear:N  \tl_clear:N
\cs_generate_variant:Nn \clist_clear:N {c}
\cs_new_eq:NN \clist_gclear:N \tl_gclear:N
\cs_generate_variant:Nn \clist_gclear:N {c}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\clist_clear_new:N}
% \begin{macro}{\clist_clear_new:c}
% \begin{macro}{\clist_gclear_new:N}
% \begin{macro}{\clist_gclear_new:c}
%    Clearing a comma-list is the same as clearing a token list.
%    \begin{macrocode}
\cs_new_eq:NN \clist_clear_new:N  \tl_clear_new:N
\cs_generate_variant:Nn \clist_clear_new:N {c}
\cs_new_eq:NN \clist_gclear_new:N \tl_gclear_new:N
\cs_generate_variant:Nn \clist_gclear_new:N {c}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_set_eq:NN}
% \begin{macro}{\clist_set_eq:cN}
% \begin{macro}{\clist_set_eq:Nc}
% \begin{macro}{\clist_set_eq:cc}
%    We can set one \meta{clist} equal to another.
%    \begin{macrocode}
\cs_new_eq:NN \clist_set_eq:NN \cs_set_eq:NN
\cs_new_eq:NN \clist_set_eq:cN \cs_set_eq:cN
\cs_new_eq:NN \clist_set_eq:Nc \cs_set_eq:Nc
\cs_new_eq:NN \clist_set_eq:cc \cs_set_eq:cc
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\clist_gset_eq:NN}
% \begin{macro}{\clist_gset_eq:cN}
% \begin{macro}{\clist_gset_eq:Nc}
% \begin{macro}{\clist_gset_eq:cc}
%    An of course globally which seems to be needed far more often.
%    \begin{macrocode}
\cs_new_eq:NN \clist_gset_eq:NN \cs_gset_eq:NN
\cs_new_eq:NN \clist_gset_eq:cN \cs_gset_eq:cN
\cs_new_eq:NN \clist_gset_eq:Nc \cs_gset_eq:Nc
\cs_new_eq:NN \clist_gset_eq:cc \cs_gset_eq:cc
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_set_from_seq:NN,\clist_gset_from_seq:NN}
% I hope this technique is more efficient than looping through each element
% and using "\clist_put_right:Nn" (Will).
%    \begin{macrocode}
\cs_new:Npn \clist_set_from_seq_aux:NNN #1#2#3 {
  \cs_set:Npn \seq_elt:w ##1 \seq_elt_end: ##2 {
    \exp_not:n {##1}
    \quark_if_nil:NF ##2 { , ##2 }
  }
  #1 #2 { #3 \q_nil }
}
\cs_new:Npn \clist_set_from_seq:NN  { \clist_set_from_seq_aux:NNN \tl_set:Nx  }
\cs_new:Npn \clist_gset_from_seq:NN { \clist_set_from_seq_aux:NNN \tl_gset:Nx }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Predicates and conditionals}
%
% \begin{macro}{\clist_if_empty_p:N,\clist_if_empty_p:c}
% \begin{macro}[TF]{\clist_if_empty:N,\clist_if_empty:c}
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \clist_if_empty:N \tl_if_empty:N {p,TF,T,F}
\prg_new_eq_conditional:NNn \clist_if_empty:c \tl_if_empty:c {p,TF,T,F}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\clist_if_empty_err:N}
%   Signals an error if the comma-list is empty.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_if_empty_err:N #1 {
  \if_meaning:w #1 \c_empty_tl
    \tl_clear:N \l_testa_tl % catch prefixes
    \msg_kernel_bug:x {Empty~comma-list~`\token_to_str:N #1'}
  \fi:
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\clist_if_eq_p:NN,\clist_if_eq_p:Nc,
%               \clist_if_eq_p:cN,\clist_if_eq_p:cc}
% \begin{macro}[TF]{\clist_if_eq:NN,\clist_if_eq:cN,
%                   \clist_if_eq:Nc,\clist_if_eq:cc}
%   Returns |\c_true| iff the two comma-lists are equal.
%    \begin{macrocode}
\prg_new_eq_conditional:NNn \clist_if_eq:NN \tl_if_eq:NN {p,TF,T,F}
\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN {p,TF,T,F}
\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc {p,TF,T,F}
\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc {p,TF,T,F}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[TF]{\clist_if_in:Nn}
% \begin{macro}[TF]{\clist_if_in:NV,\clist_if_in:No,\clist_if_in:cn,
%   \clist_if_in:cV,\clist_if_in:co}
%    |\clist_if_in:NnTF| \m{clist}\m{item} \m{true~case} \m{false~case}
%    will check whether \m{item} is in \m{clist} and then either execute
%    the \m{true~case} or the \m{false~case}. \m{true~case} and
%    \m{false~case} may contain incomplete |\if_charcode:w|
%    statements.
%    \begin{macrocode}
\prg_new_conditional:Nnn \clist_if_in:Nn {TF,T,F} {
  \cs_set:Npn \clist_tmp:w ##1,#2,##2##3 \q_stop {
    \if_meaning:w \q_no_value ##2
      \prg_return_false: \else: \prg_return_true: \fi:
  }
  \exp_last_unbraced:NNo \clist_tmp:w , #1 , #2 , \q_no_value \q_stop
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_generate_variant:Nn \clist_if_in:NnTF {NV,No,cn,cV,co}
\cs_generate_variant:Nn \clist_if_in:NnT {NV,No,cn,cV,co}
\cs_generate_variant:Nn \clist_if_in:NnF {NV,No,cn,cV,co}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsection{Retrieving data}
%
% \begin{macro}{\clist_use:N}
% \begin{macro}{\clist_use:c}
% Using a \meta{clist} is just executing it but
% if \m{clist} equals |\scan_stop:| it is probably stemming
% from a |\cs:w ... \cs_end:| that was created by mistake somewhere.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_use:N #1 {
  \if_meaning:w #1 \scan_stop:
    \msg_kernel_bug:x {
      Comma~list~ `\token_to_str:N #1'~ has~ an~ erroneous~ structure!}
  \else:
    \exp_after:wN #1
  \fi:
}
\cs_generate_variant:Nn \clist_use:N {c}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_get:NN}
% \begin{macro}{\clist_get:cN}
% \begin{macro}{\clist_get_aux:w}
%    |\clist_get:NN |\meta{comma-list}\meta{cmd} defines \meta{cmd} to be the
%    left-most element of \meta{comma-list}.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_get:NN #1 {
  \clist_if_empty_err:N #1
  \exp_after:wN \clist_get_aux:w #1,\q_stop
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn \clist_get_aux:w  #1,#2\q_stop #3 { \tl_set:Nn #3{#1} }
%    \end{macrocode}
%    \begin{macrocode}
\cs_generate_variant:Nn \clist_get:NN {cN}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_pop_aux:nnNN}
% \begin{macro}{\clist_pop_aux:w}
% \begin{macro}{\clist_pop_auxi:w}
%    |\clist_pop_aux:nnNN| \meta{def$\sb1$} \meta{def$\sb2$} \meta{comma-list}
%    \meta{cmd} assigns the left-most element of \meta{comma-list} to
%    \meta{cmd} using \meta{def$\sb2$}, and assigns the tail of
%    \meta{comma-list} to \meta{comma-list} using \meta{def$\sb1$}.
%    \begin{macrocode}
\cs_new:Npn \clist_pop_aux:nnNN #1#2#3 {
  \clist_if_empty_err:N #3
  \exp_after:wN \clist_pop_aux:w #3,\q_nil\q_stop #1#2#3
}
%    \end{macrocode}
% After the assignmnets below, if there was only one element in the original 
% clist, it now contains only |\q_nil|.
%    \begin{macrocode}
\cs_new:Npn \clist_pop_aux:w  #1,#2\q_stop #3#4#5#6 {
   #4 #6 {#1}
   #3 #5 {#2}
   \quark_if_nil:NTF #5 { #3 #5 {} }{ \clist_pop_auxi:w #2 #3#5 }
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn \clist_pop_auxi:w #1,\q_nil #2#3 { #2#3{#1} }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_show:N}
% \begin{macro}{\clist_show:c}
%    \begin{macrocode}
\cs_new_eq:NN \clist_show:N \tl_show:N
\cs_new_eq:NN \clist_show:c \tl_show:c
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_display:N}
% \begin{macro}{\clist_display:c}
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_display:N #1 {
  \iow_term:x { Comma-list~\token_to_str:N #1~contains~
                   the~elements~(without~outer~braces): }
  \toks_clear:N \l_tmpa_toks
  \clist_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 {
      \iow_space: \iow_char:N \{ \exp_not:n {##1} \iow_char:N \}
    }
  }
  \toks_show:N \l_tmpa_toks
}
\cs_generate_variant:Nn \clist_display:N {c}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Storing data}
%
% \begin{macro}{\clist_put_aux:NNnnNn}
%    The generic put function.
%    When adding we have to distinguish between an empty \meta{clist}
%    and one that contains at least one item (otherwise we accumulate
%    commas).
%
% MH says: Perhaps we should make sure that empty arguments don't get
% on the stack as that is probably a mistake. That's what I've
% implemented here. Since |\tl_if_empty:nF| is expandable prefixes
% are still allowed.
%    \begin{macrocode}
\cs_new:Npn \clist_put_aux:NNnnNn #1#2#3#4#5#6 {
  \clist_if_empty:NTF #5 { #1 #5 {#6} } { 
    \tl_if_empty:nF {#6} { #2 #5{#3#6#4} } 
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\clist_put_left:Nn}
% \begin{macro}{\clist_put_left:NV}
% \begin{macro}{\clist_put_left:No}
% \begin{macro}{\clist_put_left:Nx}
% \begin{macro}{\clist_put_left:cn}
% \begin{macro}{\clist_put_left:cV}
% \begin{macro}{\clist_put_left:co}
%    The operations for adding to the left.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_put_left:Nn {
  \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_left:Nn {} ,
}
\cs_generate_variant:Nn \clist_put_left:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_gput_left:Nn}
% \begin{macro}{\clist_gput_left:NV}
% \begin{macro}{\clist_gput_left:No}
% \begin{macro}{\clist_gput_left:Nx}
% \begin{macro}{\clist_gput_left:cn}
% \begin{macro}{\clist_gput_left:cV}
% \begin{macro}{\clist_gput_left:co}
% Global versions.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_gput_left:Nn {
  \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_left:Nn {} ,
}
\cs_generate_variant:Nn \clist_gput_left:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_put_right:Nn}
% \begin{macro}{\clist_put_right:NV}
% \begin{macro}{\clist_put_right:No}
% \begin{macro}{\clist_put_right:Nx}
% \begin{macro}{\clist_put_right:cn}
% \begin{macro}{\clist_put_right:cV}
% \begin{macro}{\clist_put_right:co}
%  Adding something to the right side is almost the same.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_put_right:Nn {
  \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_right:Nn , {}
}
\cs_generate_variant:Nn \clist_put_right:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_gput_right:Nn}
% \begin{macro}{\clist_gput_right:NV}
% \begin{macro}{\clist_gput_right:No}
% \begin{macro}{\clist_gput_right:Nx}
% \begin{macro}{\clist_gput_right:cn}
% \begin{macro}{\clist_gput_right:cV}
% \begin{macro}{\clist_gput_right:co}
%    And here the global variants.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_gput_right:Nn {
  \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_right:Nn , {}
}
\cs_generate_variant:Nn \clist_gput_right:Nn {NV,No,Nx,cn,cV,co}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsection{Mapping}
%
% \begin{macro}{\clist_map_function:NN}
% \begin{macro}{\clist_map_function:cN}
% \begin{macro}{\clist_map_function:nN}
%    |\clist_map_function:NN| \meta{comma-list} \meta{cmd} applies \meta{cmd} to each
%    element of \meta{comma-list}, from left to right.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_map_function:NN #1#2 {
  \clist_if_empty:NF #1 {
    \exp_after:wN \clist_map_function_aux:Nw
    \exp_after:wN #2 #1 , \q_recursion_tail , \q_recursion_stop 
  }
}
\cs_generate_variant:Nn \clist_map_function:NN {cN}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn \clist_map_function:nN #1#2 {
  \tl_if_blank:nF {#1} { 
    \clist_map_function_aux:Nw #2 #1 , \q_recursion_tail , \q_recursion_stop 
  }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[aux]{\clist_map_function_aux:Nw}
%  The general loop. Tests if we hit the first stop marker and exits if
%  we did. If we didn't, place the function "#1" in front of the
%  element "#2", which is surrounded by braces.
%    \begin{macrocode}
\cs_new:Npn \clist_map_function_aux:Nw #1#2,{
  \quark_if_recursion_tail_stop:n{#2} 
  #1{#2}
  \clist_map_function_aux:Nw #1
}
%    \end{macrocode}
% \end{macro}
%
%  \begin{macro}{\clist_map_break:}
%    The break statement is easy. Same as in other modules, gobble
%    everything up to the special recursion stop marker.
%    \begin{macrocode}
\cs_new_eq:NN \clist_map_break: \use_none_delimit_by_q_recursion_stop:w
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\clist_map_inline:Nn}
% \begin{macro}{\clist_map_inline:cn}
% \begin{macro}{\clist_map_inline:nn}
%   The inline type is faster but not expandable. In order to make it
%   nestable, we use a counter to keep track of the nesting level so
%   that all of the functions called have distict names. A simpler
%   approach would of course be to use grouping and thus the save
%   stack but then you lose the ability to do things locally.
%
%   A funny little thing occured in one document: The command setting
%   up the first call of |\clist_map_inline:Nn| was used in a tabular
%   cell and the inline code used |\\| so the loop broke as soon as
%   this happened. Lesson to be learned from this: If you wish to have
%   group like structure but not using the groupings of \TeX, then do
%   every operation globally.
%    \begin{macrocode}
\int_new:N \g_clist_inline_level_int
\cs_new:Npn \clist_map_inline:Nn #1#2 {
  \clist_if_empty:NF #1 {
    \int_gincr:N \g_clist_inline_level_int
    \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} 
    ##1{#2}
%    \end{macrocode}
% It is a lot more efficient to carry over
% the special function rather than constructing the same csname over
% and over again, so we just do it once. We reuse
% |\clist_map_function_aux:Nw| for the actual loop.
%    \begin{macrocode}
    \exp_last_unbraced:NcV \clist_map_function_aux:Nw 
    {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n}
    #1 , \q_recursion_tail , \q_recursion_stop 
    \int_gdecr:N \g_clist_inline_level_int
  }
}
\cs_generate_variant:Nn \clist_map_inline:Nn {c}
\cs_new:Npn \clist_map_inline:nn #1#2 {
  \tl_if_empty:nF {#1} {
    \int_gincr:N \g_clist_inline_level_int
    \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} 
    ##1{#2}
    \exp_args:Nc \clist_map_function_aux:Nw 
    {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} 
    #1 , \q_recursion_tail , \q_recursion_stop 
    \int_gdecr:N \g_clist_inline_level_int
  }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\clist_map_variable:nNn}
% \begin{macro}{\clist_map_variable:NNn}
% \begin{macro}{\clist_map_variable:cNn}
%    |\clist_map_variable:NNn| \meta{comma-list} \meta{temp} \meta{action} assigns
%    \meta{temp} to each element and executes \meta{action}.
%    \begin{macrocode}
\cs_new:Npn \clist_map_variable:nNn #1#2#3 {
  \tl_if_empty:nF {#1} {
    \clist_map_variable_aux:Nnw #2 {#3} #1 
    , \q_recursion_tail , \q_recursion_stop
  }
}
%    \end{macrocode}
%    Something for v/V
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_map_variable:NNn {\exp_args:No \clist_map_variable:nNn}
\cs_generate_variant:Nn\clist_map_variable:NNn {cNn}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[aux]{\clist_map_variable_aux:Nnw}
%  The general loop. Assign the temp variable |#1| to the current item
%  |#3| and then check if that's the stop marker. If it is, break the
%  loop. If not, execute the action |#2| and continue.
%    \begin{macrocode}
\cs_new:Npn \clist_map_variable_aux:Nnw #1#2#3,{
  \cs_set_nopar:Npn #1{#3}
  \quark_if_recursion_tail_stop:N #1 
  #2 \clist_map_variable_aux:Nnw #1{#2}
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Higher level functions}
%
% \begin{macro}[aux]{\clist_concat_aux:NNNN}
% \begin{macro}{\clist_concat:NNN,\clist_concat:ccc}
% \begin{macro}{\clist_gconcat:NNN,\clist_gconcat:ccc}
%    |\clist_gconcat:NNN| \m{clist~1} \m{clist~2} \m{clist~3} will globally
%    assign \m{clist~1} the concatenation of \m{clist~2} and
%    \m{clist~3}.
%
%    Again the situation is a bit more complicated because of the use
%    of commas between items, so if either list is empty we have to avoid
%    adding a comma.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_concat_aux:NNNN #1#2#3#4 {
  \toks_set:No \l_tmpa_toks {#3}
  \toks_set:No \l_tmpb_toks {#4}
  #1 #2 {
    \toks_use:N \l_tmpa_toks
    \toks_if_empty:NF \l_tmpa_toks { \toks_if_empty:NF \l_tmpb_toks , }
    \toks_use:N \l_tmpb_toks
  }
}
\cs_new_nopar:Npn \clist_concat:NNN  { \clist_concat_aux:NNNN \tl_set:Nx  }
\cs_new_nopar:Npn \clist_gconcat:NNN { \clist_concat_aux:NNNN \tl_gset:Nx }
\cs_generate_variant:Nn \clist_concat:NNN {ccc}
\cs_generate_variant:Nn \clist_gconcat:NNN {ccc}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% 
%  \begin{macro}[aux]{\l_clist_remove_clist}
%  A common scratch space for the removal routines.
%    \begin{macrocode}
\clist_new:N \l_clist_remove_clist
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}[aux]{\clist_remove_duplicates_aux:NN}
%  \begin{macro}[aux]{\clist_remove_duplicates_aux:n}
%  \begin{macro}{\clist_remove_duplicates:N}
%  \begin{macro}{\clist_gremove_duplicates:N}
%  Removing duplicate entries in a \meta{clist} is fairly straight
%  forward. We use a temporary variable and then go through the list
%  from left to right. For each element check if the element is
%  already present in the list.
%    \begin{macrocode}
\cs_new:Nn \clist_remove_duplicates_aux:NN {
  \clist_clear:N \l_clist_remove_clist
  \clist_map_function:NN #2 \clist_remove_duplicates_aux:n
  #1 #2 \l_clist_remove_clist
}
\cs_new:Nn \clist_remove_duplicates_aux:n {
  \clist_if_in:NnF \l_clist_remove_clist {#1} {
    \clist_put_right:Nn \l_clist_remove_clist {#1}
  }
}
%    \end{macrocode}
%  The high level functions are just for telling if it should be a
%  local or global setting.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_remove_duplicates:N {
  \clist_remove_duplicates_aux:NN \clist_set_eq:NN
}
\cs_new_nopar:Npn \clist_gremove_duplicates:N {
  \clist_remove_duplicates_aux:NN \clist_gset_eq:NN
}
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  
%\begin{macro}{\clist_remove_element:Nn}
%\begin{macro}{\clist_gremove_element:Nn}
%\begin{macro}[aux]{\clist_remove_element_aux:NNn}
%\begin{macro}[aux]{\clist_remove_element_aux:n}
% The same general idea is used for removing elements: the parent 
% functions just set things up for the internal ones.
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_remove_element:Nn {
  \clist_remove_element_aux:NNn \clist_set_eq:NN
}
\cs_new_nopar:Npn \clist_gremove_element:Nn {
  \clist_remove_element_aux:NNn \clist_gset_eq:NN
}
\cs_new:Nn \clist_remove_element_aux:NNn {
  \clist_clear:N \l_clist_remove_clist
  \cs_set:Nn \clist_remove_element_aux:n {
    \tl_if_eq:nnF {#3} {##1} {
      \clist_put_right:Nn \l_clist_remove_clist {##1}
    }
  }
  \clist_map_function:NN #2 \clist_remove_element_aux:n
  #1 #2 \l_clist_remove_clist
}
\cs_new:Nn \clist_remove_element_aux:n { }
%    \end{macrocode}
%\end{macro}
%\end{macro} 
%\end{macro} 
%\end{macro} 
%
% \subsection{Stack operations}
%
% We build stacks from comma-lists,  but here we put the
% specific functions together.
%
%
% \begin{macro}{\clist_push:Nn}
% \begin{macro}{\clist_push:No}
% \begin{macro}{\clist_push:NV}
% \begin{macro}{\clist_push:cn}
% \begin{macro}{\clist_pop:NN}
% \begin{macro}{\clist_pop:cN}
%    Since comma-lists can be used as stacks, we ought to have both
%    `push' and `pop'. In most cases they are nothing more then new
%    names for old functions.
%    \begin{macrocode}
\cs_new_eq:NN \clist_push:Nn \clist_put_left:Nn
\cs_new_eq:NN \clist_push:NV \clist_put_left:NV
\cs_new_eq:NN \clist_push:No \clist_put_left:No
\cs_new_eq:NN \clist_push:cn \clist_put_left:cn
\cs_new_nopar:Npn \clist_pop:NN {\clist_pop_aux:nnNN \tl_set:Nn \tl_set:Nn}
\cs_generate_variant:Nn \clist_pop:NN {cN}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\clist_gpush:Nn}
% \begin{macro}{\clist_gpush:No}
% \begin{macro}{\clist_gpush:NV}
% \begin{macro}{\clist_gpush:cn}
% \begin{macro}{\clist_gpop:NN}
% \begin{macro}{\clist_gpop:cN}
%    I don't agree with Denys that one needs only local stacks,
%    actually I believe that one will probably need the functions
%    here more often. In case of |\clist_gpop:NN| the value is
%    nevertheless returned locally.
%    \begin{macrocode}
\cs_new_eq:NN \clist_gpush:Nn \clist_gput_left:Nn
\cs_new_eq:NN \clist_gpush:NV \clist_gput_left:NV
\cs_new_eq:NN \clist_gpush:No \clist_gput_left:No
\cs_generate_variant:Nn \clist_gpush:Nn {cn}
%    \end{macrocode}
%    
%    \begin{macrocode}
\cs_new_nopar:Npn \clist_gpop:NN {\clist_pop_aux:nnNN \tl_gset:Nn \tl_set:Nn}
\cs_generate_variant:Nn \clist_gpop:NN {cN}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\clist_top:NN}
% \begin{macro}{\clist_top:cN}
%    Looking at the top element of the stack without removing it is
%    done with this operation.
%    \begin{macrocode}
\cs_new_eq:NN \clist_top:NN \clist_get:NN
\cs_new_eq:NN \clist_top:cN \clist_get:cN
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% Show token usage:
%    \begin{macrocode}
%<*showmemory>
%\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
% \PrintIndex
%
%
%
% \endinput
