% \iffalse %% File: l3seq.dtx Copyright (C) 1990-2010 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} % %\fi \GetIdInfo$Id: l3seq.dtx 1879 2010-03-29 17:48:38Z mittelba $ {L3 Experimental sequences and stacks} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} % % \fi % % % \title{The \textsf{l3seq} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Sequences} % \author{\Team} % \date{\filedate} % \maketitle % % \begin{documentation} % % \LaTeX3 implements a data type called `sequences'. 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 sequence might contain any tokens except two internal % functions that are used to structure sequences (see section internal % functions below). It is also possible to map functions on such % sequences so that they are executed for every item on the sequence. % % All functions that return items from a sequence 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 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. Maybe one should % therefore remove the ``left'' functions totally. % % \section{Functions for creating/initialising sequences} % % \begin{function}{ \seq_new:N | % \seq_new:c } % \begin{syntax} % "\seq_new:N" % \end{syntax} % Defines 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" % \end{syntax} % These functions locally or globally clear . % \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" % \end{syntax} % These functions locally or globally clear 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 } % \begin{syntax} % "\seq_set_eq:NN" % \end{syntax} % Function that locally makes identical to . % \end{function} % % \begin{function}{ \seq_gset_eq:NN | % \seq_gset_eq:cN | % \seq_gset_eq:Nc | % \seq_gset_eq:cc } % \begin{syntax} % "\seq_gset_eq:NN" % \end{syntax} % Function that globally makes identical to . % \end{function} % % \begin{function}{% % \seq_concat:NNN | % \seq_concat:ccc | % \seq_gconcat:NNN | % \seq_gconcat:ccc | % } % \begin{syntax} % "\seq_concat:NNN" % "\seq_gconcat:NNN" % \end{syntax} % Function that conatenates and and locally or globally assigns the % result to . % \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" % \end{syntax} % Locally appends as a single item to the left % of . 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" % \end{syntax} % Locally appends as a single item to the right % of . 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" % \end{syntax} % Globally appends as a single item to the left % of . % \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" % \end{syntax} % Globally appends as a single item to the right % of . % \end{function} % % % \section{Working with sequences} % % \begin{function}{% % \seq_get:NN | % \seq_get:cN | % } % \begin{syntax} % "\seq_get:NN" % \end{syntax} % Functions that locally assign the left-most item of to the % token list variable . Item is not removed from ! If you % need a global return value you need to code something like this: % \begin{quote} % "\seq_get:NN" "\l_tmpa_tl" \\ % "\tl_gset_eq:NN" "\l_tmpa_tl" % \end{quote} % But if this kind of construction is used often enough a separate % function should be provided. % \end{function} % % % \begin{function}{\seq_map_variable:NNn | % \seq_map_variable:cNn % } % \begin{syntax} % "\seq_map_variable:NNn" \Arg{code using tl var.} % \end{syntax} % Every element in is assigned to and then is executed. The operation is not expandable which means % that it can't be used within write operations etc. However, this % function can be nested which the others can't. % \end{function} % % \begin{function}{ \seq_map_function:NN | % \seq_map_function:cN } % \begin{syntax} % "\seq_map_function:NN" % \end{syntax} % This function applies (which must be a function with one % argument) to every item of . 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. % % In the current implementation the next functions are more efficient and % should be preferred. % \end{function} % % \begin{function}{\seq_map_inline:Nn | % \seq_map_inline:cn % } % \begin{syntax} % "\seq_map_inline:Nn" \Arg{inline function} % \end{syntax} % Applies (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 . 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. % \end{function} % % \begin{function}{ \seq_map_break: | \seq_map_break:n } % These functions are used to break out of a mapping function at the point % of execution. (Please do not put `|\q_stop|' inside a that uses % these functions.) % \end{function} % % \begin{function}{ \seq_show:N | % \seq_show:c } % \begin{syntax} % "\seq_show:N" % \end{syntax} % Function that pauses the compilation and displays 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" % \end{syntax} % As with "\seq_show:N" but pretty prints the output one line per element. % \end{function} % % \begin{function}{ \seq_remove_duplicates:N | % \seq_gremove_duplicates:N } % \begin{syntax} % "\seq_gremove_duplicates:N" % \end{syntax} % Function that removes any duplicate entries in . % \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" % \end{syntax} % This predicate returns `true' if is `empty' i.e., doesn't % contain any items. Note that this is `false' even if the 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" \Arg{true code} \Arg{false code} % \end{syntax} % Set of conditionals that test whether or not a particular % is empty and if so executes either or . % \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" \Arg{item} \Arg{true code} \Arg{false code} % \end{syntax} % Functions that test if is in . Depending on the result % either or is executed. % \end{function} % % \section{Internal functions} % % \begin{function}{\seq_if_empty_err:N} % \begin{syntax} % "\seq_if_empty_err:N" % \end{syntax} % Signals an \LaTeX3 error if is empty. % \end{function} % % \begin{function}{\seq_pop_aux:nnNN} % \begin{syntax} % "\seq_pop_aux:nnNN" % \end{syntax} % Function that assigns the left-most item of to using % and assigns the tail to using . This % function could be used to implement a global return function. % \end{function} % % \begin{function}{% % \seq_get_aux:w | % \seq_pop_aux:w | % \seq_put_aux:Nnn | % \seq_put_aux:w | % } % Functions used to implement put and get operations. They are not for % meant for direct use. % \end{function} % % \begin{function}{ \seq_elt:w | % \seq_elt_end: } % Functions (usually used as constants) that separates items within a % sequence. They might get special meaning during mapping operations and % are not supposed to show up as tokens within an item appended to a % sequence. % \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:cn | % } % \begin{syntax} % "\seq_push:Nn" \Arg{token list} % \end{syntax} % Locally or globally pushes as a single item onto the % . % \end{function} % % \begin{function}{% % \seq_pop:NN | % \seq_pop:cN | % \seq_gpop:NN | % \seq_gpop:cN | % } % \begin{syntax} % "\seq_pop:NN" % \end{syntax} % Functions that assign the top item of to % and removes it from ! % \end{function} % % \begin{function}{% % \seq_top:NN | % \seq_top:cN | % } % \begin{syntax} % "\seq_top:NN" % \end{syntax} % Functions that locally assign the top item of to the . % Item is \emph{not} removed from ! % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3seq} implementation} % % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \package_check_loaded_expl: % % \end{macrocode} % % A sequence is a control sequence whose top-level expansion is of the % form `|\seq_elt:w| \m{text$\sb1$} |\seq_elt_end:| \ldots{} % |\seq_elt:w| \meta{text$\sb{n}$} \ldots'. We use explicit delimiters % instead of braces around \m{text} to allow efficient searching for % an item in the sequence. % % \begin{macro}{\seq_elt:w} % \begin{macro}{\seq_elt_end:} % We allocate the delimiters and make them errors if executed. % \begin{macrocode} %<*initex|package> \cs_new:Npn \seq_elt:w {\ERROR} \cs_new:Npn \seq_elt_end: {\ERROR} % \end{macrocode} % \end{macro} % \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.} % \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} % |\seq_concat:NNN| \m{seq~1} \m{seq~2} \m{seq~3} 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} % |\seq_gconcat:NNN| \m{seq~1} \m{seq~2} \m{seq~3} 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{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} % Signals an error if the sequence is empty. % \begin{macrocode} \cs_new_nopar:Npn \seq_if_empty_err:N #1 { \if_meaning:w #1 \c_empty_tl % \end{macrocode} % 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.) % \begin{macrocode} \tl_clear:N \l_kernel_testa_tl % catch prefixes \msg_kernel_bug:x {Empty~sequence~`\token_to_str:N#1'} \fi: } % \end{macrocode} % \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} % |\seq_if_in:NnTF| \m{seq}\m{item} \m{true~case} \m{false~case} % will check whether \m{item} is in \m{seq} 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. % % Note that |##2| in the definition below for "\seq_tmp:w" contains % exactly one token which we can compare with |\q_no_value|. % \begin{macrocode} \prg_new_protected_conditional:Nnn \seq_if_in:Nn {TF,T,F} { \cs_set:Npn \seq_tmp:w ##1 \seq_elt:w #2 \seq_elt_end: ##2##3 \q_stop { \if_meaning:w \q_no_value ##2 \prg_return_false: \else: \prg_return_true: \fi: } \exp_after:wN \seq_tmp:w #1 \seq_elt:w #2 \seq_elt_end: \q_no_value \q_stop } % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn \seq_if_in:NnTF { NV, cV, co, c, cx} \cs_generate_variant:Nn \seq_if_in:NnT { NV, cV, co, c, cx} \cs_generate_variant:Nn \seq_if_in:NnF { NV, cV, co, c, cx} % \end{macrocode} % \end{macro} % % \subsection{Getting data out} % % \begin{macro}{\seq_get:NN} % \begin{macro}{\seq_get:cN} % \begin{macro}{\seq_get_aux:w} % |\seq_get:NN |\meta{sequence}\meta{cmd} defines \meta{cmd} to be the % left-most element of \meta{sequence}. % \begin{macrocode} \cs_new_protected_nopar:Npn \seq_get:NN #1 { \seq_if_empty_err:N #1 \exp_after:wN \seq_get_aux:w #1 \q_stop } \cs_new_protected:Npn \seq_get_aux:w \seq_elt:w #1 \seq_elt_end: #2 \q_stop #3 { \tl_set:Nn #3 {#1} } \cs_generate_variant:Nn \seq_get:NN {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_pop_aux:nnNN} % \begin{macro}{\seq_pop_aux:w} % |\seq_pop_aux:nnNN| \meta{def$\sb1$} \meta{def$\sb2$} \meta{sequence} % \meta{cmd} assigns the left_most element of \meta{sequence} to % \meta{cmd} using \meta{def$\sb2$}, and assigns the tail of % \meta{sequence} to \meta{sequence} using \meta{def$\sb1$}. % \begin{macrocode} \cs_new_protected:Npn \seq_pop_aux:nnNN #1#2#3 { \seq_if_empty_err:N #3 \exp_after:wN \seq_pop_aux:w #3 \q_stop #1#2#3 } \cs_new_protected:Npn \seq_pop_aux:w \seq_elt:w #1 \seq_elt_end: #2\q_stop #3#4#5#6 { #3 #5 {#2} #4 #6 {#1} } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_show:N} % \begin{macro}{\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} % \end{macro} % % \begin{macro}{\seq_display:N} % \begin{macro}{\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} % \end{macro} % % % \subsection{Putting data in} % % \begin{macro}{\seq_put_aux:Nnn} % \begin{macro}{\seq_put_aux:w} % |\seq_put_aux:Nnn| \meta{sequence} \meta{left} \meta{right} adds the % elements specified by \meta{left} to the left of \meta{sequence}, and % those specified by \meta{right} to the right. % \begin{macrocode} \cs_new_protected:Npn \seq_put_aux:Nnn #1 { \exp_after:wN \seq_put_aux:w #1 \q_stop #1 } \cs_new_protected:Npn \seq_put_aux:w #1\q_stop #2#3#4 { \tl_set:Nn #2 {#3#1#4} } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_put_left:Nn} % \begin{macro}{\seq_put_left:NV} % \begin{macro}{\seq_put_left:No} % \begin{macro}{\seq_put_left:Nx} % \begin{macro}{\seq_put_left:cn} % \begin{macro}{\seq_put_left:cV} % \begin{macro}{\seq_put_left:co} % \begin{macro}{\seq_put_right:Nn} % \begin{macro}{\seq_put_right:No} % \begin{macro}{\seq_put_right:NV} % \begin{macro}{\seq_put_right:Nx} % \begin{macro}{\seq_put_right:cn} % \begin{macro}{\seq_put_right:cV} % \begin{macro}{\seq_put_right:co} % Here are the usual operations for adding to the left and right. % \begin{macrocode} \cs_new_protected:Npn \seq_put_left:Nn #1#2 { \seq_put_aux:Nnn #1 {\seq_elt:w #2\seq_elt_end:} {} } % \end{macrocode} % We can't put in a |\prg_do_nothing:| instead of |{}| above since this argument % is passed literally (and we would end up with many |\prg_do_nothing:|s inside % the sequences). % \begin{macrocode} \cs_generate_variant:Nn \seq_put_left:Nn {NV,No,Nx,c,cV,co} % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn \seq_put_right:Nn #1#2{ \seq_put_aux:Nnn #1{}{\seq_elt:w #2\seq_elt_end:}} % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn \seq_put_right:Nn {NV,No,Nx,c,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_gput_left:Nn} % \begin{macro}{\seq_gput_left:NV} % \begin{macro}{\seq_gput_left:No} % \begin{macro}{\seq_gput_left:Nx} % \begin{macro}{\seq_gput_left:cn} % \begin{macro}{\seq_gput_left:cV} % \begin{macro}{\seq_gput_left:co} % \begin{macro}{\seq_gput_right:Nn} % \begin{macro}{\seq_gput_right:NV} % \begin{macro}{\seq_gput_right:No} % \begin{macro}{\seq_gput_right:Nx} % \begin{macro}{\seq_gput_right:cn} % \begin{macro}{\seq_gput_right:cV} % \begin{macro}{\seq_gput_right:co} % \begin{macrocode} \cs_new_protected:Npn \seq_gput_left:Nn { %<*check> \pref_global_chk: % %<*!check> \pref_global:D % \seq_put_left:Nn } % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn \seq_gput_right:Nn { %<*check> \pref_global_chk: % %<*!check> \pref_global:D % \seq_put_right:Nn } % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn \seq_gput_left:Nn {NV,No,Nx,c,cV,co} % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn \seq_gput_right:Nn {NV,No,Nx,c,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsection{Mapping} % % \begin{macro}{\seq_map_variable:NNn} % \begin{macro}{\seq_map_variable:cNn} % \begin{macro}[aux]{\seq_map_variable_aux:Nnw} % Nothing spectacular here. % \begin{macrocode} \cs_new_protected:Npn \seq_map_variable_aux:Nnw #1#2 \seq_elt:w #3 \seq_elt_end: { \tl_set:Nn #1 {#3} \quark_if_nil:NT #1 \seq_map_break: #2 \seq_map_variable_aux:Nnw #1{#2} } \cs_new_protected:Npn \seq_map_variable:NNn #1#2#3 { \tl_set:Nn #2 {\seq_map_variable_aux:Nnw #2{#3}} \exp_after:wN #2 #1 \seq_elt:w \q_nil\seq_elt_end: \q_stop } \cs_generate_variant:Nn \seq_map_variable:NNn {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_map_break:} % \begin{macro}{\seq_map_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_eq:NN \seq_map_break: \use_none_delimit_by_q_stop:w \cs_new_eq:NN \seq_map_break:n \use_i_delimit_by_q_stop:nw % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_map_function:NN} % \begin{macro}{\seq_map_function:cN} % |\seq_map_function:NN| \meta{sequence} \meta{cmd} applies \meta{cmd} to each % element of \meta{sequence}, from left to right. Since we don't have % braces, this implementation is not very efficient. It might be % better to say that \meta{cmd} must be a function with one argument % that is delimited by |\seq_elt_end:|. % \begin{macrocode} \cs_new_protected_nopar:Npn \seq_map_function:NN #1#2 { \cs_set:Npn \seq_elt:w ##1 \seq_elt_end: {#2{##1}} #1 \use_none:n \q_stop \cs_set_eq:NN \seq_elt:w \ERROR } \cs_generate_variant:Nn \seq_map_function:NN {c} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\seq_map_inline:Nn} % \begin{macro}{\seq_map_inline:cn} % When no braces are used, this version of mapping seems more % natural. % \begin{macrocode} \cs_new_protected_nopar:Npn \seq_map_inline:Nn #1#2 { \cs_set:Npn \seq_elt:w ##1 \seq_elt_end: {#2} #1 \use_none:n \q_stop \cs_set_eq:NN \seq_elt:w \ERROR } \cs_generate_variant:Nn \seq_map_inline:Nn {c} % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Manipulation} % % \begin{macro}[aux]{\l_clist_remove_clist} % A common scratch space for the removal routines. % \begin{macrocode} \seq_new:N \l_seq_remove_seq % \end{macrocode} % \end{macro} % % \begin{macro}[aux]{\seq_remove_duplicates_aux:NN} % \begin{macro}[aux]{\seq_remove_duplicates_aux:n} % \begin{macro}{\seq_remove_duplicates:N} % \begin{macro}{\seq_gremove_duplicates:N} % Copied from "\clist_remove_duplicates". % \begin{macrocode} \cs_new_protected:Npn \seq_remove_duplicates_aux:NN #1#2 { \seq_clear:N \l_seq_remove_seq \seq_map_function:NN #2 \seq_remove_duplicates_aux:n #1 #2 \l_seq_remove_seq } \cs_new_protected:Npn \seq_remove_duplicates_aux:n #1 { \seq_if_in:NnF \l_seq_remove_seq {#1} { \seq_put_right:Nn \l_seq_remove_seq {#1} } } % \end{macrocode} % \begin{macrocode} \cs_new_protected_nopar:Npn \seq_remove_duplicates:N { \seq_remove_duplicates_aux:NN \seq_set_eq:NN } \cs_new_protected_nopar:Npn \seq_gremove_duplicates:N { \seq_remove_duplicates_aux:NN \seq_gset_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Sequence stacks} % % \begin{macro}{\seq_push:Nn} % \begin{macro}{\seq_push:NV} % \begin{macro}{\seq_push:No} % \begin{macro}{\seq_push:cn} % \begin{macro}{\seq_pop:NN} % \begin{macro}{\seq_pop:cN} % Since sequences 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 \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_protected_nopar:Npn \seq_pop:NN { \seq_pop_aux:nnNN \tl_set:Nn \tl_set:Nn } \cs_generate_variant:Nn \seq_pop:NN {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_gpush:Nn} % \begin{macro}{\seq_gpush:NV} % \begin{macro}{\seq_gpush:No} % \begin{macro}{\seq_gpush:cn} % \begin{macro}{\seq_gpush:Nv} % \begin{macro}{\seq_gpop:NN} % \begin{macro}{\seq_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 |\seq_gpop:NN| the value is % nevertheless returned locally. % \begin{macrocode} \cs_new_eq:NN \seq_gpush:Nn \seq_gput_left:Nn \cs_new_protected_nopar:Npn \seq_gpop:NN { \seq_pop_aux:nnNN \tl_gset:Nn \tl_set:Nn } \cs_generate_variant:Nn \seq_gpush:Nn {NV,No,c,Nv} \cs_generate_variant:Nn \seq_gpop:NN {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\seq_top:NN} % \begin{macro}{\seq_top:cN} % Looking at the top element of the stack without removing it is % done with this operation. % \begin{macrocode} \cs_new_eq:NN \seq_top:NN \seq_get:NN \cs_new_eq:NN \seq_top:cN \seq_get:cN % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % Show token usage: % \begin{macrocode} %<*showmemory> %\showMemUsage % % \end{macrocode} % % \end{implementation} % \PrintIndex % % \endinput