texlive[62926] Master/texmf-dist: functional (1apr22)
commits+karl at tug.org
commits+karl at tug.org
Tue Apr 5 23:57:49 CEST 2022
Revision: 62926
http://tug.org/svn/texlive?view=revision&revision=62926
Author: karl
Date: 2022-04-05 23:57:49 +0200 (Tue, 05 Apr 2022)
Log Message:
-----------
functional (1apr22)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/functional/README.txt
trunk/Master/texmf-dist/doc/latex/functional/functional.pdf
trunk/Master/texmf-dist/doc/latex/functional/functional.tex
trunk/Master/texmf-dist/tex/latex/functional/functional.sty
Modified: trunk/Master/texmf-dist/doc/latex/functional/README.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/functional/README.txt 2022-04-05 21:57:36 UTC (rev 62925)
+++ trunk/Master/texmf-dist/doc/latex/functional/README.txt 2022-04-05 21:57:49 UTC (rev 62926)
@@ -1,5 +1,6 @@
Functional: LaTeX2 functional interfaces for LaTeX3 programming layer
Copyright : 2022 (c) Jianrui Lyu <tolvjr at 163.com>
+CTAN Page : https://ctan.org/pkg/functional
Repository: https://github.com/lvjr/functional
Repository: https://bitbucket.org/lvjr/functional
License : The LaTeX Project Public License 1.3c
Modified: trunk/Master/texmf-dist/doc/latex/functional/functional.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/functional/functional.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/functional/functional.tex 2022-04-05 21:57:36 UTC (rev 62925)
+++ trunk/Master/texmf-dist/doc/latex/functional/functional.tex 2022-04-05 21:57:49 UTC (rev 62926)
@@ -3,7 +3,7 @@
\documentclass[oneside]{book}
\usepackage[a4paper,margin=2.5cm]{geometry}
-\newcommand*{\myversion}{2022B}
+\newcommand*{\myversion}{2022C}
\newcommand*{\mydate}{Version \myversion\ (\the\year-\mylpad\month-\mylpad\day)}
\newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
@@ -76,6 +76,8 @@
\texttt{\{}\textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}\texttt{\}}%
}
+\NewDocumentCommand\pkg{m}{\textsf{#1}}
+
\NewDocumentCommand\nan{}{\texttt{NaN}}
\NewDocumentCommand\enquote{m}{``#1''}
@@ -245,18 +247,18 @@
\Functional{scoping=true}
\IgnoreSpacesOn
\IntSet \lTmpaInt {1}
-\IntLogVar \lTmpaInt % ---- 1
+\IntVarLog \lTmpaInt % ---- 1
\PrgNewFunction \SomeFun { } {
\IntSet \lTmpaInt {2}
- \IntLogVar \lTmpaInt % ---- 2
+ \IntVarLog \lTmpaInt % ---- 2
\IntCompareTF {1} > {0} {
\IntSet \lTmpaInt {3}
- \IntLogVar \lTmpaInt % ---- 3
+ \IntVarLog \lTmpaInt % ---- 3
}{ }
- \IntLogVar \lTmpaInt % ---- 2
+ \IntVarLog \lTmpaInt % ---- 2
}
\SomeFun
-\IntLogVar \lTmpaInt % ---- 1
+\IntVarLog \lTmpaInt % ---- 1
\IgnoreSpacesOff
\end{codehigh}
\end{minipage}%
@@ -296,18 +298,18 @@
\Functional{scoping=true}
\IgnoreSpacesOn
\IntSet \gTmpaInt {1}
-\IntLogVar \gTmpaInt % ---- 1
+\IntVarLog \gTmpaInt % ---- 1
\PrgNewFunction \SomeFun { } {
\IntSet \gTmpaInt {2}
- \IntLogVar \gTmpaInt % ---- 2
+ \IntVarLog \gTmpaInt % ---- 2
\IntCompareTF {1} > {0} {
\IntSet \gTmpaInt {3}
- \IntLogVar \gTmpaInt % ---- 3
+ \IntVarLog \gTmpaInt % ---- 3
}{ }
- \IntLogVar \gTmpaInt % ---- 3
+ \IntVarLog \gTmpaInt % ---- 3
}
\SomeFun
-\IntLogVar \gTmpaInt % ---- 3
+\IntVarLog \gTmpaInt % ---- 3
\IgnoreSpacesOff
\end{codehigh}
\end{minipage}%
@@ -567,12 +569,12 @@
Expands the \meta{tokens} exhaustively and returns the result.
\end{function}
-\begin{function}{\ExpNot}
+\begin{function}{\UnExpand}
\begin{syntax}
-\cs{ExpNot} \Arg{tokens}
+\cs{UnExpand} \Arg{tokens}
\end{syntax}
Prevents expansion of the \meta{tokens} inside the argument of \cs{Expand} function.
-The argument of \cs{ExpNot} \emph{must} be surrounded by braces.
+The argument of \cs{UnExpand} \emph{must} be surrounded by braces.
%\begin{texnote}
%This is the \eTeX{} \tn{unexpanded} primitive. In an
%|x|-expanding definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#1}|
@@ -583,10 +585,27 @@
%\end{texnote}
\end{function}
-\begin{function}{\ExpValue}
+\begin{function}{\OnlyName}
\begin{syntax}
-\cs{ExpValue} \meta{variable}
+\cs{OnlyName} \Arg{tokens}
\end{syntax}
+Expands the \meta{tokens} until only characters remain, and then
+converts this into a control sequence.
+Further expansion of this control sequence is then inhibited
+inside the argument of \cs{Expand} function.
+%\begin{texnote}
+%Protected macros that appear in a \texttt{c}-type argument are
+%expanded despite being protected; \cs{exp_not:n} also has no
+%effect. An internal error occurs if non-characters or active
+%characters remain after full expansion, as the conversion to a
+%control sequence is not possible.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\OnlyValue}
+\begin{syntax}
+\cs{OnlyValue} \meta{variable}
+\end{syntax}
Recovers the content of the \meta{variable}, then prevents expansion
of this material inside the argument of \cs{Expand} function.
\end{function}
@@ -792,7 +811,7 @@
\cs{BoolVarNotTF} \meta{boolean} \Arg{true code} \Arg{false code}
\end{syntax}
Evaluates \meta{true code} if \meta{boolean} is \verb!false!,
-and \meta{false code} If \meta{boolean} is \verb!true!.
+and \meta{false code} if \meta{boolean} is \verb!true!.
For example
\begin{demohigh}
\BoolVarNotTF {\IntCompare{3}>{2}} {\Result{Yes}} {\Result{No}}
@@ -845,6 +864,43 @@
\chapter{Token Lists (\texttt{Tl})}
+\TeX{} works with tokens, and \LaTeX3 therefore provides a number of
+functions to deal with lists of tokens. Token lists may be present
+directly in the argument to a function:
+\begin{codehigh}
+\TlFoo {a collection of \tokens}
+\end{codehigh}
+or may be stored in a so-called \enquote{token list variable}, which
+have the suffix \texttt{Tl}: a token list variable can also be used as
+the argument to a function, for example
+\begin{codehigh}
+\TlVarFoo \lSomeTl
+\end{codehigh}
+In both cases, functions are available to test and manipulate the lists
+of tokens, and these have the module prefix \texttt{Tl}.
+In many cases, functions which can be applied to token list variables
+are paired with similar functions for application to explicit lists
+of tokens: the two \enquote{views} of a token list are therefore collected
+together here.
+
+A token list (explicit, or stored in a variable) can be seen either
+as a list of \enquote{items},
+or a list of \enquote{tokens}. An item is whatever \cs{UseOne} would
+grab as its argument: a single non-space token or a brace group,
+with optional leading explicit space characters (each item is thus
+itself a token list). A token is either a normal \texttt{N} argument,
+or \verb*| |, \verb|{|, or \verb|}| (assuming normal \TeX{} category codes).
+Thus for example
+\begin{codehigh}
+{Hello} world
+\end{codehigh}
+contains 6 items (\texttt{Hello}, \texttt{w}, \texttt{o}, \texttt{r},
+\texttt{l} and \texttt{d}), but 13 tokens (\verb|{|, \texttt{H}, \texttt{e},
+\texttt{l}, \texttt{l}, \texttt{o}, \verb|}|, \verb*| |, \texttt{w}, \texttt{o},
+\texttt{r}, \texttt{l} and \texttt{d}).
+Functions which act on items are often faster than their analogue acting
+directly on tokens.
+
\section{Constant and Scratch Token Lists}
\begin{variable}{\cSpaceTl}
@@ -895,6 +951,9 @@
Creates a new \meta{tl var} or raises an error if the
name is already taken. The declaration is global. The
\meta{tl~var} is initially empty.
+\begin{codehigh}
+\TlNew \lFooSomeTl
+\end{codehigh}
\end{function}
\begin{function}{\TlConst}
@@ -904,6 +963,9 @@
Creates a new constant \meta{tl var} or raises an error
if the name is already taken. The value of the
\meta{tl var} is set globally to the \meta{token list}.
+\begin{codehigh}
+\TlConst \cFooSomeTl {abc}
+\end{codehigh}
\end{function}
\begin{function}{\TlUse}
@@ -914,6 +976,9 @@
An error is raised if the variable
does not exist or if it is invalid. Note that it is possible to use
a \meta{tl~var} directly without an accessor function.
+\begin{codehigh}
+\TlUse \lTmpbTl
+\end{codehigh}
\end{function}
\begin{function}{\TlToStr}
@@ -924,6 +989,9 @@
resulting character tokens. A \meta{string}
is a series of tokens with category code $12$ (other) with the exception
of spaces, which retain category code $10$ (space).
+\begin{demohigh}
+\TlToStr {12\abc34}
+\end{demohigh}
%This function requires only a single expansion.
%Its argument \emph{must} be braced.
%\begin{texnote}
@@ -963,6 +1031,10 @@
resulting character tokens. A \meta{string}
is a series of tokens with category code $12$ (other) with the exception
of spaces, which retain category code $10$ (space).
+\begin{demohigh}
+\TlSet \lTmpaTl {12\abc34}
+\TlVarToStr \lTmpaTl
+\end{demohigh}
\end{function}
\section{Viewing Token Lists}
@@ -973,6 +1045,9 @@
\end{syntax}
Writes the \meta{token list} in the log file. See also
\cs{TlShow} which displays the result in the terminal.
+\begin{codehigh}
+\TlLog {123\abc456}
+\end{codehigh}
\end{function}
\begin{function}{\TlVarLog}
@@ -981,6 +1056,10 @@
\end{syntax}
Writes the content of the \meta{tl var} in the log file. See also
\cs{TlVarShow} which displays the result in the terminal.
+\begin{codehigh}
+\TlSet \lTmpaTl {123\abc456}
+\TlVarLog \lTmpaTl
+\end{codehigh}
\end{function}
\begin{function}{\TlShow}
@@ -988,6 +1067,9 @@
\cs{TlShow} \Arg{token list}
\end{syntax}
Displays the \meta{token list} on the terminal.
+\begin{codehigh}
+\TlShow {123\abc456}
+\end{codehigh}
%\begin{texnote}
%This is similar to the \eTeX{} primitive \tn{showtokens}, wrapped
%to a fixed number of characters per line.
@@ -999,10 +1081,14 @@
\cs{TlVarShow} \meta{tl var}
\end{syntax}
Displays the content of the \meta{tl var} on the terminal.
-\begin{texnote}
-This is similar to the \TeX{} primitive \tn{show}, wrapped to a
-fixed number of characters per line.
-\end{texnote}
+\begin{codehigh}
+\TlSet \lTmpaTl {123\abc456}
+\TlVarShow \lTmpaTl
+\end{codehigh}
+%\begin{texnote}
+%This is similar to the \TeX{} primitive \tn{show}, wrapped to a
+%fixed number of characters per line.
+%\end{texnote}
\end{function}
\section{Setting Token List Variables}
@@ -1012,7 +1098,7 @@
\cs{TlSet} \meta{tl~var} \Arg{tokens}
\end{syntax}
Sets \meta{tl~var} to contain \meta{tokens},
-removing any previous content from the variable. For example
+removing any previous content from the variable.
\begin{demohigh}
\TlSet \lTmpiTl {\IntMathMult{4}{5}}
\TlUse \lTmpiTl
@@ -1023,8 +1109,12 @@
\begin{syntax}
\cs{TlSetEq} \meta{tl var_1} \meta{tl var_2}
\end{syntax}
-Sets the content of \meta{tl var_1} equal to that of
-\meta{tl var_2}.
+Sets the content of \meta{tl var_1} equal to that of \meta{tl var_2}.
+\begin{demohigh}
+\TlSet \lTmpaTl {abc}
+\TlSetEq \lTmpbTl \lTmpaTl
+\TlUse \lTmpbTl
+\end{demohigh}
\end{function}
\begin{function}{\TlClear}
@@ -1031,7 +1121,7 @@
\begin{syntax}
\cs{TlClear} \meta{tl~var}
\end{syntax}
-Clears all entries from the \meta{tl~var}. For example
+Clears all entries from the \meta{tl~var}.
\begin{demohigh}
\TlSet \lTmpjTl {One}
\TlClear \lTmpjTl
@@ -1047,6 +1137,9 @@
Ensures that the \meta{tl var} exists globally by applying
\cs{TlNew} if necessary, then applies \cs{TlClear} to leave
the \meta{tl var} empty.
+\begin{codehigh}
+\TlClearNew \lFooSomeTl
+\end{codehigh}
\end{function}
\begin{function}{\TlConcat}
@@ -1056,6 +1149,12 @@
Concatenates the content of \meta{tl var_2} and \meta{tl var_3}
together and saves the result in \meta{tl var_1}. The \meta{tl var_2}
is placed at the left side of the new token list.
+\begin{demohigh}
+\TlSet \lTmpbTl {con}
+\TlSet \lTmpcTl {cat}
+\TlConcat \lTmpaTl \lTmpbTl \lTmpcTl
+\TlUse \lTmpaTl
+\end{demohigh}
\end{function}
\begin{function}{\TlPutLeft}
@@ -1062,8 +1161,7 @@
\begin{syntax}
\cs{TlPutLeft} \meta{tl~var} \Arg{tokens}
\end{syntax}
-Appends \meta{tokens} to the left side of the current content of
-\meta{tl~var}. For example
+Appends \meta{tokens} to the left side of the current content of \meta{tl~var}.
\begin{demohigh}
\TlSet \lTmpkTl {Functional}
\TlPutLeft \lTmpkTl {Hello}
@@ -1075,8 +1173,7 @@
\begin{syntax}
\cs{TlPutRight} \meta{tl~var} \Arg{tokens}
\end{syntax}
-Appends \meta{tokens} to the right side of the current content of
-\meta{tl~var}. For example
+Appends \meta{tokens} to the right side of the current content of \meta{tl~var}.
\begin{demohigh}
\TlSet \lTmpkTl {Functional}
\TlPutRight \lTmpkTl {World}
@@ -1090,9 +1187,9 @@
no recursion into brace groups (more precisely, within a group defined by
a categroy code $1$/$2$ pair).
-\begin{function}{\TlReplaceOnce}
+\begin{function}{\TlVarReplaceOnce}
\begin{syntax}
-\cs{TlReplaceOnce} \meta{tl var} \Arg{old tokens} \Arg{new tokens}
+\cs{TlVarReplaceOnce} \meta{tl var} \Arg{old tokens} \Arg{new tokens}
\end{syntax}
Replaces the first (leftmost) occurrence of \meta{old tokens} in the
\meta{tl var} with \meta{new tokens}. \meta{Old tokens}
@@ -1099,11 +1196,16 @@
cannot contain \verb|{|, \verb|}| or \verb|#|
(more precisely, explicit character tokens with category code $1$
(begin-group) or $2$ (end-group), and tokens with category code $6$).
+\begin{demohigh}
+\TlSet \lTmpaTl {1{bc}2bc3}
+\TlVarReplaceOnce \lTmpaTl {bc} {xx}
+\TlUse \lTmpaTl
+\end{demohigh}
\end{function}
-\begin{function}{\TlReplaceAll}
+\begin{function}{\TlVarReplaceAll}
\begin{syntax}
-\cs{TlReplaceAll} \meta{tl var} \Arg{old tokens} \Arg{new tokens}
+\cs{TlVarReplaceAll} \meta{tl var} \Arg{old tokens} \Arg{new tokens}
\end{syntax}
Replaces all occurrences of \meta{old tokens} in the
\meta{tl var} with \meta{new tokens}. \meta{Old tokens}
@@ -1112,23 +1214,32 @@
(begin-group) or $2$ (end-group), and tokens with category code $6$).
As this function
operates from left to right, the pattern \meta{old tokens}
-may remain after the replacement (see \cs{TlRemoveAll}
-for an example).
+may remain after the replacement (see \cs{TlVarRemoveAll} for an example).
+\begin{demohigh}
+\TlSet \lTmpaTl {1{bc}2bc3}
+\TlVarReplaceAll \lTmpaTl {bc} {xx}
+\TlUse \lTmpaTl
+\end{demohigh}
\end{function}
-\begin{function}{\TlRemoveOnce}
+\begin{function}{\TlVarRemoveOnce}
\begin{syntax}
-\cs{TlRemoveOnce} \meta{tl var} \Arg{tokens}
+\cs{TlVarRemoveOnce} \meta{tl var} \Arg{tokens}
\end{syntax}
Removes the first (leftmost) occurrence of \meta{tokens} from the
\meta{tl var}. \meta{Tokens} cannot contain \verb|{|, \verb|}| or \verb|#|
(more precisely, explicit character tokens with category code $1$
(begin-group) or $2$ (end-group), and tokens with category code $6$).
+\begin{demohigh}
+\TlSet \lTmpaTl {1{bc}2bc3}
+\TlVarRemoveOnce \lTmpaTl {bc}
+\TlUse \lTmpaTl
+\end{demohigh}
\end{function}
-\begin{function}{\TlRemoveAll}
+\begin{function}{\TlVarRemoveAll}
\begin{syntax}
-\cs{TlRemoveAll} \meta{tl var} \Arg{tokens}
+\cs{TlVarRemoveAll} \meta{tl var} \Arg{tokens}
\end{syntax}
Removes all occurrences of \meta{tokens} from the
\meta{tl var}. \meta{Tokens} cannot contain \verb|{|, \verb|}| or \verb|#|
@@ -1139,7 +1250,7 @@
may remain after the removal, for instance,
\begin{demohigh}
\TlSet \lTmpaTl {abbccd}
-\TlRemoveAll \lTmpaTl {bc}
+\TlVarRemoveAll \lTmpaTl {bc}
\TlUse \lTmpaTl
\end{demohigh}
\end{function}
@@ -1151,6 +1262,9 @@
Removes any leading and trailing explicit space characters
(explicit tokens with character code $32$ and category code $10$)
from the \meta{token list} and returns the result.
+\begin{demohigh}
+Foo\TlTrimSpaces { 12 34 }Bar
+\end{demohigh}
%\begin{texnote}
%The result is returned within \tn{unexpanded}, which means that the token
%list does not expand further when appearing in an \texttt{x}-type
@@ -1165,6 +1279,11 @@
Sets the \meta{tl var} to contain the result of removing any leading
and trailing explicit space characters (explicit tokens with
character code $32$ and category code $10$) from its contents.
+\begin{demohigh}
+\TlSet \lTmpaTl { 12 34 }
+\TlVarTrimSpaces \lTmpaTl
+Foo\TlUse \lTmpaTl Bar
+\end{demohigh}
\end{function}
\section{Working with the Content of Token Lists}
@@ -1177,6 +1296,9 @@
Unbraced tokens count as one element as do each token group (\verb|{|$\cdots$\verb|}|).
This process ignores any unprotected spaces within \meta{tokens}. %See also \cs{TlVarCount}.
%This function requires three expansions, giving an \meta{integer denotation}.
+\begin{demohigh}
+\TlCount {12\abc34}
+\end{demohigh}
\end{function}
\begin{function}{\TlVarCount}
@@ -1187,6 +1309,10 @@
Unbraced tokens count as one element as do each token group (\verb|{|$\cdots$\verb|}|).
This process ignores any unprotected spaces within the \meta{tl var}. %See also \cs{TlCount}.
%This function requires three expansions, giving an \meta{integer denotation}.
+\begin{demohigh}
+\TlSet \lTmpaTl {12\abc34}
+\TlVarCount \lTmpaTl
+\end{demohigh}
\end{function}
\begin{function}{\TlHead}
@@ -1223,9 +1349,12 @@
\end{syntax}
Returns the first \meta{item} in the \meta{tl var},
discarding the rest of the \meta{tl var}.
-All leading explicit space characters
-(explicit tokens with character code $32$ and category code $10$)
-are discarded.
+All leading explicit space characters (explicit tokens with character code $32$
+and category code $10$) are discarded.
+\begin{demohigh}
+\TlSet \lTmpaTl {HELLO}
+\TlVarHead \lTmpaTl
+\end{demohigh}
\end{function}
\begin{function}{\TlTail}
@@ -1260,6 +1389,10 @@
(explicit tokens with character code $32$ and category code $10$)
and the first \meta{item} in the \meta{tl var}, and returns the
remaining tokens.
+\begin{demohigh}
+\TlSet \lTmpaTl {HELLO}
+\TlVarTail \lTmpaTl
+\end{demohigh}
\end{function}
\begin{function}{\TlItem,\TlVarItem}
@@ -1273,6 +1406,9 @@
If the \meta{integer expression} is negative, indexing occurs from
the right of the token list, starting at $-1$ for the right-most item.
If the index is out of bounds, then the function returns nothing.
+\begin{demohigh}
+\TlItem {abcd} {3}
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{item}
@@ -1289,6 +1425,10 @@
Selects and returns a pseudo-random item of the \meta{token list}.
If the \meta{token list} is blank, the result is empty.
%This is not available in older versions of \XeTeX{}.
+\begin{demohigh}
+\TlRandItem {abcdef}
+\TlRandItem {abcdef}
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{item}
@@ -1331,7 +1471,17 @@
\end{syntax}
Applies the \meta{inline function} to every \meta{item} stored within the
\meta{token list}. The \meta{inline function} should consist of code which
-receives the \meta{item} as \verb|#1|.
+receives the \meta{item} as \verb|#1|. For example,
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\TlMapInline {one} {
+ \TlPutRight \lTmpaTl {[#1]}
+}
+\Result{\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [o][n][e].
\end{function}
\begin{function}{\TlVarMapInline}
@@ -1340,7 +1490,18 @@
\end{syntax}
Applies the \meta{inline function} to every \meta{item} stored within the
\meta{tl var}. The \meta{inline function} should consist of code which
-receives the \meta{item} as \verb|#1|.
+receives the \meta{item} as \verb|#1|. For example,
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\TlSet \lTmpkTl {one}
+\TlVarMapInline \lTmpkTl {
+ \TlPutRight \lTmpaTl {[#1]}
+}
+\Result{\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [o][n][e].
\end{function}
%\begin{function}{\TlMapTokens,\TlVarMapTokens}
@@ -1371,6 +1532,15 @@
is not enforced. The assignments to the \meta{variable} are local.
Its value after the loop is the last \meta{item} in the
\meta{tl var}, or its original value if the \meta{tl var} is blank.
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\TlMapVariable {one} \lTmpiTl {
+ \TlPutRight \lTmpaTl {\Expand {[\lTmpiTl]}}
+}
+\Result{\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\TlVarMapVariable}
@@ -1383,6 +1553,16 @@
enforced. The assignments to the \meta{variable} are local. Its
value after the loop is the last \meta{item} in the \meta{tl var},
or its original value if the \meta{tl var} is blank.
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\TlSet \lTmpkTl {one}
+\TlVarMapVariable \lTmpkTl \lTmpiTl {
+ \TlPutRight \lTmpaTl {\Expand {[\lTmpiTl]}}
+}
+\Result{\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
%\begin{function}{\TlMapBreak}
@@ -1445,6 +1625,10 @@
\end{syntax}
Tests whether the \meta{tl var} is currently defined. This does not
check that the \meta{tl var} really is a token list variable.
+\begin{demohigh}
+\TlIfExistTF \lTmpaTl {\Result{Yes}} {\Result{No}}
+\TlIfExistTF \lFooUndefinedTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\TlIfEmpty,\TlIfEmptyTF}
@@ -1485,6 +1669,10 @@
\meta{token list} is zero or more explicit space characters
(explicit tokens with character code $32$ and category code $10$),
and is \texttt{false} otherwise.
+\begin{demohigh}
+\TlIfEmptyTF { } {\Result{Yes}} {\Result{No}}
+\TlIfBlankTF { } {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\TlIfEq,\TlIfEqTF}
@@ -1538,6 +1726,10 @@
(more precisely, explicit character tokens with category code $1$
(begin-group) or $2$ (end-group), and tokens with category code $6$).
The search does \emph{not} enter brace (category code $1$/$2$) groups.
+\begin{demohigh}
+\TlIfInTF {hello world} {o} {\Result{Yes}} {\Result{No}}
+\TlIfInTF {hello world} {a} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\TlVarIfIn,\TlVarIfInTF}
@@ -1550,6 +1742,11 @@
the tokens \verb|{|, \verb|}| or \verb|#|
(more precisely, explicit character tokens with category code $1$
(begin-group) or $2$ (end-group), and tokens with category code $6$).
+\begin{demohigh}
+\TlSet \lTmpaTl {hello world}
+\TlVarIfInTF \lTmpaTl {o} {\Result{Yes}} {\Result{No}}
+\TlVarIfInTF \lTmpaTl {a} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\TlIfSingle,\TlIfSingleTF}
@@ -1562,6 +1759,10 @@
begin-group character) or a single brace group, surrounded by
optional spaces on both sides. In other words, such a token list has
token count $1$ according to \cs{TlCount}.
+\begin{demohigh}
+\TlIfSingleTF {a} {\Result{Yes}} {\Result{No}}
+\TlIfSingleTF {abc} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\TlVarIfSingle,\TlVarIfSingleTF}
@@ -1574,6 +1775,12 @@
character nor a begin-group character) or a single brace group,
surrounded by optional spaces on both sides. In other words, such a
token list has token count $1$ according to \cs{TlVarCount}.
+\begin{demohigh}
+\TlSet \lTmpaTl {a}
+\TlVarIfSingleTF \lTmpaTl {\Result{Yes}} {\Result{No}}
+\TlSet \lTmpaTl {abc}
+\TlVarIfSingleTF \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\section{Token List Case Functions}
@@ -1594,6 +1801,19 @@
then the associated \meta{code} is left in the input
stream and other cases are discarded. The function
does nothing if there is no match.
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlSet \lTmpaTl {a}
+\TlSet \lTmpbTl {b}
+\TlSet \lTmpcTl {c}
+\TlSet \lTmpkTl {b}
+\TlVarCase \lTmpkTl {
+ \lTmpaTl {\Result {First}}
+ \lTmpbTl {\Result {Second}}
+ \lTmpcTl {\Result {Third}}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\TlVarCaseT}
@@ -1614,6 +1834,21 @@
stream and other cases are discarded. If any of the
cases are matched, the \meta{true code} is also inserted into the
input stream (after the code for the appropriate case).
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlSet \lTmpaTl {a}
+\TlSet \lTmpbTl {b}
+\TlSet \lTmpcTl {c}
+\TlSet \lTmpkTl {b}
+\TlVarCaseT \lTmpkTl {
+ \lTmpaTl {\IntSet \lTmpkInt {1}}
+ \lTmpbTl {\IntSet \lTmpkInt {2}}
+ \lTmpcTl {\IntSet \lTmpkInt {3}}
+}{
+ \Result {\IntUse \lTmpkInt}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\TlVarCaseF}
@@ -1631,9 +1866,23 @@
with each of the \meta{token list variable cases}. If the two
are equal (as described for \cs{TlVarIfEq})
then the associated \meta{code} is left in the input
-stream and other cases are discarded. If none
-match then the \meta{false code} is inserted into the input stream
- (after the code for the appropriate case).
+stream and other cases are discarded. If none match then the \meta{false code}
+is inserted into the input stream (after the code for the appropriate case).
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlSet \lTmpaTl {a}
+\TlSet \lTmpbTl {b}
+\TlSet \lTmpcTl {c}
+\TlSet \lTmpkTl {b}
+\TlVarCaseF \lTmpkTl{
+ \lTmpaTl {\Result {First}}
+ \lTmpbTl {\Result {Second}}
+ \lTmpcTl {\Result {Third}}
+}{
+ \Result {No~Match!}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\TlVarCaseTF}
@@ -1655,13 +1904,63 @@
stream and other cases are discarded. If any of the
cases are matched, the \meta{true code} is also inserted into the
input stream (after the code for the appropriate case), while if none
-match then the \meta{false code} is inserted. The function
-\cs{TlVarCase}, which does nothing if there is no match, is also
-available.
+match then the \meta{false code} is inserted. The function \cs{TlVarCase},
+which does nothing if there is no match, is also available.
+\begin{demohigh}
+\IgnoreSpacesOn
+\TlSet \lTmpaTl {a}
+\TlSet \lTmpbTl {b}
+\TlSet \lTmpcTl {c}
+\TlSet \lTmpkTl {b}
+\TlVarCaseTF \lTmpkTl {
+ \lTmpaTl {\IntSet \lTmpkInt {1}}
+ \lTmpbTl {\IntSet \lTmpkInt {2}}
+ \lTmpcTl {\IntSet \lTmpkInt {3}}
+}{
+ \Result {\IntUse \lTmpkInt}
+}{
+ \Result {0}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\chapter{Strings (\texttt{Str})}
+\TeX{} associates each character with a category code: as such, there is no
+concept of a \enquote{string} as commonly understood in many other
+programming languages. However, there are places where we wish to manipulate
+token lists while in some sense \enquote{ignoring} category codes: this is
+done by treating token lists as strings in a \TeX{} sense.
+
+A \TeX{} string (and thus an \pkg{expl3} string) is a series of characters
+which have category code $12$ (\enquote{other}) with the exception of
+space characters which have category code $10$ (\enquote{space}). Thus
+at a technical level, a \TeX{} string is a token list with the appropriate
+category codes. In this documentation, these are simply referred to as
+strings.
+
+String variables are simply specialised token lists, but by convention
+should be named with the suffix \texttt{Str}. Such variables
+should contain characters with category code $12$ (other), except
+spaces, which have category code $10$ (blank space). All the
+functions in this module which accept a token list argument first
+convert it to a string using \cs{TlToStr} for internal processing,
+and do not treat a token list or the corresponding string
+representation differently.
+
+As a string is a subset of the more general token list, it is sometimes unclear
+when one should be used over the other.
+Use a string variable for data that isn't primarily intended for typesetting
+and for which a level of protection from unwanted expansion is suitable.
+This data type simplifies comparison of variables since there are no concerns
+about expansion of their contents.
+
+%The functions \cs{CsToStr}, \cs{TlToStr}, \cs{TlVarToStr} and
+%\cs{TokenToStr} (and variants) generate strings from the appropriate
+%input: these are documented in modules \pkg{Cs}, \pkg{Tl} and \pkg{Token},
+%respectively.
+
\section{Constant and Scratch Strings}
\begin{variable}{\cAmpersandStr,\cAtsignStr,\cBackslashStr,\cLeftBraceStr,\cRightBraceStr,
@@ -1692,6 +1991,9 @@
Creates a new \meta{str var} or raises an error if the name is
already taken. The declaration is global. The \meta{str var} is
initially empty.
+\begin{codehigh}
+\StrNew \lFooSomeStr
+\end{codehigh}
\end{function}
\begin{function}{\StrConst}
@@ -1701,6 +2003,9 @@
Creates a new constant \meta{str var} or raises an error if the name
is already taken. The value of the \meta{str var} is set
globally to the \meta{token list}, converted to a string.
+\begin{codehigh}
+\StrConst \cFooSomeStr {12\abc34}
+\end{codehigh}
\end{function}
\begin{function}{\StrUse}
@@ -1711,6 +2016,9 @@
An error is raised if the variable
does not exist or if it is invalid. Note that it is possible to use
a \meta{str} directly without an accessor function.
+\begin{codehigh}
+\StrUse \lTmpaStr
+\end{codehigh}
\end{function}
\section{Viewing Strings}
@@ -1720,6 +2028,9 @@
\cs{StrLog} \Arg{token list}
\end{syntax}
Writes \meta{token list} in the log file.
+\begin{codehigh}
+\StrLog {1234\abcd5678}
+\end{codehigh}
\end{function}
\begin{function}{\StrVarLog}
@@ -1727,7 +2038,6 @@
\cs{StrVarLog} \meta{str var}
\end{syntax}
Writes the content of the \meta{str var} in the log file.
-For example
\begin{codehigh}
\StrSet \lTmpiStr {1234\abcd5678}
\StrVarLog \lTmpiStr
@@ -1739,6 +2049,9 @@
\cs{StrShow} \Arg{token list}
\end{syntax}
Displays \meta{token list} on the terminal.
+\begin{codehigh}
+\StrShow {1234\abcd5678}
+\end{codehigh}
\end{function}
\begin{function}{\StrVarShow}
@@ -1746,6 +2059,10 @@
\cs{StrVarShow} \meta{str var}
\end{syntax}
Displays the content of the \meta{str var} on the terminal.
+\begin{codehigh}
+\StrSet \lTmpiStr {1234\abcd5678}
+\StrVarShow \lTmpiStr
+\end{codehigh}
\end{function}
\section{Setting String Variables}
@@ -1755,7 +2072,7 @@
\cs{StrSet} \meta{str var} \Arg{token list}
\end{syntax}
Converts the \meta{token list} to a \meta{string}, and stores the
-result in \meta{str var}. For example
+result in \meta{str var}.
\begin{demohigh}
\StrSet \lTmpiStr {\IntMathMult{4}{5}}
\StrUse \lTmpiStr
@@ -1766,8 +2083,12 @@
\begin{syntax}
\cs{StrSetEq} \meta{str var_1} \meta{str var_2}
\end{syntax}
-Sets the content of \meta{str var_1} equal to that of
-\meta{str var_2}.
+Sets the content of \meta{str var_1} equal to that of \meta{str var_2}.
+\begin{demohigh}
+\StrSet \lTmpaStr {abc}
+\StrSetEq \lTmpbStr \lTmpaStr
+\StrUse \lTmpbStr
+\end{demohigh}
\end{function}
\begin{function}{\StrClear}
@@ -1790,6 +2111,10 @@
Ensures that the \meta{str var} exists globally by applying
\cs{StrNew} if necessary, then applies \cs{StrClear} to leave
the \meta{str var} empty.
+\begin{codehigh}
+\StrClearNew \lFooSomeStr
+\StrUse \lFooSomeStr
+\end{codehigh}
\end{function}
\begin{function}{\StrConcat}
@@ -1801,6 +2126,12 @@
is placed at the left side of the new string variable.
The \meta{str var_2} and \meta{str var_3} must indeed be strings, as
this function does not convert their contents to a string.
+\begin{demohigh}
+\StrSet \lTmpbStr {con}
+\StrSet \lTmpcStr {cat}
+\StrConcat \lTmpaStr \lTmpbStr \lTmpcStr
+\StrUse \lTmpaStr
+\end{demohigh}
\end{function}
\begin{function}{\StrPutLeft}
@@ -1809,7 +2140,7 @@
\end{syntax}
Converts the \meta{token list} to a \meta{string}, and prepends the
result to \meta{str var}. The current contents of the \meta{str
-var} are not automatically converted to a string. For example
+var} are not automatically converted to a string.
\begin{demohigh}
\StrSet \lTmpkStr {Functional}
\StrPutLeft \lTmpkStr {Hello}
@@ -1823,7 +2154,7 @@
\end{syntax}
Converts the \meta{token list} to a \meta{string}, and appends the
result to \meta{str var}. The current contents of the \meta{str
-var} are not automatically converted to a string. For example
+var} are not automatically converted to a string.
\begin{demohigh}
\StrSet \lTmpkStr {Functional}
\StrPutRight \lTmpkStr {World}
@@ -1833,18 +2164,23 @@
\section{Modifying String Variables}
-\begin{function}{\StrReplaceOnce}
+\begin{function}{\StrVarReplaceOnce}
\begin{syntax}
-\cs{StrReplaceOnce} \meta{str var} \Arg{old} \Arg{new}
+\cs{StrVarReplaceOnce} \meta{str var} \Arg{old} \Arg{new}
\end{syntax}
Converts the \meta{old} and \meta{new} token lists to strings, then
replaces the first (leftmost) occurrence of \meta{old string} in the
\meta{str var} with \meta{new string}.
+\begin{demohigh}
+\StrSet \lTmpaStr {a{bc}bcd}
+\StrVarReplaceOnce \lTmpaStr {bc} {xx}
+\StrUse \lTmpaStr
+\end{demohigh}
\end{function}
-\begin{function}{\StrReplaceAll}
+\begin{function}{\StrVarReplaceAll}
\begin{syntax}
-\cs{StrReplaceAll} \meta{str var} \Arg{old} \Arg{new}
+\cs{StrVarReplaceAll} \meta{str var} \Arg{old} \Arg{new}
\end{syntax}
Converts the \meta{old} and \meta{new} token lists to strings, then
replaces all occurrences of \meta{old string} in the
@@ -1852,20 +2188,29 @@
As this function
operates from left to right, the pattern \meta{old string}
may remain after the replacement.
+\begin{demohigh}
+\StrSet \lTmpaStr {a{bc}bcd}
+\StrVarReplaceAll \lTmpaStr {bc} {xx}
+\StrUse \lTmpaStr
+\end{demohigh}
\end{function}
-\begin{function}{\StrRemoveOnce}
+\begin{function}{\StrVarRemoveOnce}
\begin{syntax}
-\cs{StrRemoveOnce} \meta{str var} \Arg{token list}
+\cs{StrVarRemoveOnce} \meta{str var} \Arg{token list}
\end{syntax}
Converts the \meta{token list} to a \meta{string} then
-removes the first (leftmost) occurrence of \meta{string} from the
-\meta{str var}.
+removes the first (leftmost) occurrence of \meta{string} from the \meta{str var}.
+\begin{demohigh}
+\StrSet \lTmpaStr {a{bc}bcd}
+\StrVarRemoveOnce \lTmpaStr {bc}
+\StrUse \lTmpaStr
+\end{demohigh}
\end{function}
-\begin{function}{\StrRemoveAll}
+\begin{function}{\StrVarRemoveAll}
\begin{syntax}
-\cs{StrRemoveAll} \meta{str var} \Arg{token list}
+\cs{StrVarRemoveAll} \meta{str var} \Arg{token list}
\end{syntax}
Converts the \meta{token list} to a \meta{string} then
removes all occurrences of \meta{string} from the \meta{str var}.
@@ -1873,7 +2218,7 @@
the pattern \meta{string} may remain after the removal, for instance,
\begin{demohigh}
\StrSet \lTmpaStr {abbccd}
-\StrRemoveAll \lTmpaStr {bc}
+\StrVarRemoveAll \lTmpaStr {bc}
\TlUse \lTmpaStr
\end{demohigh}
\end{function}
@@ -1886,7 +2231,9 @@
\end{syntax}
Returns the number of characters in the string representation of \meta{token list},
as an integer denotation. All characters including spaces are counted.
-\par
+\begin{demohigh}
+\StrCount {12\abc34}
+\end{demohigh}
Due to naming conflict, you need to use \cs{StrSize} instead of \cs{StrCount}
if you want to use \verb!functional! package together with \verb!xstring! package.
\end{function}
@@ -1897,6 +2244,10 @@
\end{syntax}
Returns the number of characters in the string representation of the \meta{tl var},
as an integer denotation. All characters including spaces are counted.
+\begin{demohigh}
+\StrSet \lTmpaStr {12\abc34}
+\StrVarCount \lTmpaStr
+\end{demohigh}
\end{function}
\begin{function}{\StrHead}
@@ -1908,6 +2259,9 @@
with category code \enquote{other}. If the first character is a space,
it returns a space token with category code $10$ (blank space).
If the \meta{string} is empty, then nothing is returned.
+\begin{demohigh}
+\StrHead {HELLO}
+\end{demohigh}
\end{function}
\begin{function}{\StrVarHead}
@@ -1919,6 +2273,10 @@
with category code \enquote{other}. If the first character is a space,
it returns a space token with category code $10$ (blank space).
If the \meta{string} is empty, then nothing is returned.
+\begin{demohigh}
+\StrSet \lTmpaStr {HELLO}
+\StrVarHead \lTmpaStr
+\end{demohigh}
\end{function}
\begin{function}{\StrTail}
@@ -1931,6 +2289,9 @@
If the first character is a space, it only trims that space.
If the \meta{token list} is empty,
then nothing is left on the input stream.
+\begin{demohigh}
+\StrTail {HELLO}
+\end{demohigh}
\end{function}
\begin{function}{\StrVarTail}
@@ -1943,6 +2304,10 @@
If the first character is a space, it only trims that space.
If the \meta{token list} is empty,
then nothing is left on the input stream.
+\begin{demohigh}
+\StrSet \lTmpaStr {HELLO}
+\StrVarTail \lTmpaStr
+\end{demohigh}
\end{function}
\begin{function}{\StrItem}
@@ -1956,6 +2321,9 @@
If the \meta{integer expression} is negative,
characters are counted from the end of the \meta{string}. Hence,
$-1$ is the right-most character, \emph{etc.}
+\begin{demohigh}
+\StrItem {abcd} {3}
+\end{demohigh}
\end{function}
\begin{function}{\StrVarItem}
@@ -1969,6 +2337,10 @@
If the \meta{integer expression} is negative,
characters are counted from the end of the \meta{string}. Hence,
$-1$ is the right-most character, \emph{etc.}
+\begin{demohigh}
+\StrSet \lTmpaStr {abcd}
+\StrVarItem \lTmpaStr {3}
+\end{demohigh}
\end{function}
\section{Mapping over Strings}
@@ -1997,6 +2369,17 @@
\meta{str var} including spaces.
The \meta{inline function} should consist of code which
receives the \meta{character} as \verb|#1|.
+For example,
+\begin{codehigh}
+\IgnoreSpacesOn
+\StrClear \lTmpaStr
+\StrMapInline {one} {
+ \StrPutRight \lTmpaStr {[#1]}
+}
+\Result{\StrUse\lTmpaStr}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [o][n][e].
\end{function}
%\begin{function}{\StrMapTokens, \StrVarMapTokens}
@@ -2024,6 +2407,15 @@
\meta{variable} are local. Its value after the loop is the last
\meta{character} in the \meta{string}, or its original value if the
\meta{string} is empty.
+\begin{demohigh}
+\IgnoreSpacesOn
+\StrClear \lTmpaStr
+\StrMapVariable {one} \lTmpiStr {
+ \StrPutRight \lTmpaStr {\Expand {[\lTmpiStr]}}
+}
+\Result{\StrUse\lTmpaStr}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
%\begin{function}{\StrMapBreak}
@@ -2086,6 +2478,10 @@
\end{syntax}
Tests whether the \meta{str var} is currently defined. This does not
check that the \meta{str var} really is a string.
+\begin{demohigh}
+\StrIfExistTF\lTmpaStr{\Result{Yes}}{\Result{No}}
+\StrIfExistTF\lFooUndefinedStr{\Result{Yes}}{\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\StrVarIfEmpty,\StrVarIfEmptyTF}
@@ -2094,7 +2490,7 @@
\cs{StrVarIfEmptyTF} \meta{str var} \Arg{true code} \Arg{false code}
\end{syntax}
Tests if the \meta{string variable} is entirely empty
-(\emph{i.e.} contains no characters at all). For example
+(\emph{i.e.} contains no characters at all).
\begin{demohigh}
\StrSet \lTmpaStr {abc}
\StrVarIfEmptyTF \lTmpaStr {\Result{Empty}} {\Result{NonEmpty}}
@@ -2160,6 +2556,10 @@
\end{syntax}
Converts both \meta{token lists} to \meta{strings} and
tests whether \meta{string_2} is found inside \meta{string_1}.
+\begin{demohigh}
+\StrIfInTF {hello world} {o} {\Result{Yes}}{\Result{No}}
+\StrIfInTF {hello world} {a} {\Result{Yes}}{\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\StrVarIfIn,\StrVarIfInTF}
@@ -2168,8 +2568,12 @@
\cs{StrVarIfInTF} \meta{str var} \Arg{token list} \Arg{true code} \Arg{false code}
\end{syntax}
Converts the \meta{token list} to a \meta{string} and
-tests if that \meta{string} is found in the content of the
-\meta{str var}.
+tests if that \meta{string} is found in the content of the \meta{str var}.
+\begin{demohigh}
+\StrSet \lTmpaStr {hello world}
+\StrVarIfInTF \lTmpaStr {o} {\Result{Yes}}{\Result{No}}
+\StrVarIfInTF \lTmpaStr {a} {\Result{Yes}}{\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\StrCompare,\StrCompareTF}
@@ -2221,6 +2625,15 @@
If the two are equal (as described for
\cs{StrIfEq}) then the associated \meta{code} is left in the
input stream and other cases are discarded.
+\begin{demohigh}
+\IgnoreSpacesOn
+\StrCase {bbb} {
+ {aaa} {\Result{First}}
+ {bbb} {\Result{Second}}
+ {ccb} {\Result{Third}}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\StrCaseT}
@@ -2241,6 +2654,17 @@
input stream and other cases are discarded. If any of the
cases are matched, the \meta{true code} is also inserted into the
input stream (after the code for the appropriate case).
+\begin{demohigh}
+\IgnoreSpacesOn
+\StrCaseT {bbb} {
+ {aaa} {\TlSet\lTmpkTl{First}}
+ {bbb} {\TlSet\lTmpkTl{Second}}
+ {ccb} {\TlSet\lTmpkTl{Third}}
+}{
+ \Result{\TlUse\lTmpkTl}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\StrCaseF}
@@ -2260,6 +2684,17 @@
\cs{StrIfEq}) then the associated \meta{code} is left in the
input stream and other cases are discarded. If none
match then the \meta{false code} is inserted.
+\begin{demohigh}
+\IgnoreSpacesOn
+\StrCaseF {bbb} {
+ {aaa} {\Result{First}}
+ {bbb} {\Result{Second}}
+ {ccb} {\Result{Third}}
+}{
+ \Result{No~Match!}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\begin{function}{\StrCaseTF}
@@ -2282,6 +2717,19 @@
cases are matched, the \meta{true code} is also inserted into the
input stream (after the code for the appropriate case), while if none
match then the \meta{false code} is inserted.
+\begin{demohigh}
+\IgnoreSpacesOn
+\StrCaseTF {bbb} {
+ {aaa} {\TlSet\lTmpkTl{First}}
+ {bbb} {\TlSet\lTmpkTl{Second}}
+ {ccb} {\TlSet\lTmpkTl{Third}}
+}{
+ \Result{\TlUse\lTmpkTl}
+}{
+ \Result{No~Match!}
+}
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
\chapter{Integers (\texttt{Int})}
@@ -3787,6 +4235,9 @@
Creates a new \meta{comma list} or raises an error if the name is
already taken. The declaration is global. The \meta{comma list}
initially contains no items.
+\begin{codehigh}
+\ClistNew \lFooSomeClist
+\end{codehigh}
\end{function}
\begin{function}{\ClistConst}
@@ -3797,6 +4248,9 @@
if the name is already taken. The value of the
\meta{clist var} is set globally to the
\meta{comma list}.
+\begin{codehigh}
+\ClistConst \cFooSomeClist {one,two,three}
+\end{codehigh}
\end{function}
\begin{function}{\ClistVarJoin}
@@ -3808,7 +4262,6 @@
%If the comma list has a single item, it is placed in the input stream,
%and a comma list with no items produces no output.
%An error is raised if the variable does not exist or if it is invalid.
-For example,
\begin{demohigh}
\ClistSet \lTmpaClist { a , b , , c , {de} , f }
\ClistVarJoin \lTmpaClist { and }
@@ -3835,13 +4288,14 @@
%If the comma list has a single item, it is placed in the input stream,
%and a comma list with no items produces no output.
%An error is raised if the variable does not exist or if it is invalid.
-For example,
\begin{demohigh}
+\ClistSet \lTmpaClist { a , b }
+\ClistVarJoinExtended \lTmpaClist { and } {, } {, and }
+\end{demohigh}
+\begin{demohigh}
\ClistSet \lTmpaClist { a , b , , c , {de} , f }
\ClistVarJoinExtended \lTmpaClist { and } {, } {, and }
\end{demohigh}
-The first separator argument is not used in this case
-because the comma list has more than $2$ items.
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{items}
@@ -3862,6 +4316,12 @@
resulting space-trimmed item is braced. The \meta{separators} are
then inserted in the same way as for \cs{ClistVarJoin} and
\cs{ClistVarJoinExtended}, respectively.
+\begin{demohigh}
+\ClistJoinExtended { a , b } { and } {, } {, and }
+\end{demohigh}
+\begin{demohigh}
+\ClistJoinExtended { a , b , , c , {de} , f } { and } {, } {, and }
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{items}
@@ -3878,6 +4338,9 @@
\end{syntax}
Writes the entries in the comma list in the log file. See also
\cs{ClistShow} which displays the result in the terminal.
+\begin{codehigh}
+\ClistLog {one,two,three}
+\end{codehigh}
\end{function}
\begin{function}{\ClistVarLog}
@@ -3886,6 +4349,10 @@
\end{syntax}
Writes the entries in the \meta{comma list} in the log file. See
also \cs{ClistVarShow} which displays the result in the terminal.
+\begin{codehigh}
+\ClistSet \lTmpaClist {one,two,three}
+\ClistVarLog \lTmpaClist
+\end{codehigh}
\end{function}
\begin{function}{\ClistShow}
@@ -3893,6 +4360,9 @@
\cs{ClistShow} \Arg{tokens}
\end{syntax}
Displays the entries in the comma list in the terminal.
+\begin{codehigh}
+\ClistShow {one,two,three}
+\end{codehigh}
\end{function}
\begin{function}{\ClistVarShow}
@@ -3900,6 +4370,10 @@
\cs{ClistVarShow} \meta{comma list}
\end{syntax}
Displays the entries in the \meta{comma list} in the terminal.
+\begin{codehigh}
+\ClistSet \lTmpaClist {one,two,three}
+\ClistVarShow \lTmpaClist
+\end{codehigh}
\end{function}
\section{Setting Comma Lists}
@@ -3916,6 +4390,10 @@
To store some \meta{tokens} as a single \meta{item} even if the
\meta{tokens} contain commas or spaces, add a set of braces:
\cs{ClistSet} \meta{comma list} \verb|{| \Arg{tokens} \verb|}|.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,three}
+\ClistVarJoin \lTmpaClist { and }
+\end{demohigh}
\end{function}
\begin{function}{\ClistSetEq}
@@ -3927,16 +4405,27 @@
list variable, use \cs{TlSetEq}. Conversely, setting a comma
list variable to a token list is unadvisable unless one checks
space-trimming and related issues.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,three,four}
+\ClistSetEq \lTmpbClist \lTmpaClist
+\ClistVarJoin \lTmpbClist { and }
+\end{demohigh}
\end{function}
-%\begin{function}{\ClistSetFromSeq}
-%\begin{syntax}
-%\cs{ClistSetFromSeq} \meta{comma list} \meta{sequence}
-%\end{syntax}
-%Converts the data in the \meta{sequence} into a \meta{comma list}:
-%the original \meta{sequence} is unchanged.
-%Items which contain either spaces or commas are surrounded by braces.
-%\end{function}
+\begin{function}{\ClistSetFromSeq}
+\begin{syntax}
+\cs{ClistSetFromSeq} \meta{comma list} \meta{sequence}
+\end{syntax}
+Converts the data in the \meta{sequence} into a \meta{comma list}:
+the original \meta{sequence} is unchanged.
+Items which contain either spaces or commas are surrounded by braces.
+\begin{demohigh}
+\SeqPutRight \lTmpaSeq {one}
+\SeqPutRight \lTmpaSeq {two}
+\ClistSetFromSeq \lTmpaClist \lTmpaSeq
+\ClistVarJoin \lTmpaClist { and }
+\end{demohigh}
+\end{function}
\begin{function}{\ClistClear}
\begin{syntax}
@@ -3943,6 +4432,10 @@
\cs{ClistClear} \meta{comma list}
\end{syntax}
Clears all items from the \meta{comma list}.
+\begin{codehigh}
+\ClistSet \lTmpaClist {one,two,three,four}
+\ClistClear \lTmpaClist
+\end{codehigh}
\end{function}
\begin{function}{\ClistClearNew}
@@ -3952,6 +4445,11 @@
Ensures that the \meta{comma list} exists globally by applying
\cs{ClistNew} if necessary, then applies \cs{ClistClear} to leave
the list empty.
+\begin{demohigh}
+\ClistClearNew \lFooSomeClist
+\ClistSet \lFooSomeClist {one,two,three}
+\ClistVarJoin \lFooSomeClist { and }
+\end{demohigh}
\end{function}
\begin{function}{\ClistConcat}
@@ -3961,6 +4459,12 @@
Concatenates the content of \meta{comma list_2} and \meta{comma list_3}
together and saves the result in \meta{comma list_1}. The items in
\meta{comma list_2} are placed at the left side of the new comma list.
+\begin{demohigh}
+\ClistSet \lTmpbClist {one,two}
+\ClistSet \lTmpcClist {three,four}
+\ClistConcat \lTmpaClist \lTmpbClist \lTmpcClist
+\ClistVarJoin \lTmpaClist { + }
+\end{demohigh}
\end{function}
\begin{function}{\ClistPutLeft}
@@ -3974,6 +4478,11 @@
To append some \meta{tokens} as a single \meta{item} even if the
\meta{tokens} contain commas or spaces, add a set of braces:
\cs{ClistPutLeft} \meta{comma list} \verb|{| \Arg{tokens} \verb|}|.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two}
+\ClistPutLeft \lTmpaClist {zero}
+\ClistVarJoin \lTmpaClist { and }
+\end{demohigh}
\end{function}
\begin{function}{\ClistPutRight}
@@ -3987,6 +4496,11 @@
To append some \meta{tokens} as a single \meta{item} even if the
\meta{tokens} contain commas or spaces, add a set of braces:
\cs{ClistPutRight} \meta{comma list} \verb|{| \Arg{tokens} \verb|}|.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two}
+\ClistPutRight \lTmpaClist {three}
+\ClistVarJoin \lTmpaClist { and }
+\end{demohigh}
\end{function}
\section{Modifying Comma Lists}
@@ -3996,46 +4510,61 @@
to update comma lists, while retaining the order of the unaffected
entries.
-\begin{function}{\ClistRemoveDuplicates}
+\begin{function}{\ClistVarRemoveDuplicates}
\begin{syntax}
-\cs{ClistRemoveDuplicates} \meta{comma list}
+\cs{ClistVarRemoveDuplicates} \meta{comma list}
\end{syntax}
Removes duplicate items from the \meta{comma list}, leaving the
left most copy of each item in the \meta{comma list}. The \meta{item}
comparison takes place on a token basis, as for \cs{TlIfEqTF}.
-\begin{texnote}
-This function iterates through every item in the \meta{comma list} and
-does a comparison with the \meta{items} already checked. It is therefore
-relatively slow with large comma lists.
-Furthermore, it may fail if any of the items in the
-\meta{comma list} contains \verb|{|, \verb|}|, or \verb|#|
-(assuming the usual \TeX{} category codes apply).
-\end{texnote}
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,one,two,three}
+\ClistVarRemoveDuplicates \lTmpaClist
+\ClistVarJoin \lTmpaClist {,}
+\end{demohigh}
+%\begin{texnote}
+%This function iterates through every item in the \meta{comma list} and
+%does a comparison with the \meta{items} already checked. It is therefore
+%relatively slow with large comma lists.
+%Furthermore, it may fail if any of the items in the
+%\meta{comma list} contains \verb|{|, \verb|}|, or \verb|#|
+%(assuming the usual \TeX{} category codes apply).
+%\end{texnote}
\end{function}
-\begin{function}{\ClistRemoveAll}
+\begin{function}{\ClistVarRemoveAll}
\begin{syntax}
-\cs{ClistRemoveAll} \meta{comma list} \Arg{item}
+\cs{ClistVarRemoveAll} \meta{comma list} \Arg{item}
\end{syntax}
Removes every occurrence of \meta{item} from the \meta{comma list}.
The \meta{item} comparison takes place on a token basis, as for
\cs{TlIfEqTF}.
-\begin{texnote}
-The function may fail if the \meta{item} contains \verb|{|, \verb|}|, or \verb|#|
-(assuming the usual \TeX{} category codes apply).
-\end{texnote}
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,one,two,three}
+\ClistVarRemoveAll \lTmpaClist {two}
+\ClistVarJoin \lTmpaClist {,}
+\end{demohigh}
+%\begin{texnote}
+%The function may fail if the \meta{item} contains \verb|{|, \verb|}|, or \verb|#|
+%(assuming the usual \TeX{} category codes apply).
+%\end{texnote}
\end{function}
-\begin{function}{\ClistReverse}
+\begin{function}{\ClistVarReverse}
\begin{syntax}
-\cs{ClistReverse} \meta{comma list}
+\cs{ClistVarReverse} \meta{comma list}
\end{syntax}
Reverses the order of items stored in the \meta{comma list}.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,one,two,three}
+\ClistVarReverse \lTmpaClist
+\ClistVarJoin \lTmpaClist {,}
+\end{demohigh}
\end{function}
-%\begin{function}{\ClistSort}
+%\begin{function}{\ClistVarSort}
%\begin{syntax}
-%\cs{ClistSort} \meta{clist var} \Arg{comparison code}
+%\cs{ClistVarSort} \meta{clist var} \Arg{comparison code}
%\end{syntax}
%Sorts the items in the \meta{clist var} according to the
%\meta{comparison code}, and assigns the result to
@@ -4054,6 +4583,10 @@
as an \meta{integer denotation}. The total number of items
in a \meta{comma list} includes those which are duplicates,
\emph{i.e.} every item in a \meta{comma list} is counted.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,three,four}
+\ClistVarCount \lTmpaClist
+\end{demohigh}
\end{function}
\begin{function}{\ClistItem}
@@ -4067,6 +4600,10 @@
bottom (right) of the comma list. When the \meta{integer expression}
is larger than the number of items in the \meta{comma list} (as
calculated by \cs{ClistCount}) then the function returns nothing.
+\begin{demohigh}
+\TlSet \lTmpaTl {\ClistItem {one,two,three,four} {3}}
+\TlUse \lTmpaTl
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{item}
@@ -4086,6 +4623,11 @@
bottom (right) of the comma list. When the \meta{integer expression}
is larger than the number of items in the \meta{comma list} (as
calculated by \cs{ClistVarCount}) then the function returns nothing.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two,three,four}
+\TlSet \lTmpaTl {\ClistVarItem \lTmpaClist {3}}
+\TlUse \lTmpaTl
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{item}
@@ -4101,6 +4643,12 @@
\end{syntax}
Selects a pseudo-random item of the \meta{comma list}.
If the \meta{comma list} has no item, the result is empty.
+\begin{demohigh}
+\TlSet \lTmpaTl {\ClistRandItem {one,two,three,four,five,six}}
+\TlUse \lTmpaTl
+\TlSet \lTmpaTl {\ClistRandItem {one,two,three,four,five,six}}
+\TlUse \lTmpaTl
+\end{demohigh}
%\begin{texnote}
%The result is returned within the \tn{unexpanded}
%primitive (\cs{exp_not:n}), which means that the \meta{item}
@@ -4118,36 +4666,77 @@
in the previous section: a comma list should either be used as an
ordered data type or as a stack, but not in both ways.
-\begin{function}{\ClistGet,\ClistGetTF}
+\begin{function}{\ClistGet}
\begin{syntax}
\cs{ClistGet} \meta{comma list} \meta{token list variable}
+\end{syntax}
+Stores the left-most item from the \meta{comma list} in the
+\meta{token list variable} without removing it from the
+\meta{comma list}. The \meta{token list variable} is assigned locally.
+If the \meta{comma list} is empty the
+\meta{token list variable} is set to the marker value \cs{qNoValue}.
+\begin{demohigh}
+\ClistSet \lTmpaClist {two,three,four}
+\ClistGet \lTmpaClist \lTmpaTl
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\ClistGetT,\ClistGetF,\ClistGetTF}
+\begin{syntax}
\cs{ClistGetT} \meta{comma list} \meta{token list variable} \meta{true code}
\cs{ClistGetF} \meta{comma list} \meta{token list variable} \meta{false code}
\cs{ClistGetTF} \meta{comma list} \meta{token list variable} \meta{true code} \meta{false code}
\end{syntax}
-Stores the left-most item from a \meta{comma list} in the
-\meta{token list variable} without removing it from the
-\meta{comma list}. The \meta{token list variable} is assigned locally.
-%In the non-branching version, if the \meta{comma list} is empty the
-%\meta{token list variable} is set to the marker value \cs{qNoValue}.
+If the \meta{comma list} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{comma list} is non-empty, stores the left-most item from the
+\meta{comma list} in the \meta{token list variable} without removing
+it from the \meta{comma list}.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\ClistSet \lTmpaClist {two,three,four}
+\ClistGetTF \lTmpaClist \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
-
-\begin{function}{\ClistPop,\ClistPopT,\ClistPopF,\ClistPopTF}
+
+\begin{function}{\ClistPop}
\begin{syntax}
\cs{ClistPop} \meta{comma list} \meta{token list variable}
-\cs{ClistPopT} \meta{comma list} \meta{token list variable} \Arg{true code}
-\cs{ClistPopF} \meta{comma list} \meta{token list variable} \Arg{false code}
-\cs{ClistPopTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code}
\end{syntax}
Pops the left-most item from a \meta{comma list} into the
\meta{token list variable}, \emph{i.e.} removes the item from the
comma list and stores it in the \meta{token list variable}.
The assignment of the \meta{token list variable} is local.
-If the \meta{comma list} is empty,
-the value of the \meta{token list variable} is
-not defined in this case and should not be relied upon.
+If the \meta{comma list} is empty the
+\meta{token list variable} is set to the marker value \cs{qNoValue}.
+\begin{demohigh}
+\ClistSet \lTmpaClist {two,three,four}
+\ClistPop \lTmpaClist \lTmpaTl
+\ClistVarJoin \lTmpaClist {,}
+\end{demohigh}
\end{function}
-
+
+\begin{function}{\ClistPopT,\ClistPopF,\ClistPopTF}
+\begin{syntax}
+\cs{ClistPopT} \meta{comma list} \meta{token list variable} \Arg{true code}
+\cs{ClistPopF} \meta{comma list} \meta{token list variable} \Arg{false code}
+\cs{ClistPopTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{comma list} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{comma list} is non-empty, pops the top item from the
+\meta{comma list} in the \meta{token list variable}, \emph{i.e.} removes
+the item from the \meta{comma list}.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\ClistSet \lTmpaClist {two,three,four}
+\ClistPopTF \lTmpaClist \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
\begin{function}{\ClistPush}
\begin{syntax}
\cs{ClistPush} \meta{comma list} \Arg{items}
@@ -4155,6 +4744,11 @@
Adds the \Arg{items} to the top of the \meta{comma list}.
Spaces are removed from both sides of each item as for any
\texttt{n}-type comma list.
+\begin{demohigh}
+\ClistSet \lTmpaClist {two,three,four}
+\ClistPush \lTmpaClist {zero,one}
+\ClistVarJoin \lTmpaClist {|}
+\end{demohigh}
\end{function}
\section{Mapping over Comma Lists}
@@ -4225,6 +4819,14 @@
Its value after the loop is the last \meta{item} in the \meta{comma
list}, or its original value if there were no \meta{item}. The
\meta{items} are returned from left to right.
+\begin{demohigh}
+\IgnoreSpacesOn
+\ClistMapVariable {one,two,three} \lTmpiTl {
+ \TlPutRight \gTmpaTl {\Expand {(\lTmpiTl)}}
+}
+\TlUse \gTmpaTl
+\IgnoreSpacesOff
+\end{demohigh}
\end{function}
%\begin{function}{\ClistMapTokens,\ClistVarMapTokens}
@@ -4302,6 +4904,10 @@
\end{syntax}
Tests whether the \meta{comma list} is currently defined. This does
not check that the \meta{comma list} really is a comma list.
+\begin{demohigh}
+\ClistIfExistTF \lTmpaClist {\Result{Yes}} {\Result{No}}
+\ClistIfExistTF \lFooUndefinedClist {\Result{Yes}} {\Result{No}}
+\end{demohigh}
\end{function}
\begin{function}{\ClistIfEmpty,\ClistIfEmptyTF}
@@ -4315,6 +4921,10 @@
outer braces) is empty, while \verb|{ ,{},}| (without outer braces)
contains one element, which happens to be empty: the comma-list
is not empty.
+\begin{demohigh}
+\ClistIfEmptyTF {one,two} {\Result{Empty}} {\Result{NonEmpty}}
+\ClistIfEmptyTF { , } {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
\end{function}
\begin{function}{\ClistVarIfEmpty,\ClistVarIfEmptyTF}
@@ -4323,6 +4933,12 @@
\cs{ClistVarIfEmptyTF} \meta{comma list} \Arg{true code} \Arg{false code}
\end{syntax}
Tests if the \meta{comma list} is empty (containing no items).
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two}
+\ClistVarIfEmptyTF \lTmpaClist {\Result{Empty}} {\Result{NonEmpty}}
+\ClistClear \lTmpaClist
+\ClistVarIfEmptyTF \lTmpaClist {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
\end{function}
\begin{function}{\ClistIfIn,\ClistIfInTF}
@@ -4334,7 +4950,8 @@
In the case of an \texttt{n}-type \meta{comma list}, the usual rules
of space trimming and brace stripping apply. For example
\begin{demohigh}
-\ClistIfInTF { a , {b} , {b} , c } {b} {Yes} {No}
+\ClistIfInTF { a , {b} , {b} , c } {b} {\Result{Yes}} {\Result{No}}
+\ClistIfInTF { a , {b} , {b} , c } {d} {\Result{Yes}} {\Result{No}}
\end{demohigh}
%\begin{texnote}
%The function may fail if the \meta{item} contains \verb|{|, \verb|}|, or \verb|#|
@@ -4350,6 +4967,11 @@
Tests if the \meta{item} is present in the \meta{comma list}.
In the case of an \texttt{n}-type \meta{comma list}, the usual rules
of space trimming and brace stripping apply.
+\begin{demohigh}
+\ClistSet \lTmpaClist {one,two}
+\ClistVarIfInTF \lTmpaClist {one} {\Result{Yes}} {\Result{No}}
+\ClistVarIfInTF \lTmpaClist {three} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
%\begin{texnote}
%The function may fail if the \meta{item} contains \verb|{|, \verb|}|, or \verb|#|
%(assuming the usual \TeX{} category codes apply).
@@ -4356,6 +4978,1463 @@
%\end{texnote}
\end{function}
+\chapter{Sequences and Stacks (\texttt{Seq})}
+
+\section{Constant and Scratch Sequences}
+
+\begin{variable}{\cEmptySeq}
+Constant that is always empty.
+\end{variable}
+
+\begin{variable}{\lTmpaSeq,\lTmpbSeq,\lTmpcSeq,\lTmpiSeq,\lTmpjSeq,\lTmpkSeq}
+Scratch sequences for local assignment. These are never used by
+the \verb!functional! package, and so are safe for use with any
+function. However, they may be overwritten by other
+code and so should only be used for short-term storage.
+\end{variable}
+
+\begin{variable}{\gTmpaSeq,\gTmpbSeq,\gTmpcSeq,\gTmpiSeq,\gTmpjSeq,\gTmpkSeq}
+Scratch sequences for global assignment. These are never used by
+the \verb!functional! package, and so are safe for use with any
+function. However, they may be overwritten by other
+code and so should only be used for short-term storage.
+\end{variable}
+
+\section{Creating and Using Sequences}
+
+\begin{function}{\SeqNew}
+\begin{syntax}
+\cs{SeqNew} \meta{sequence}
+\end{syntax}
+Creates a new \meta{sequence} or raises an error if the name is
+already taken. The declaration is global. The \meta{sequence}
+initially contains no items.
+\begin{codehigh}
+\SeqNew \lFooSomeSeq
+\end{codehigh}
+\end{function}
+
+\begin{function}{\SeqConstFromClist}
+\begin{syntax}
+\cs{SeqConstFromClist} \meta{seq var} \Arg{comma-list}
+\end{syntax}
+Creates a new constant \meta{seq var} or raises an error if the name
+is already taken. The \meta{seq var} is set globally to contain the
+items in the \meta{comma list}.
+\begin{codehigh}
+\SeqConstFromClist \cFooSomeSeq {one,two,three}
+\end{codehigh}
+\end{function}
+
+\begin{function}{\SeqVarJoin}
+\begin{syntax}
+\cs{SeqVarJoin} \meta{seq var} \Arg{separator}
+\end{syntax}
+Returns the contents of the \meta{seq var}, with
+the \meta{separator} between the items. If the sequence has
+a single item, it is returned with no \meta{separator},
+and an empty sequence returns nothing. An error is raised if
+the variable does not exist or if it is invalid.
+\begin{demohigh}
+\SeqSetSplit \lTmpaSeq {|} {a|b|c|{de}|f}
+\SeqVarJoin \lTmpaSeq { and }
+\end{demohigh}
+%\begin{texnote}
+%The result is returned within the \tn{unexpanded}
+%primitive (\cs{exp_not:n}), which means that the \meta{items}
+%do not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\SeqVarJoinExtended}
+\begin{syntax}
+\cs{SeqVarJoinExtended} \meta{seq var} \Arg{separator between two} \Arg{separator between more than two} \Arg{separator between final two}
+\end{syntax}
+Returns the contents of the \meta{seq var}, with
+the appropriate \meta{separator} between the items. Namely, if the
+sequence has more than two items, the \meta{separator between more
+than two} is placed between each pair of items except the last,
+for which the \meta{separator between final two} is used. If the
+sequence has exactly two items, then they are joined
+with the \meta{separator between two} and returned. If the sequence has
+a single item, it is returned, and an empty sequence
+returns nothing. An error is raised if the variable does
+not exist or if it is invalid.
+\begin{demohigh}
+\SeqSetSplit \lTmpaSeq {|} {a|b|c|{de}|f}
+\SeqVarJoinExtended \lTmpaSeq { and } {, } {, and }
+\end{demohigh}
+The first separator argument is not used in this case
+because the sequence has more than $2$ items.
+%\begin{texnote}
+%The result is returned within the \tn{unexpanded}
+%primitive (\cs{exp_not:n}), which means that the \meta{items}
+%do not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\section{Viewing Sequences}
+
+\begin{function}{\SeqVarLog}
+\begin{syntax}
+\cs{SeqVarLog} \meta{sequence}
+\end{syntax}
+Writes the entries in the \meta{sequence} in the log file.
+\begin{codehigh}
+\SeqVarLog \lFooSomeSeq
+\end{codehigh}
+\end{function}
+
+\begin{function}{\SeqVarShow}
+\begin{syntax}
+\cs{SeqVarShow} \meta{sequence}
+\end{syntax}
+Displays the entries in the \meta{sequence} in the terminal.
+\begin{codehigh}
+\SeqVarShow \lFooSomeSeq
+\end{codehigh}
+\end{function}
+
+\section{Setting Sequences}
+
+\begin{function}{\SeqSetFromClist}
+\begin{syntax}
+\cs{SeqSetFromClist} \meta{sequence} \meta{comma-list}
+\end{syntax}
+Converts the data in the \meta{comma list} into a \meta{sequence}:
+the original \meta{comma list} is unchanged.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,three}
+\SeqVarJoin \lTmpaSeq { and }
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqSetSplit}
+\begin{syntax}
+\cs{SeqSetSplit} \meta{sequence} \Arg{delimiter} \Arg{token list}
+\end{syntax}
+Splits the \meta{token list} into \meta{items} separated
+by \meta{delimiter}, and assigns the result to the \meta{sequence}.
+Spaces on both sides of each \meta{item} are ignored,
+then one set of outer braces is removed (if any);
+this space trimming behaviour is identical to that of
+\pkg{Clist} functions. Empty \meta{items} are preserved by
+\cs{SeqSetSplit}, and can be removed afterwards using
+\cs{SeqVarRemoveAll} \meta{sequence} \verb|{}|.
+The \meta{delimiter} may not contain \verb|{|, \verb|}| or \verb|#|
+(assuming \TeX{}'s normal category code r\'egime).
+If the \meta{delimiter} is empty, the \meta{token list} is split
+into \meta{items} as a \meta{token list}.
+%See also \cs{SeqSetSplitKeepSpaces}, which omits space stripping.
+\begin{demohigh}
+\SeqSetSplit \lTmpaSeq {,} {1,2,3}
+\SeqVarJoin \lTmpaSeq { and }
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqSetEq}
+\begin{syntax}
+\cs{SeqSetEq} \meta{sequence_1} \meta{sequence_2}
+\end{syntax}
+Sets the content of \meta{sequence_1} equal to that of
+\meta{sequence_2}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,three,four}
+\SeqSetEq \lTmpbSeq \lTmpaSeq
+\SeqVarJoin \lTmpbSeq { and }
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqClear}
+\begin{syntax}
+\cs{SeqClear} \meta{sequence}
+\end{syntax}
+Clears all items from the \meta{sequence}.
+\begin{codehigh}
+\SeqClear \lTmpaSeq
+\end{codehigh}
+\end{function}
+
+\begin{function}{\SeqClearNew}
+\begin{syntax}
+\cs{SeqClearNew} \meta{sequence}
+\end{syntax}
+Ensures that the \meta{sequence} exists globally by applying
+\cs{SeqNew} if necessary, then applies \cs{SeqClear} to leave
+the \meta{sequence} empty.
+\begin{demohigh}
+\SeqClearNew \lFooSomeSeq
+\SeqSetFromClist \lFooSomeSeq {one,two,three}
+\SeqVarJoin \lFooSomeSeq { and }
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqConcat}
+\begin{syntax}
+\cs{SeqConcat} \meta{sequence_1} \meta{sequence_2} \meta{sequence_3}
+\end{syntax}
+Concatenates the content of \meta{sequence_2} and \meta{sequence_3}
+together and saves the result in \meta{sequence_1}. The items in
+\meta{sequence_2} are placed at the left side of the new sequence.
+\begin{demohigh}
+\SeqSetFromClist \lTmpbSeq {one,two}
+\SeqSetFromClist \lTmpcSeq {three,four}
+\SeqConcat \lTmpaSeq \lTmpbSeq \lTmpcSeq
+\SeqVarJoin \lTmpaSeq {, }
+\end{demohigh}
+\end{function}
+
+%\begin{function}{\SeqSetSplitKeepSpaces}
+%\begin{syntax}
+%\cs{SeqSetSplitKeepSpaces} \meta{sequence} \Arg{delimiter} \Arg{token list}
+%\end{syntax}
+%Splits the \meta{token list} into \meta{items} separated
+%by \meta{delimiter}, and assigns the result to the \meta{sequence}.
+%One set of outer braces is removed (if any) but any surrounding spaces
+%are retained: any braces \emph{inside} one or more spaces are
+%therefore kept. Empty \meta{items} are preserved by
+%\cs{SeqSetSplitKeepSpaces}, and can be removed afterwards using
+%\cs{SeqVarRemoveAll} \meta{sequence} \verb|{}|.
+%The \meta{delimiter} may not contain \verb|{|, \verb|}| or \verb|#|
+%(assuming \TeX{}'s normal category code r\'egime).
+%If the \meta{delimiter} is empty, the \meta{token list} is split
+%into \meta{items} as a \meta{token list}.
+%%See also \cs{SeqSetSplit}, which removes spaces around the delimiters.
+%\end{function}
+
+\begin{function}{\SeqPutLeft}
+\begin{syntax}
+\cs{SeqPutLeft} \meta{sequence} \Arg{item}
+\end{syntax}
+Appends the \meta{item} to the left of the \meta{sequence}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two}
+\SeqPutLeft \lTmpaSeq {zero}
+\SeqVarJoin \lTmpaSeq { and }
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPutRight}
+\begin{syntax}
+\cs{SeqPutRight} \meta{sequence} \Arg{item}
+\end{syntax}
+Appends the \meta{item} to the right of the \meta{sequence}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two}
+\SeqPutRight \lTmpaSeq {three}
+\SeqVarJoin \lTmpaSeq { and }
+\end{demohigh}
+\end{function}
+
+\section{Modifying Sequences}
+
+While sequences are normally used as ordered lists, it may be
+necessary to modify the content. The functions here may be used
+to update sequences, while retaining the order of the unaffected
+entries.
+
+\begin{function}{\SeqVarRemoveDuplicates}
+\begin{syntax}
+\cs{SeqVarRemoveDuplicates} \meta{sequence}
+\end{syntax}
+Removes duplicate items from the \meta{sequence}, leaving the
+left most copy of each item in the \meta{sequence}. The \meta{item}
+comparison takes place on a token basis, as for \cs{TlIfEqTF}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,one,two,three}
+\SeqVarRemoveDuplicates \lTmpaSeq
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+%\begin{texnote}
+%This function iterates through every item in the \meta{sequence} and
+%does a comparison with the \meta{items} already checked. It is therefore
+%relatively slow with large sequences.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\SeqVarRemoveAll}
+\begin{syntax}
+\cs{SeqVarRemoveAll} \meta{sequence} \Arg{item}
+\end{syntax}
+Removes every occurrence of \meta{item} from the \meta{sequence}.
+The \meta{item} comparison takes place on a token basis, as for \cs{TlIfEqTF}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,one,two,three}
+\SeqVarRemoveAll \lTmpaSeq {two}
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqVarReverse}
+\begin{syntax}
+\cs{SeqVarReverse} \meta{sequence}
+\end{syntax}
+Reverses the order of the items stored in the \meta{sequence}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,one,two,three}
+\SeqVarReverse \lTmpaSeq
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+\end{function}
+
+%\begin{function}{\SeqVarSort}
+%\begin{syntax}
+%\cs{SeqVarSort} \meta{sequence} \Arg{comparison code}
+%\end{syntax}
+%Sorts the items in the \meta{sequence} according to the
+%\meta{comparison code}, and assigns the result to
+%\meta{sequence}. The details of sorting comparison are
+%described in Section \ref{sec:l3sort:mech}.
+%\end{function}
+
+%\begin{function}{\SeqVarShuffle}
+%\begin{syntax}
+%\cs{SeqVarShuffle} \meta{seq var}
+%\end{syntax}
+%Sets the \meta{seq var} to the result of placing the items of the
+%\meta{seq var} in a random order. Each item is (roughly) as likely
+%to end up in any given position.
+%\begin{texnote}
+%For sequences with more than $13$ items or so, only a small
+%proportion of all possible permutations can be reached, because
+%the random seed \cs{sys_rand_seed:} only has $28$-bits. The use
+%of \tn{toks} internally means that sequences with more than
+%$32767$ or $65535$ items (depending on the engine) cannot be
+%shuffled.
+%\end{texnote}
+%\end{function}
+
+\section{Working with the Contents of Sequences}
+
+\begin{function}{\SeqVarCount}
+\begin{syntax}
+\cs{SeqVarCount} \meta{sequence}
+\end{syntax}
+Returns the number of items in the \meta{sequence}
+as an \meta{integer denotation}. The total number of items
+in a \meta{sequence} includes those which are empty and duplicates,
+\emph{i.e.} every item in a \meta{sequence} is unique.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,three,four}
+\SeqVarCount \lTmpaSeq
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqVarItem}
+\begin{syntax}
+\cs{SeqVarItem} \meta{sequence} \Arg{integer expression}
+\end{syntax}
+Indexing items in the \meta{sequence} from $1$ at the top (left), this
+function evaluates the \meta{integer expression} and returns the
+appropriate item from the sequence. If the
+\meta{integer expression} is negative, indexing occurs from the
+bottom (right) of the sequence. If the \meta{integer expression}
+is larger than the number of items in the \meta{sequence} (as
+calculated by \cs{SeqVarCount}) then the function returns nothing.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,three,four}
+\TlSet \lTmpaTl {\SeqVarItem \lTmpaSeq {3}}
+\TlUse \lTmpaTl
+\end{demohigh}
+%\begin{texnote}
+%The result is returned within the \tn{unexpanded}
+%primitive (\cs{exp_not:n}), which means that the \meta{item}
+%does not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\SeqVarRandItem}
+\begin{syntax}
+\cs{SeqVarRandItem} \meta{seq var}
+\end{syntax}
+Selects a pseudo-random item of the \meta{sequence}. If the
+\meta{sequence} is empty the result is empty.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two,three,four,five,six}
+\TlSet \lTmpaTl {\SeqVarRandItem \lTmpaSeq}
+\TlUse \lTmpaTl
+\TlSet \lTmpaTl {\SeqVarRandItem \lTmpaSeq}
+\TlUse \lTmpaTl
+\end{demohigh}
+%This is not available in older versions of \XeTeX{}.
+%\begin{texnote}
+%The result is returned within the \tn{unexpanded}
+%primitive (\cs{exp_not:n}), which means that the \meta{item}
+%does not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\section{Sequences as Stacks}
+
+Sequences can be used as stacks, where data is pushed to and popped
+from the top of the sequence. (The left of a sequence is the top, for
+performance reasons.) The stack functions for sequences are not
+intended to be mixed with the general ordered data functions detailed
+in the previous section: a sequence should either be used as an
+ordered data type or as a stack, but not in both ways.
+
+\begin{function}{\SeqGet}
+\begin{syntax}
+\cs{SeqGet} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Reads the top item from a \meta{sequence} into the
+\meta{token list variable} without removing it from the
+\meta{sequence}. The \meta{token list variable} is assigned locally.
+If \meta{sequence} is empty the \meta{token list variable} is set to
+the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGet \lTmpaSeq \lTmpaTl
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqGetT,\SeqGetF,\SeqGetTF}
+\begin{syntax}
+\cs{SeqGetT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqGetF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqGetTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, stores the top item from a
+\meta{sequence} in the \meta{token list variable} without removing it from
+the \meta{sequence}. The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGetTF \lTmpaSeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPop}
+\begin{syntax}
+\cs{SeqPop} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Pops the top item from a \meta{sequence} into the
+\meta{token list variable}. the \meta{token list variable} is assigned locally.
+If \meta{sequence} is empty the \meta{token list variable} is set to
+the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqPop \lTmpaSeq \lTmpaTl
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPopT,\SeqPopF,\SeqPopTF}
+\begin{syntax}
+\cs{SeqPopT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqPopF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqPopTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, pops the top item from the \meta{sequence}
+in the \meta{token list variable}, \emph{i.e.} removes the item from the
+\meta{sequence}. The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqPopTF \cEmptySeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPush}
+\begin{syntax}
+\cs{SeqPush} \meta{sequence} \Arg{item}
+\end{syntax}
+Adds the \Arg{item} to the top of the \meta{sequence}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqPush \lTmpaSeq {one}
+\SeqVarJoin \lTmpaSeq {|}
+\end{demohigh}
+You can only push one item to the \meta{sequence} with \cs{SeqPush},
+which is different from \cs{ClistPush}.
+\end{function}
+
+\section{Recovering Items from Sequences}
+
+Items can be recovered from either the left or the right of sequences.
+For implementation reasons, the actions at the left of the sequence are
+faster than those acting on the right. These functions all assign the
+recovered material locally.
+
+\begin{function}{\SeqGetLeft}
+\begin{syntax}
+\cs{SeqGetLeft} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Stores the left-most item from a \meta{sequence} in the
+\meta{token list variable} without removing it from the
+\meta{sequence}. The \meta{token list variable} is assigned locally.
+If \meta{sequence} is empty the \meta{token list variable}
+is set to the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGetLeft \lTmpaSeq \lTmpaTl
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqGetLeftT,\SeqGetLeftF,\SeqGetLeftTF}
+\begin{syntax}
+\cs{SeqGetLeftT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqGetLeftF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqGetLeftTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, stores the left-most item from the
+\meta{sequence}
+in the \meta{token list variable} without removing it from the
+\meta{sequence}, then leaves the \meta{true code} in the input stream.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGetLeftTF \lTmpaSeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqGetRight}
+\begin{syntax}
+\cs{SeqGetRight} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Stores the right-most item from a \meta{sequence} in the
+\meta{token list variable} without removing it from the
+\meta{sequence}. The \meta{token list variable} is assigned locally.
+If \meta{sequence} is empty the \meta{token list variable}
+is set to the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGetRight \lTmpaSeq \lTmpaTl
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqGetRightT,\SeqGetRightF,\SeqGetRightTF}
+\begin{syntax}
+\cs{SeqGetRightT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqGetRightF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqGetRightTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, stores the right-most item from the
+\meta{sequence}
+in the \meta{token list variable} without removing it from the
+\meta{sequence}, then leaves the \meta{true code} in the input stream.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqGetRightTF \lTmpaSeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPopLeft}
+\begin{syntax}
+\cs{SeqPopLeft} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Pops the left-most item from a \meta{sequence} into the
+\meta{token list variable}, \emph{i.e.} removes the item from the
+sequence and stores it in the \meta{token list variable}.
+The assignment of the \meta{token list variable} is local.
+If \meta{sequence} is empty the \meta{token list variable}
+is set to the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqPopLeft \lTmpaSeq \lTmpaTl
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPopLeftT,\SeqPopLeftF,\SeqPopLeftTF}
+\begin{syntax}
+\cs{SeqPopLeftT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqPopLeftF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqPopLeftTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, pops the left-most item from the \meta{sequence}
+in the \meta{token list variable}, \emph{i.e.} removes the item from the
+\meta{sequence}, then leaves the \meta{true code} in the input stream.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqPopLeftTF \cEmptySeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPopRight}
+\begin{syntax}
+\cs{SeqPopRight} \meta{sequence} \meta{token list variable}
+\end{syntax}
+Pops the right-most item from a \meta{sequence} into the
+\meta{token list variable}, \emph{i.e.} removes the item from the
+sequence and stores it in the \meta{token list variable}.
+The assignment of the \meta{token list variable} is local.
+If \meta{sequence} is empty the \meta{token list variable}
+is set to the special marker \cs{qNoValue}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {two,three,four}
+\SeqPopRight \lTmpaSeq \lTmpaTl
+\SeqVarJoin \lTmpaSeq {,}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqPopRightT,\SeqPopRightF,\SeqPopRightTF}
+\begin{syntax}
+\cs{SeqPopRightT} \meta{sequence} \meta{token list variable} \Arg{true code}
+\cs{SeqPopRightF} \meta{sequence} \meta{token list variable} \Arg{false code}
+\cs{SeqPopRightTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{sequence} is empty, leaves the \meta{false code} in the
+input stream. The value of the \meta{token list variable} is
+not defined in this case and should not be relied upon. If the
+\meta{sequence} is non-empty, pops the right-most item from the \meta{sequence}
+in the \meta{token list variable}, \emph{i.e.} removes the item from the
+\meta{sequence}, then leaves the \meta{true code} in the input stream.
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\SeqPopRightTF \cEmptySeq \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\section{Mapping over Sequences}
+
+%All mappings are done at the current group level, \emph{i.e.} any
+%local assignments made by the \meta{function} or \meta{code} discussed
+%below remain in effect after the loop.
+
+%\begin{function}{\SeqVarMapFunction}
+%\begin{syntax}
+%\cs{SeqVarMapFunction} \meta{sequence} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every \meta{item} stored in the
+%\meta{sequence}. The \meta{function} will receive one argument for
+%each iteration. The \meta{items} are returned from left to right.
+%To pass further arguments to the \meta{function}, see \cs{SeqVarMapTokens}.
+%The function \cs{SeqVarMapInline} is faster than
+%\cs{SeqVarMapFunction} for sequences with more than about $10$ items.
+%\end{function}
+
+\begin{function}{\SeqVarMapInline}
+\begin{syntax}
+\cs{SeqVarMapInline} \meta{sequence} \Arg{inline function}
+\end{syntax}
+Applies \meta{inline function} to every \meta{item} stored
+within the \meta{sequence}. The \meta{inline function} should
+consist of code which will receive the \meta{item} as \verb|#1|.
+The \meta{items} are returned from left to right. For example,
+\begin{codehigh}
+\IgnoreSpacesOn
+\SeqSetFromClist \lTmpkSeq {one,two,three}
+\TlClear \lTmpaTl
+\SeqVarMapInline \lTmpkSeq {
+ \TlPutRight \lTmpaTl {(#1)}
+}
+\Result {\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces (one)(two)(three).
+\end{function}
+
+%\begin{function}{\SeqVarMapTokens}
+%\begin{syntax}
+%\cs{SeqVarMapTokens} \meta{sequence} \Arg{code}
+%\end{syntax}
+%Analogue of \cs{SeqVarMapFunction} which maps several tokens
+%instead of a single function. The \meta{code} receives each item in
+%the \meta{sequence} as a trailing brace group. For instance,
+%\begin{verbatim}
+%\SeqVarMapTokens \lMySeq { \PrgReplicate { 2 } }
+%\end{verbatim}
+%expands to twice each item in the \meta{sequence}: for each item in
+%\verb|\l_my_seq| the function \cs{PrgReplicate} receives \verb|2| and
+%\meta{item} as its two arguments. The function
+%\cs{SeqVarMapInline} is typically faster but it is not expandable.
+%\end{function}
+
+\begin{function}{\SeqVarMapVariable}
+\begin{syntax}
+\cs{SeqVarMapVariable} \meta{sequence} \meta{variable} \Arg{code}
+\end{syntax}
+Stores each \meta{item} of the \meta{sequence} in turn in the (token
+list) \meta{variable} and applies the \meta{code}. The \meta{code}
+will usually make use of the \meta{variable}, but this is not
+enforced. The assignments to the \meta{variable} are local. Its
+value after the loop is the last \meta{item} in the \meta{sequence},
+or its original value if the \meta{sequence} is empty. The
+\meta{items} are returned from left to right.
+\begin{demohigh}
+\IgnoreSpacesOn
+\IntZero \lTmpaInt
+\SeqSetFromClist \lTmpaSeq {1,3,7}
+\SeqVarMapVariable \lTmpaSeq \lTmpiTl {
+ \IntAdd \lTmpaInt {\lTmpiTl*\lTmpiTl}
+}
+\Result {\IntUse\lTmpaInt}
+\IgnoreSpacesOff
+\end{demohigh}
+\end{function}
+
+%\begin{function}{\SeqVarMapIndexedFunction}
+%\begin{syntax}
+%\cs{SeqVarMapIndexedFunction} \meta{seq var} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every entry in the \meta{sequence
+%variable}. The \meta{function} should have signature |:nn|. It
+%receives two arguments for each iteration: the \meta{index} (namely
+%\verb|1| for the first entry, then \verb|2| and so on) and the \meta{item}.
+%\end{function}
+
+%\begin{function}{\SeqVarMapIndexedInline}
+%\begin{syntax}
+%\cs{SeqVarMapIndexedInline} \meta{seq var} \Arg{inline function}
+%\end{syntax}
+%Applies \meta{inline function} to every entry in the \meta{sequence
+%variable}. The \meta{inline function} should consist of code which
+%receives the \meta{index} (namely \verb|1| for the first entry, then \verb|2|
+%and so on) as \verb|#1| and the \meta{item} as \verb|#2|.
+%\end{function}
+
+%\begin{function}{\SeqMapBreak}
+%\begin{syntax}
+%\cs{SeqMapBreak}
+%\end{syntax}
+%Used to terminate a seq map function before all
+%entries in the \meta{sequence} have been processed. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\seq_map_inline:Nn \l_my_seq
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \seq_map_break: }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a seq map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before further items are taken
+%from the input stream. This depends on the design of the mapping
+%function.
+%\end{texnote}
+%\end{function}
+
+%\begin{function}{\SeqMapBreakDo}
+%\begin{syntax}
+%\cs{SeqMapBreakDo} \Arg{code}
+%\end{syntax}
+%Used to terminate a seq map function before all
+%entries in the \meta{sequence} have been processed, inserting
+%the \meta{code} after the mapping has ended. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\seq_map_inline:Nn \l_my_seq
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \seq_map_break:n { <code> } }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a seq map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before the \meta{code} is
+%inserted into the input stream.
+%This depends on the design of the mapping function.
+%\end{texnote}
+%\end{function}
+
+%\begin{function}
+%{\seq_set_map:NNn, \seq_gset_map:NNn}
+%\begin{syntax}
+%\cs{seq_set_map:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function}
+%\end{syntax}
+%Applies \meta{inline function} to every \meta{item} stored
+%within the \meta{sequence_2}. The \meta{inline function} should
+%consist of code which will receive the \meta{item} as \verb|#1|.
+%The sequence resulting applying \meta{inline function} to each
+%\meta{item} is assigned to \meta{sequence_1}.
+%\begin{texnote}
+%Contrarily to other mapping functions, \cs{seq_map_break:} cannot
+%be used in this function, and would lead to low-level \TeX{} errors.
+%\end{texnote}
+%\end{function}
+
+%\begin{function}[added = 2020-07-16]
+%{\seq_set_map_x:NNn, \seq_gset_map_x:NNn}
+%\begin{syntax}
+%\cs{seq_set_map_x:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function}
+%\end{syntax}
+%Applies \meta{inline function} to every \meta{item} stored
+%within the \meta{sequence_2}. The \meta{inline function} should
+%consist of code which will receive the \meta{item} as \verb|#1|.
+%The sequence resulting from \texttt{x}-expanding
+%\meta{inline function} applied to each \meta{item}
+%is assigned to \meta{sequence_1}. As such, the code
+%in \meta{inline function} should be expandable.
+%\begin{texnote}
+%Contrarily to other mapping functions, \cs{seq_map_break:} cannot
+%be used in this function, and would lead to low-level \TeX{} errors.
+%\end{texnote}
+%\end{function}
+
+\section{Sequence Conditionals}
+
+\begin{function}{\SeqIfExist,\SeqIfExistTF}
+\begin{syntax}
+\cs{SeqIfExist} \meta{sequence}
+\cs{SeqIfExistTF} \meta{sequence} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{sequence} is currently defined. This does not
+check that the \meta{sequence} really is a sequence variable.
+\begin{demohigh}
+\SeqIfExistTF \lTmpaSeq {\Result{Yes}} {\Result{No}}
+\SeqIfExistTF \lFooUndefinedSeq {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqVarIfEmpty,\SeqVarIfEmptyTF}
+\begin{syntax}
+\cs{SeqVarIfEmpty} \meta{sequence}
+\cs{SeqVarIfEmptyTF} \meta{sequence} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{sequence} is empty (containing no items).
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two}
+\SeqVarIfEmptyTF \lTmpaSeq {\Result{Empty}} {\Result{NonEmpty}}
+\SeqClear \lTmpaSeq
+\SeqVarIfEmptyTF \lTmpaSeq {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\SeqVarIfIn,\SeqVarIfInTF}
+\begin{syntax}
+\cs{SeqVarIfIn} \meta{sequence} \Arg{item}
+\cs{SeqVarIfInTF} \meta{sequence} \Arg{item} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{item} is present in the \meta{sequence}.
+\begin{demohigh}
+\SeqSetFromClist \lTmpaSeq {one,two}
+\SeqVarIfInTF \lTmpaSeq {one} {\Result{Yes}} {\Result{Not}}
+\SeqVarIfInTF \lTmpaSeq {three} {\Result{Yes}} {\Result{Not}}
+\end{demohigh}
+\end{function}
+
+\chapter{Property Lists (\texttt{Prop})}
+
+\LaTeX3 implements a \enquote{property list} data type, which contain
+an unordered list of entries each of which consists of a \meta{key} and
+an associated \meta{value}. The \meta{key} and \meta{value} may both
+be any \meta{balanced text}, the \meta{key} is processed using
+\cs{TlToStr}, meaning that category codes are ignored. It is possible to
+map functions to property lists such that the function is applied to every
+key--value pair within the list.
+
+Each entry in a property list must have a unique \meta{key}: if an entry is
+added to a property list which already contains the \meta{key} then the new
+entry overwrites the existing one. The \meta{keys} are compared on a
+string basis, using the same method as \cs{StrIfEq}.
+
+%Property lists are intended for storing key-based information for use within
+%code. This is in contrast to key--value lists, which are a form of
+%\emph{input} parsed by the \pkg{l3keys} module.
+
+\section{Constant and Scratch Sequences}
+
+\begin{variable}{\cEmptyProp}
+Constant that is always empty.
+\end{variable}
+
+\begin{variable}{\lTmpaProp,\lTmpbProp,\lTmpcProp,\lTmpiProp,\lTmpjProp,\lTmpkProp}
+Scratch property lists for local assignment. These are never used by
+the \verb!functional! package, and so are safe for use with any
+function. However, they may be overwritten by other
+code and so should only be used for short-term storage.
+\end{variable}
+
+\begin{variable}{\gTmpaProp,\gTmpbProp,\gTmpcProp,\gTmpiProp,\gTmpjProp,\gTmpkProp}
+Scratch property lists for global assignment. These are never used by
+the \verb!functional! package, and so are safe for use with any
+function. However, they may be overwritten by other
+code and so should only be used for short-term storage.
+\end{variable}
+
+\section{Creating and Using Property Lists}
+
+\begin{function}{\PropNew}
+\begin{syntax}
+\cs{PropNew} \meta{property list}
+\end{syntax}
+Creates a new \meta{property list} or raises an error if the name is
+already taken. The declaration is global. The \meta{property list}
+initially contains no entries.
+\begin{codehigh}
+\PropNew \lFooSomeProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropConstFromKeyval}
+\begin{syntax}
+\cs{PropConstFromKeyval} \meta{prop var}
+\{
+~ \meta{key1} \verb|=| \meta{value1} \verb|,|
+~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$
+\}
+\end{syntax}
+Creates a new constant \meta{prop var} or raises an error if the
+name is already taken. The \meta{prop var} is set globally to
+contain key--value pairs given in the second argument, processed in
+the way described for \cs{PropSetFromKeyval}. If duplicate
+keys appear only the last of the values is kept.
+This function correctly detects the \verb|=| and \verb|,| signs provided they
+have the standard category code $12$ or they are active.
+\begin{codehigh}
+\PropConstFromKeyval \cFooSomeProp {key1=one,key2=two,key3=three}
+\end{codehigh}
+%Notice that in contrast to most keyval lists (\emph{e.g.} those in
+%\pkg{l3keys}), each key here \emph{must} be followed with an \texttt{=} sign.
+\end{function}
+
+\begin{function}{\PropToKeyval}
+\begin{syntax}
+\cs{PropToKeyval} \meta{property list}
+\end{syntax}
+Returns the \meta{property list} in a key--value notation. Keep in mind
+that a \meta{property list} is \emph{unordered}, while key--value interfaces
+don't necessarily are, so this can't be used for arbitrary interfaces.
+%\begin{texnote}
+%The result is returned within the \tn{unexpanded} primitive
+%(\cs{exp_not:n}), which means that the key--value list does not expand
+%further when appearing in an \texttt{x}-type or \texttt{e}-type argument expansion.
+%It also needs exactly two steps of expansion.
+%\end{texnote}
+\begin{codehigh}
+\PropToKeyval \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\section{Viewing Property Lists}
+
+\begin{function}{\PropVarLog}
+\begin{syntax}
+\cs{PropVarLog} \meta{property list}
+\end{syntax}
+Writes the entries in the \meta{property list} in the log file.
+\begin{codehigh}
+\PropVarLog \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropVarShow}
+\begin{syntax}
+\cs{PropVarShow} \meta{property list}
+\end{syntax}
+Displays the entries in the \meta{property list} in the terminal.
+\begin{codehigh}
+\PropVarShow \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\section{Setting Property Lists}
+
+\begin{function}{\PropSetFromKeyval}
+\begin{syntax}
+\cs{PropSetFromKeyval} \meta{prop var}
+\{
+~ \meta{key1} \verb|=| \meta{value1} \verb|,|
+~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$
+\}
+\end{syntax}
+Sets \meta{prop var} to contain key--value pairs given in the second
+argument. If duplicate keys appear only the last of the values is kept.
+
+Spaces are trimmed around every \meta{key} and every \meta{value},
+and if the result of trimming spaces consists of a single brace
+group then a set of outer braces is removed. This enables both the
+\meta{key} and the \meta{value} to contain spaces, commas or equal
+signs. The \meta{key} is then processed by \cs{TlToStr}.
+This function correctly detects the \verb|=| and \verb|,| signs provided they
+have the standard category code $12$ or they are active.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\end{codehigh}
+%Notice that in contrast to most keyval lists (\emph{e.g.} those in
+%\pkg{l3keys}), each key here \emph{must} be followed with an \texttt{=} sign.
+\end{function}
+
+\begin{function}{\PropSetEq}
+\begin{syntax}
+\cs{PropSetEq} \meta{property list_1} \meta{property list_2}
+\end{syntax}
+Sets the content of \meta{property list_1} equal to that of
+\meta{property list_2}.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropSetEq \lTmpbProp \lTmpaProp
+\PropVarLog \lTmpbProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropClear}
+\begin{syntax}
+\cs{PropClear} \meta{property list}
+\end{syntax}
+Clears all entries from the \meta{property list}.
+\begin{codehigh}
+\PropClear \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropClearNew}
+\begin{syntax}
+\cs{PropClearNew} \meta{property list}
+\end{syntax}
+Ensures that the \meta{property list} exists globally by applying \cs{PropNew}
+if necessary, then applies \cs{PropClear} to leave the list empty.
+\begin{codehigh}
+\PropClearNew \lFooSomeProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropConcat}
+\begin{syntax}
+\cs{PropConcat} \meta{prop var_1} \meta{prop var_2} \meta{prop var_3}
+\end{syntax}
+Combines the key--value pairs of \meta{prop var_2} and
+\meta{prop var_3}, and saves the result in \meta{prop var_1}. If a
+key appears in both \meta{prop var_2} and \meta{prop var_3} then the
+last value, namely the value in \meta{prop var_3} is kept.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpbProp {key1=one,key2=two}
+\PropSetFromKeyval \lTmpcProp {key3=three,key4=four}
+\PropConcat \lTmpaProp \lTmpbProp \lTmpcProp
+\PropVarLog \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropPut}
+\begin{syntax}
+\cs{PropPut} \meta{property list} \Arg{key} \Arg{value}
+\end{syntax}
+Adds an entry to the \meta{property list} which may be accessed
+using the \meta{key} and which has \meta{value}. If the \meta{key}
+is already present in the \meta{property list}, the existing entry
+is overwritten by the new \meta{value}. Both the \meta{key} and
+\meta{value} may contain any \meta{balanced text}. The \meta{key} is
+stored after processing with \cs{TlToStr}, meaning that category
+codes are ignored.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropPut \lTmpaProp {key1} {newone}
+\PropVarLog \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropPutIfNew}
+\begin{syntax}
+\cs{PropPutIfNew} \meta{property list} \Arg{key} \Arg{value}
+\end{syntax}
+If the \meta{key} is present in the \meta{property list} then no
+action is taken. Otherwise, a new entry is added as described for
+\cs{PropPut}.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropPutIfNew \lTmpaProp {key1} {newone}
+\PropVarLog \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\begin{function}{\PropPutFromKeyval}
+\begin{syntax}
+\cs{PropPutFromKeyval} \meta{prop var}
+\{
+~ \meta{key1} \verb|=| \meta{value1} \verb|,|
+~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$
+\}
+\end{syntax}
+Updates the \meta{prop var} by adding entries for each key--value
+pair given in the second argument. The addition is done through
+\cs{PropPut}, hence if the \meta{prop var} already contains
+some of the keys, the corresponding values are discarded and
+replaced by those given in the key--value list. If duplicate keys
+appear in the key--value list then only the last of the values is kept.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropPutFromKeyval \lTmpaProp {key1=newone,key3=three}
+\PropVarLog \lTmpaProp
+\end{codehigh}
+%The function is equivalent to storing the key--value pairs in a
+%temporary property variable using \cs{PropSetFromKeyval}, then
+%combining \meta{prop var} with the temporary variable using
+%\cs{PropConcat}. In particular, the \meta{keys} and
+%\meta{values} are space-trimmed and unbraced as described in
+%\cs{PropSetFromKeyval}. This function correctly detects
+%the \verb|=| and \verb|,| signs provided they
+%have the standard category code $12$ or they are active.
+\end{function}
+
+\begin{function}{\PropVarRemove}
+\begin{syntax}
+\cs{PropVarRemove} \meta{property list} \Arg{key}
+\end{syntax}
+Removes the entry listed under \meta{key} from the
+\meta{property list}. If the \meta{key} is
+not found in the \meta{property list} no change occurs,
+\emph{i.e} there is no need to test for the existence of a key before
+deleting it.
+\begin{codehigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropVarRemove \lTmpaProp {key2}
+\PropVarLog \lTmpaProp
+\end{codehigh}
+\end{function}
+
+\section{Recovering Values from Property Lists}
+
+\begin{function}{\PropVarCount}
+\begin{syntax}
+\cs{PropVarCount} \meta{property list}
+\end{syntax}
+Returns the number of key--value pairs in the \meta{property list}
+as an \meta{integer denotation}.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropVarCount \lTmpaProp
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropVarItem}
+\begin{syntax}
+\cs{PropVarItem} \meta{property list} \Arg{key}
+\end{syntax}
+Returns the \meta{value} corresponding to the \meta{key} in
+the \meta{property list}. If the \meta{key} is missing,
+nothing is returned.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\TlSet \lTmpaTl {\PropVarItem \lTmpaProp {key2}}
+\TlUse \lTmpaTl
+\end{demohigh}
+%\begin{texnote}
+%This function is slower than the non-expandable analogue
+%\cs{prop_get:NnN}.
+%The result is returned within the \tn{unexpanded}
+%primitive (\cs{exp_not:n}), which means that the \meta{value}
+%does not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\PropGet}
+\begin{syntax}
+\cs{PropGet} \meta{property list} \Arg{key} \meta{token list variable}
+\end{syntax}
+Recovers the \meta{value} stored with \meta{key} from the \meta{property list},
+and places this in the \meta{token list variable}.
+If the \meta{key} is not found in the
+\meta{property list} then the \meta{token list variable} is set
+to the special marker \cs{qNoValue}.
+The assignment of the \meta{token list variable} is local.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropGet \lTmpaProp {key2} \lTmpaTl
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropGetT,\PropGetF,\PropGetTF}
+\begin{syntax}
+\cs{PropGetT} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code}
+\cs{PropGetF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{false code}
+\cs{PropGetTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{key} is not present in the \meta{property list}, leaves
+the \meta{false code} in the input stream. The value of the
+\meta{token list variable} is not defined in this case and should
+not be relied upon. If the \meta{key} is present in the
+\meta{property list}, stores the corresponding \meta{value} in the
+\meta{token list variable} without removing it from the
+\meta{property list}, then leaves the \meta{true code} in the input
+stream. The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropGetTF \lTmpaProp {key2} \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropPop}
+\begin{syntax}
+\cs{PropPop} \meta{property list} \Arg{key} \meta{token list variable}
+\end{syntax}
+Recovers the \meta{value} stored with \meta{key} from the \meta{property list},
+and places this in the \meta{token list variable}.
+If the \meta{key} is not found in the
+\meta{property list} then the \meta{token list variable} is set
+to the special marker \cs{qNoValue}.
+The \meta{key} and \meta{value} are then deleted from the property list.
+The assignment of the \meta{token list variable} is local.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropPop \lTmpaProp {key2} \lTmpaTl
+Pop: \TlUse \lTmpaTl.
+Count: \PropVarCount \lTmpaProp.
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropPopT,\PropPopF,\PropPopTF}
+\begin{syntax}
+\cs{PropPopT} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code}
+\cs{PropPopF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{false code}
+\cs{PropPopTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code}
+\end{syntax}
+If the \meta{key} is not present in the \meta{property list}, leaves
+the \meta{false code} in the input stream. The value of the
+\meta{token list variable} is not defined in this case and should
+not be relied upon. If the \meta{key} is present in
+the \meta{property list}, pops the corresponding \meta{value}
+in the \meta{token list variable}, \emph{i.e.} removes the item from
+The \meta{token list variable} is assigned locally.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three}
+\PropPopTF \lTmpaProp {key2} \lTmpaTl {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\section{Mapping over property lists}
+
+%All mappings are done at the current group level, \emph{i.e.} any
+%local assignments made by the \meta{function} or \meta{code} discussed
+%below remain in effect after the loop.
+
+%\begin{function}{\PropVarMapFunction}
+%\begin{syntax}
+%\cs{PropVarMapFunction} \meta{property list} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every \meta{entry} stored in the
+%\meta{property list}. The \meta{function} receives two arguments for
+%each iteration: the \meta{key} and associated \meta{value}.
+%The order in which \meta{entries} are returned is not defined and
+%should not be relied upon.
+%To pass further arguments to the \meta{function}, see
+%\cs{prop_map_tokens:Nn}.
+%\end{function}
+
+\begin{function}{\PropVarMapInline}
+\begin{syntax}
+\cs{PropVarMapInline} \meta{property list} \Arg{inline function}
+\end{syntax}
+Applies \meta{inline function} to every \meta{entry} stored
+within the \meta{property list}. The \meta{inline function} should
+consist of code which receives the \meta{key} as \verb|#1| and the
+\meta{value} as \verb|#2|.
+The order in which \meta{entries} are returned is not defined and
+should not be relied upon.
+For example,
+\begin{codehigh}
+\IgnoreSpacesOn
+\PropSetFromKeyval \lTmpkProp {key1=one,key2=two,key3=three}
+\TlClear \lTmpaTl
+\PropVarMapInline \lTmpkProp {
+ \TlPutRight \lTmpaTl {(#1=#2)}
+}
+\Result {\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces (key1=one)(key2=two)(key3=three).
+\end{function}
+
+%\begin{function}{\PropVarMapTokens}
+%\begin{syntax}
+%\cs{PropVarMapTokens} \meta{property list} \Arg{code}
+%\end{syntax}
+%Analogue of \cs{PropVarMapFunction} which maps several tokens
+%instead of a single function. The \meta{code} receives each
+%key--value pair in the \meta{property list} as two trailing brace
+%groups. For instance,
+%\begin{verbatim}
+%\PropVarMapTokens \lMyProp { \StrIfEqT { mykey } }
+%\end{verbatim}
+%expands to the value corresponding to \texttt{mykey}: for each
+%pair in \verb|\lMyProp| the function \cs{StrIfEqT} receives
+%\texttt{mykey}, the \meta{key} and the \meta{value} as its three
+%arguments. For that specific task, \cs{PropVarItem} is faster.
+%\end{function}
+
+%\begin{function}{\PropMapBreak}
+%\begin{syntax}
+%\cs{PropMapBreak}
+%\end{syntax}
+%Used to terminate a prop map function before all
+%entries in the \meta{property list} have been processed. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\prop_map_inline:Nn \l_my_prop
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \prop_map_break: }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a prop map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before further items are taken
+%from the input stream. This depends on the design of the mapping
+%function.
+%\end{texnote}
+%\end{function}
+
+%\begin{function}{\PropMapBreakDo}
+%\begin{syntax}
+%\cs{PropMapBreakDo} \Arg{code}
+%\end{syntax}
+%Used to terminate a prop map function before all
+%entries in the \meta{property list} have been processed, inserting
+%the \meta{code} after the mapping has ended. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\prop_map_inline:Nn \l_my_prop
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \prop_map_break:n { <code> } }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a prop map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before the \meta{code} is
+%inserted into the input stream.
+%This depends on the design of the mapping function.
+%\end{texnote}
+%\end{function}
+
+\section{Property List Conditionals}
+
+\begin{function}{\PropIfExist}
+\begin{syntax}
+\cs{PropIfExist} \meta{property list}
+\cs{PropIfExistTF} \meta{property list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{property list} is currently defined. This does not
+check that the \meta{property list} really is a property list variable.
+\begin{demohigh}
+\PropIfExistTF \lTmpaProp {\Result{Yes}} {\Result{No}}
+\PropIfExistTF \lFooUndefinedProp {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropVarIfEmpty}
+\begin{syntax}
+\cs{PropVarIfEmpty} \meta{property list}
+\cs{PropVarIfEmptyTF} \meta{property list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{property list} is empty (containing no entries).
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropVarIfEmptyTF \lTmpaProp {\Result{Empty}} {\Result{NonEmpty}}
+\PropClear \lTmpaProp
+\PropVarIfEmptyTF \lTmpaProp {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\PropVarIfIn}
+\begin{syntax}
+\cs{PropVarIfIn} \meta{property list} \Arg{key} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{key} is present in the \meta{property list},
+making the comparison using the method described by \cs{StrIfEqTF}.
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropVarIfInTF \lTmpaProp {key1} {\Result{Yes}} {\Result{Not}}
+\PropVarIfInTF \lTmpaProp {key3} {\Result{Yes}} {\Result{Not}}
+\end{demohigh}
+%\begin{texnote}
+%This function iterates through every key--value pair in the
+%\meta{property list} and is therefore slower than using \cs{PropGetTF}.
+%\end{texnote}
+\end{function}
+
+\chapter{Quarks (\texttt{Quark})}
+
+%One special type of constants in \LaTeX3 is \enquote{quarks}.
+%By convention all constants of type quark start out with \verb|\q|.
+
+Quarks are control sequences (and in fact, token lists) that expand
+to themselves and should therefore \emph{never} be executed directly
+in the code. This would result in an endless loop!
+
+Quarks can be used as error return values for functions that receive erroneous input.
+For example, in the function \cs{PropGet} to retrieve a value stored
+in some key of a property list, if the key does not exist then the return value
+is the quark \cs{qNoValue}.
+As mentioned above, such quarks are extremely fragile and it is imperative
+when using such functions that code is carefully written to check for
+pathological cases to avoid leakage of a quark into an uncontrolled
+environment.
+
+\section{Constant Quarks}
+
+\begin{variable}{\qNoValue}
+A canonical value for a missing value, when one is requested from
+a data structure. This is therefore used as a \enquote{return} value
+by functions such as \cs{PropGet} if there is no data to return.
+\end{variable}
+
+\section{Quark Conditionals}
+
+\begin{function}{\QuarkVarIfNoValue,\QuarkVarIfNoValueTF}
+\begin{syntax}
+\cs{QuarkVarIfNoValue} \meta{token}
+\cs{QuarkVarIfNoValueTF} \meta{token} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{token} is equal to \cs{qNoValue}.
+\begin{demohigh}
+\ClistGet \cEmptyClist \lTmpaTl
+\QuarkVarIfNoValueTF \lTmpaTl {\Result{NoValue}} {\Result{SomeValue}}
+\end{demohigh}
+\begin{demohigh}
+\SeqPop \cEmptySeq \lTmpaTl
+\QuarkVarIfNoValueTF \lTmpaTl {\Result{NoValue}} {\Result{SomeValue}}
+\end{demohigh}
+\begin{demohigh}
+\PropSetFromKeyval \lTmpaProp {key1=one,key2=two}
+\PropGet \lTmpaProp {key3} \lTmpaTl
+\QuarkVarIfNoValueTF \lTmpaTl {\Result{NoValue}} {\Result{SomeValue}}
+\end{demohigh}
+\end{function}
+
+%\begin{function}{\QuarkIfNoValue,\QuarkIfNoValueTF}
+%\begin{syntax}
+%\cs{QuarkIfNoValue} \Arg{token list}
+%\cs{QuarkIfNoValueTF} \Arg{token list} \Arg{true code} \Arg{false code}
+%\end{syntax}
+%Tests if the \meta{token list} contains only \cs{qNoValue}
+%(distinct from \meta{token list} being empty or containing
+%\cs{qNoValue} plus one or more other tokens).
+%\end{function}
+
\chapter{The Source Code}
%\CodeHigh{lite}
Modified: trunk/Master/texmf-dist/tex/latex/functional/functional.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/functional/functional.sty 2022-04-05 21:57:36 UTC (rev 62925)
+++ trunk/Master/texmf-dist/tex/latex/functional/functional.sty 2022-04-05 21:57:49 UTC (rev 62926)
@@ -14,13 +14,16 @@
\NeedsTeXFormat{LaTeX2e}[2018-04-01]
\RequirePackage{expl3}
-\ProvidesExplPackage{functional}{2022-03-19}{2022B}
+\ProvidesExplPackage{functional}{2022-04-01}{2022C}
{^^JLaTeX2 functional interfaces for LaTeX3 programming layer}
\cs_generate_variant:Nn \iow_log:n { V }
+\cs_generate_variant:Nn \str_set:Nn { Ne }
\cs_generate_variant:Nn \tl_log:n { e }
\cs_generate_variant:Nn \tl_set:Nn { Ne }
+\prg_generate_conditional_variant:Nnn \str_if_eq:nn { Ve } { TF }
+
\tl_new:N \gResultTl
\int_new:N \l__fun_arg_count_int
\tl_new:N \l__fun_parameters_defined_tl
@@ -67,7 +70,7 @@
\__fun_group_begin:
\tl_gclear:N \gResultTl
#3
- \__fun_tracing_log:e { [O] ~ \gResultTl }
+ \__fun_tracing_log:e { [O] ~ \exp_not:V \gResultTl }
\__fun_group_end:
}
\use:c { __fun_new_with_arg_ \int_to_roman:n { \l__fun_arg_count_int } :NnV }
@@ -440,21 +443,45 @@
{ \tl_use:N \gResultTl }
}
-\tl_new:N \l__fun_variable_type_tl
+\str_new:N \l__fun_variable_name_str
+\str_new:N \l__fun_variable_name_a_str
+\str_new:N \l__fun_variable_name_b_str
\prg_new_protected_conditional:Npnn \__fun_if_global_variable:N #1 { TF }
{
- \tl_set:Ne \l__fun_variable_type_tl
- { \exp_args:Ne \tl_head:n { \cs_to_str:N #1 } }
- \str_if_eq:VnTF \l__fun_variable_type_tl { g }
- { \prg_return_true: }
+ \str_set:Ne \l__fun_variable_name_str { \cs_to_str:N #1 }
+ \str_set:Ne \l__fun_variable_name_b_str
+ { \str_item:Nn \l__fun_variable_name_str { 2 } }
+ \str_if_eq:VeTF
+ \l__fun_variable_name_b_str
+ { \str_uppercase:f { \l__fun_variable_name_b_str } }
{
- \str_if_eq:VnTF \l__fun_variable_type_tl { c }
- { \prg_return_true: }
- { \prg_return_false: }
+ \str_set:Ne \l__fun_variable_name_a_str
+ { \str_head:N \l__fun_variable_name_str }
+ \str_case:VnF \l__fun_variable_name_a_str
+ {
+ { l } { \prg_return_false: }
+ { g } { \prg_return_true: }
+ }
+ { \__fun_if_set_local: }
}
+ { \__fun_if_set_local: }
}
+\bool_new:N \g__fun_variable_local_bool
+
+\cs_new:Npn \__fun_if_set_local:
+ {
+ \bool_if:NTF \g__fun_variable_local_bool
+ {
+ \bool_gset_false:N \g__fun_variable_local_bool
+ \prg_return_false:
+ }
+ { \prg_return_true: }
+ }
+
+\PrgNewFunction \Local { } { \bool_gset_true:N \g__fun_variable_local_bool }
+
%% We must not put an assignment inside a group
\cs_new_protected:Npn \__fun_do_assignment:Nnn #1 #2 #3
{
@@ -499,7 +526,8 @@
\cs_generate_variant:Nn \__fun_tracing_log_on:n { e, V }
\cs_new_protected:Npn \__fun_tracing_log_off:n #1 { }
-\cs_generate_variant:Nn \__fun_tracing_log_off:n { e, V }
+\cs_new_protected:Npn \__fun_tracing_log_off:e #1 { }
+\cs_new_protected:Npn \__fun_tracing_log_off:V #1 { }
\cs_new_protected:Npn \__fun_tracing_true:
{
@@ -553,22 +581,23 @@
{
\exp_args:Nc \__fun_put_result:n { #1 }
}
-\cs_set_eq:NN \UseName \Name
\PrgNewFunction \Value { M }
{
\__fun_put_result:V #1
}
-\cs_set_eq:NN \UseValue \Value
\PrgNewFunction \Expand { m }
{
\__fun_put_result:e { #1 }
}
-\cs_set_eq:NN \UseExpand \Expand
-\cs_set_eq:NN \ExpNot \exp_not:n
-\cs_set_eq:NN \ExpValue \exp_not:V
+\cs_set_eq:NN \UnExpand \exp_not:n
+\cs_set_eq:NN \NoExpand \exp_not:N
+\cs_set_eq:NN \OnlyName \exp_not:c
+\cs_set_eq:NN \OnlyValue \exp_not:V
+\cs_set_eq:NN \OnlyExpandF \exp_not:f
+\cs_set_eq:NN \OnlyExpandO \exp_not:o
\PrgNewFunction \UseOne { n } { \Result { #1 } }
@@ -729,25 +758,25 @@
{ \tl_gput_right:Nn #1 {#2} } { \tl_put_right:Nn #1 {#2} }
}
-\PrgNewFunction \TlReplaceOnce { M m m }
+\PrgNewFunction \TlVarReplaceOnce { M m m }
{
\__fun_do_assignment:Nnn #1
{ \tl_greplace_once:Nnn #1 {#2} {#3} } { \tl_replace_once:Nnn #1 {#2} {#3} }
}
-\PrgNewFunction \TlReplaceAll { M m m }
+\PrgNewFunction \TlVarReplaceAll { M m m }
{
\__fun_do_assignment:Nnn #1
{ \tl_greplace_all:Nnn #1 {#2} {#3} } { \tl_replace_all:Nnn #1 {#2} {#3} }
}
-\PrgNewFunction \TlRemoveOnce { M m }
+\PrgNewFunction \TlVarRemoveOnce { M m }
{
\__fun_do_assignment:Nnn #1
{ \tl_gremove_once:Nn #1 {#2} } { \tl_remove_once:Nn #1 {#2} }
}
-\PrgNewFunction \TlRemoveAll { M m }
+\PrgNewFunction \TlVarRemoveAll { M m }
{
\__fun_do_assignment:Nnn #1
{ \tl_gremove_all:Nn #1 {#2} } { \tl_remove_all:Nn #1 {#2} }
@@ -933,25 +962,25 @@
{ \str_gput_right:Nn #1 {#2} } { \str_put_right:Nn #1 {#2} }
}
-\PrgNewFunction \StrReplaceOnce { M m m }
+\PrgNewFunction \StrVarReplaceOnce { M m m }
{
\__fun_do_assignment:Nnn #1
{ \str_greplace_once:Nnn #1 {#2} {#3} } { \str_replace_once:Nnn #1 {#2} {#3} }
}
-\PrgNewFunction \StrReplaceAll { M m m }
+\PrgNewFunction \StrVarReplaceAll { M m m }
{
\__fun_do_assignment:Nnn #1
{ \str_greplace_all:Nnn #1 {#2} {#3} } { \str_replace_all:Nnn #1 {#2} {#3} }
}
-\PrgNewFunction \StrRemoveOnce { M m }
+\PrgNewFunction \StrVarRemoveOnce { M m }
{
\__fun_do_assignment:Nnn #1
{ \str_gremove_once:Nn #1 {#2} } { \str_remove_once:Nn #1 {#2} }
}
-\PrgNewFunction \StrRemoveAll { M m }
+\PrgNewFunction \StrVarRemoveAll { M m }
{
\__fun_do_assignment:Nnn #1
{ \str_gremove_all:Nn #1 {#2} } { \str_remove_all:Nn #1 {#2} }
@@ -1568,40 +1597,38 @@
{ \clist_gput_right:Nn #1 {#2} } { \clist_put_right:Nn #1 {#2} }
}
-\PrgNewFunction \ClistRemoveDuplicates { M }
+\PrgNewFunction \ClistVarRemoveDuplicates { M }
{
\__fun_do_assignment:Nnn #1
{ \clist_gremove_duplicates:N #1 } { \clist_remove_duplicates:N #1 }
}
-\PrgNewFunction \ClistRemoveAll { M m }
+\PrgNewFunction \ClistVarRemoveAll { M m }
{
\__fun_do_assignment:Nnn #1
{ \clist_gremove_all:Nn #1 {#2} } { \clist_remove_all:Nn #1 {#2} }
}
-\PrgNewFunction \ClistReverse { M }
+\PrgNewFunction \ClistVarReverse { M }
{
\__fun_do_assignment:Nnn #1 { \clist_greverse:N #1 } { \clist_reverse:N #1 }
}
-\PrgNewFunction \ClistSort { M m }
+\PrgNewFunction \ClistVarSort { M m }
{
\__fun_do_assignment:Nnn #1
{ \clist_gsort:Nn #1 {#2} } { \clist_sort:Nn #1 {#2} }
}
-\PrgNewFunction \ClistCount { m }
- {
- \Result { \Expand { \clist_count:n { #1 } } }
- }
+\PrgNewFunction \ClistCount { m } { \Expand { \clist_count:n { #1 } } }
-\PrgNewFunction \ClistVarCount { m }
+\PrgNewFunction \ClistVarCount { M } { \Expand { \clist_count:N #1 } }
+
+\PrgNewFunction \ClistGet { M M }
{
- \Result { \Expand { \clist_count:N #1 } }
+ \clist_get:NN #1 #2
+ \__fun_quark_upgrade_no_value:N #2
}
-
-\PrgNewFunction \ClistGet { M M } { \clist_get:NN #1 #2 }
\PrgNewFunction \ClistGetT { M M n } { \clist_get:NNT #1 #2 {#3} }
\PrgNewFunction \ClistGetF { M M n } { \clist_get:NNF #1 #2 {#3} }
\PrgNewFunction \ClistGetTF { M M n n } { \clist_get:NNTF #1 #2 {#3} {#4} }
@@ -1610,6 +1637,7 @@
{
\__fun_do_assignment:Nnn #1
{ \clist_gpop:NN #1 #2 } { \clist_pop:NN #1 #2 }
+ \__fun_quark_upgrade_no_value:N #2
}
\PrgNewFunction \ClistPopT { M M n }
{
@@ -1673,7 +1701,7 @@
\clist_if_empty:nTF {#1} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
}
-\PrgNewConditional \ClistVarIfEmpty { m }
+\PrgNewConditional \ClistVarIfEmpty { M }
{
\clist_if_empty:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
}
@@ -1690,3 +1718,402 @@
{ \Result { \cTrueBool } } { \Result { \cFalseBool } }
}
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Sequences and Stacks (Seq)}
+%%% --------------------------------------------------------
+
+\seq_new:N \lTmpaSeq \seq_new:N \lTmpbSeq \seq_new:N \lTmpcSeq
+\seq_new:N \lTmpiSeq \seq_new:N \lTmpjSeq \seq_new:N \lTmpkSeq
+\seq_new:N \l at Funx@Seq \seq_new:N \l at Funy@Seq \seq_new:N \l at Funz@Seq
+
+\seq_new:N \gTmpaSeq \seq_new:N \gTmpbSeq \seq_new:N \gTmpcSeq
+\seq_new:N \gTmpiSeq \seq_new:N \gTmpjSeq \seq_new:N \gTmpkSeq
+\seq_new:N \g at Funx@Seq \seq_new:N \g at Funy@Seq \seq_new:N \g at Funz@Seq
+
+\seq_set_eq:NN \cEmptySeq \c_empty_seq
+
+\PrgNewFunction \SeqNew { M } { \seq_new:N #1 }
+
+\PrgNewFunction \SeqVarLog { M } { \seq_log:N #1 }
+
+\PrgNewFunction \SeqVarShow { M } { \seq_show:N #1 }
+
+\PrgNewFunction \SeqVarJoin { M m }
+ {
+ \Expand { \seq_use:Nn #1 { #2 } }
+ }
+
+\PrgNewFunction \SeqVarJoinExtended { M m m m }
+ {
+ \Expand { \seq_use:Nnnn #1 { #2 } { #3 } { #4 } }
+ }
+
+\PrgNewFunction \SeqJoin { m m }
+ {
+ \Expand { \seq_use:nn { #1 } { #2 } }
+ }
+
+\PrgNewFunction \SeqJoinExtended { m m m m }
+ {
+ \Expand { \seq_use:nnnn { #1 } { #2 } { #3 } { #4 } }
+ }
+
+\PrgNewFunction \SeqConstFromClist { M m } { \seq_const_from_clist:Nn #1 { #2 } }
+
+\PrgNewFunction \SeqSetFromClist { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gset_from_clist:Nn #1 {#2} } { \seq_set_from_clist:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqSetEq { M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gset_eq:NN #1 #2 } { \seq_set_eq:NN #1 #2 }
+ }
+
+\PrgNewFunction \SeqSetSplit { M m m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gset_split:Nnn #1 {#2} {#3} } { \seq_set_split:Nnn #1 {#2} {#3} }
+ }
+
+\PrgNewFunction \SeqConcat { M M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gconcat:NNN #1 #2 #3 } { \seq_concat:NNN #1 #2 #3 }
+ }
+
+\PrgNewFunction \SeqClear { M }
+ {
+ \__fun_do_assignment:Nnn #1 { \seq_gclear:N #1 } { \seq_clear:N #1 }
+ }
+
+\PrgNewFunction \SeqClearNew { M }
+ {
+ \__fun_do_assignment:Nnn #1 { \seq_gclear_new:N #1 } { \seq_clear_new:N #1 }
+ }
+
+\PrgNewFunction \SeqPutLeft { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gput_left:Nn #1 {#2} } { \seq_put_left:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqPutRight { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gput_right:Nn #1 {#2} } { \seq_put_right:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqVarRemoveDuplicates { M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gremove_duplicates:N #1 } { \seq_remove_duplicates:N #1 }
+ }
+
+\PrgNewFunction \SeqVarRemoveAll { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gremove_all:Nn #1 {#2} } { \seq_remove_all:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqVarReverse { M }
+ {
+ \__fun_do_assignment:Nnn #1 { \seq_greverse:N #1 } { \seq_reverse:N #1 }
+ }
+
+\PrgNewFunction \SeqVarSort { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gsort:Nn #1 {#2} } { \seq_sort:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqVarCount { M } { \Expand { \seq_count:N #1 } }
+
+\PrgNewFunction \SeqGet { M M }
+ {
+ \seq_get:NN #1 #2
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqGetT { M M n } { \seq_get:NNT #1 #2 {#3} }
+\PrgNewFunction \SeqGetF { M M n } { \seq_get:NNF #1 #2 {#3} }
+\PrgNewFunction \SeqGetTF { M M n n } { \seq_get:NNTF #1 #2 {#3} {#4} }
+
+\PrgNewFunction \SeqPop { M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop:NN #1 #2 } { \seq_pop:NN #1 #2 }
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqPopT { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop:NNT #1 #2 {#3} } { \seq_pop:NNT #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopF { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop:NNF #1 #2 {#3} } { \seq_pop:NNF #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopTF { M M n n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop:NNTF #1 #2 {#3} {#4} } { \seq_pop:NNTF #1 #2 {#3} {#4} }
+ }
+
+\PrgNewFunction \SeqPush { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpush:Nn #1 {#2} } { \seq_push:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \SeqGetLeft { M M }
+ {
+ \seq_get_left:NN #1 #2
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqGetLeftT { M M n } { \seq_get_left:NNT #1 #2 {#3} }
+\PrgNewFunction \SeqGetLeftF { M M n } { \seq_get_left:NNF #1 #2 {#3} }
+\PrgNewFunction \SeqGetLeftTF { M M n n } { \seq_get_left:NNTF #1 #2 {#3} {#4} }
+
+\PrgNewFunction \SeqGetRight { M M }
+ {
+ \seq_get_right:NN #1 #2
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqGetRightT { M M n } { \seq_get_right:NNT #1 #2 {#3} }
+\PrgNewFunction \SeqGetRightF { M M n } { \seq_get_right:NNF #1 #2 {#3} }
+\PrgNewFunction \SeqGetRightTF { M M n n } { \seq_get_right:NNTF #1 #2 {#3} {#4} }
+
+\PrgNewFunction \SeqPopLeft { M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_left:NN #1 #2 } { \seq_pop_left:NN #1 #2 }
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqPopLeftT { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_left:NNT #1 #2 {#3} } { \seq_pop_left:NNT #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopLeftF { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_left:NNF #1 #2 {#3} } { \seq_pop_left:NNF #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopLeftTF { M M n n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_left:NNTF #1 #2 {#3} {#4} }
+ { \seq_pop_left:NNTF #1 #2 {#3} {#4} }
+ }
+
+\PrgNewFunction \SeqPopRight { M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_right:NN #1 #2 } { \seq_pop_right:NN #1 #2 }
+ \__fun_quark_upgrade_no_value:N #2
+ }
+\PrgNewFunction \SeqPopRightT { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_right:NNT #1 #2 {#3} } { \seq_pop_right:NNT #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopRightF { M M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_right:NNF #1 #2 {#3} } { \seq_pop_right:NNF #1 #2 {#3} }
+ }
+\PrgNewFunction \SeqPopRightTF { M M n n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \seq_gpop_right:NNTF #1 #2 {#3} {#4} }
+ { \seq_pop_right:NNTF #1 #2 {#3} {#4} }
+ }
+
+\PrgNewFunction \SeqVarItem { M m } { \Expand { \seq_item:Nn #1 {#2} } }
+
+\PrgNewFunction \SeqVarRandItem { M } { \Expand { \seq_rand_item:N #1 } }
+
+\PrgNewFunction \SeqVarMapInline { M n }
+ {
+ \seq_map_inline:Nn #1 {#2}
+ }
+
+\PrgNewFunction \SeqVarMapVariable { M M n }
+ {
+ \seq_map_variable:NNn #1 #2 {#3}
+ }
+
+\cs_set_eq:NN \SeqMapBreak \seq_map_break:
+
+\PrgNewConditional \SeqIfExist { M }
+ {
+ \seq_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+\PrgNewConditional \SeqVarIfEmpty { M }
+ {
+ \seq_if_empty:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+\PrgNewConditional \SeqVarIfIn { M m }
+ {
+ \seq_if_in:NnTF #1 {#2}
+ { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Property Lists (Prop)}
+%%% --------------------------------------------------------
+
+\prop_new:N \lTmpaProp \prop_new:N \lTmpbProp \prop_new:N \lTmpcProp
+\prop_new:N \lTmpiProp \prop_new:N \lTmpjProp \prop_new:N \lTmpkProp
+\prop_new:N \l at Funx@Prop \prop_new:N \l at Funy@Prop \prop_new:N \l at Funz@Prop
+
+\prop_new:N \gTmpaProp \prop_new:N \gTmpbProp \prop_new:N \gTmpcProp
+\prop_new:N \gTmpiProp \prop_new:N \gTmpjProp \prop_new:N \gTmpkProp
+\prop_new:N \g at Funx@Prop \prop_new:N \g at Funy@Prop \prop_new:N \g at Funz@Prop
+
+\prop_set_eq:NN \cEmptyProp \c_empty_prop
+
+\PrgNewFunction \PropNew { M } { \prop_new:N #1 }
+
+\PrgNewFunction \PropVarLog { M } { \prop_log:N #1 }
+
+\PrgNewFunction \PropVarShow { M } { \prop_show:N #1 }
+
+\PrgNewFunction \PropConstFromKeyval { M m }
+ { \prop_const_from_keyval:Nn #1 { #2 } }
+
+\PrgNewFunction \PropSetFromKeyval { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gset_from_keyval:Nn #1 {#2} } { \prop_set_from_keyval:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \PropSetEq { M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gset_eq:NN #1 #2 } { \prop_set_eq:NN #1 #2 }
+ }
+
+\PrgNewFunction \PropClear { M }
+ {
+ \__fun_do_assignment:Nnn #1 { \prop_gclear:N #1 } { \prop_clear:N #1 }
+ }
+
+\PrgNewFunction \PropClearNew { M }
+ {
+ \__fun_do_assignment:Nnn #1 { \prop_gclear_new:N #1 } { \prop_clear_new:N #1 }
+ }
+
+\PrgNewFunction \PropConcat { M M M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gconcat:NNN #1 #2 #3 } { \prop_concat:NNN #1 #2 #3 }
+ }
+
+\PrgNewFunction \PropPut { M m m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gput:Nnn #1 {#2} {#3} } { \prop_put:Nnn #1 {#2} {#3} }
+ }
+
+\PrgNewFunction \PropPutIfNew { M m m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gput_if_new:Nnn #1 {#2} {#3} } { \prop_put_if_new:Nnn #1 {#2} {#3} }
+ }
+
+\PrgNewFunction \PropPutFromKeyval { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gput_from_keyval:Nn #1 {#2} } { \prop_put_from_keyval:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \PropVarRemove { M m }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gremove:Nn #1 {#2} } { \prop_remove:Nn #1 {#2} }
+ }
+
+\PrgNewFunction \PropVarCount { M } { \Expand { \prop_count:N #1 } }
+
+\PrgNewFunction \PropVarItem { M m } { \Expand { \prop_item:Nn #1 {#2} } }
+
+\PrgNewFunction \PropToKeyval { M } { \Expand { \prop_to_keyval:N #1 } }
+
+\PrgNewFunction \PropGet { M m M }
+ {
+ \prop_get:NnN #1 {#2} #3
+ \__fun_quark_upgrade_no_value:N #3
+ }
+\PrgNewFunction \PropGetT { M m M n } { \prop_get:NnNT #1 {#2} #3 {#4} }
+\PrgNewFunction \PropGetF { M m M n } { \prop_get:NnNF #1 {#2} #3 {#4} }
+\PrgNewFunction \PropGetTF { M m M n n } { \prop_get:NnNTF #1 {#2} #3 {#4} {#5} }
+
+\PrgNewFunction \PropPop { M m M }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gpop:NnN #1 {#2} #3 } { \prop_pop:NnN #1 {#2} #3 }
+ \__fun_quark_upgrade_no_value:N #3
+ }
+\PrgNewFunction \PropPopT { M m M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gpop:NnNT #1 {#2} #3 {#4} } { \prop_pop:NnNT #1 {#2} #3 {#4} }
+ }
+\PrgNewFunction \PropPopF { M m M n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gpop:NnNF #1 {#2} #3 {#4} } { \prop_pop:NnNF #1 {#2} #3 {#4} }
+ }
+\PrgNewFunction \PropPopTF { M m M n n }
+ {
+ \__fun_do_assignment:Nnn #1
+ { \prop_gpop:NnNTF #1 {#2} #3 {#4} {#5} }
+ { \prop_pop:NnNTF #1 {#2} #3 {#4} {#5} }
+ }
+
+\PrgNewFunction \PropVarMapInline { M n }
+ {
+ \prop_map_inline:Nn #1 {#2}
+ }
+
+\cs_set_eq:NN \PropMapBreak \prop_map_break:
+
+\PrgNewConditional \PropIfExist { M }
+ {
+ \prop_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+\PrgNewConditional \PropVarIfEmpty { M }
+ {
+ \prop_if_empty:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+\PrgNewConditional \PropVarIfIn { M m }
+ {
+ \prop_if_in:NnTF #1 {#2}
+ { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Quarks (Quark)}
+%%% --------------------------------------------------------
+
+\quark_new:N \qNoValue
+
+\cs_new_protected:Npn \__fun_quark_upgrade_no_value:N #1
+ {
+ \quark_if_no_value:NT #1 { \tl_set_eq:NN #1 \qNoValue }
+ }
+
+\PrgNewConditional \QuarkVarIfNoValue { M }
+ {
+ \tl_if_eq:NNTF \qNoValue #1
+ { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+ }
+
More information about the tex-live-commits
mailing list.