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.