texlive[62804] Master/texmf-dist: functional (18mar22)

commits+karl at tug.org commits+karl at tug.org
Sat Mar 19 21:01:01 CET 2022


Revision: 62804
          http://tug.org/svn/texlive?view=revision&revision=62804
Author:   karl
Date:     2022-03-19 21:01:01 +0100 (Sat, 19 Mar 2022)
Log Message:
-----------
functional (18mar22)

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-03-19 20:00:30 UTC (rev 62803)
+++ trunk/Master/texmf-dist/doc/latex/functional/README.txt	2022-03-19 20:01:01 UTC (rev 62804)
@@ -1,4 +1,4 @@
-Functional: LaTeX2 functional interfaces to LaTeX3 programming layer
+Functional: LaTeX2 functional interfaces for LaTeX3 programming layer
 Copyright : 2022 (c) Jianrui Lyu <tolvjr at 163.com>
 Repository: https://github.com/lvjr/functional
 Repository: https://bitbucket.org/lvjr/functional

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-03-19 20:00:30 UTC (rev 62803)
+++ trunk/Master/texmf-dist/doc/latex/functional/functional.tex	2022-03-19 20:01:01 UTC (rev 62804)
@@ -1,9 +1,9 @@
-%  -*- coding: utf-8 -*-
-
+% -*- coding: utf-8 -*-
+% !TEX program = lualatex
 \documentclass[oneside]{book}
 \usepackage[a4paper,margin=2.5cm]{geometry}
 
-\newcommand*{\myversion}{2022A}
+\newcommand*{\myversion}{2022B}
 \newcommand*{\mydate}{Version \myversion\ (\the\year-\mylpad\month-\mylpad\day)}
 \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
 
@@ -18,6 +18,8 @@
 \NewCodeHighEnv{code}{style/main=gray9,style/code=gray9}
 \NewCodeHighEnv{demo}{style/main=gray9,style/code=gray9,demo}
 
+\usepackage{enumitem}
+
 \NewDocumentCommand\MySubScript{m}{$_{#1}$}
 
 \ExplSyntaxOn
@@ -34,13 +36,13 @@
 }
 \ExplSyntaxOff
 
-\NewDocumentEnvironment{variable}{m}{
+\NewDocumentEnvironment{variable}{om}{
   \vspace{5pt}
   \begin{minipage}{\linewidth}
   \hrule\vspace{4pt}\obeylines%
   \begingroup
   \ttfamily\bfseries\color{azure3}
-  \PrintVarList{#1}
+  \PrintVarList{#2}
   \endgroup
   \par\vspace{4pt}\hrule
   \end{minipage}\par\nopagebreak\vspace{4pt}
@@ -48,7 +50,7 @@
   \vspace{5pt}%
 }
 
-\NewDocumentEnvironment{function}{m}{
+\NewDocumentEnvironment{function}{om}{
   \vspace{5pt}%
 }{\vspace{5pt}}
 
@@ -74,6 +76,9 @@
   \texttt{\{}\textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}\texttt{\}}%
 }
 
+\NewDocumentCommand\nan{}{\texttt{NaN}}
+\NewDocumentCommand\enquote{m}{``#1''}
+
 \let\tn=\cs
 
 \RenewDocumentCommand\emph{m}{%
@@ -92,7 +97,7 @@
 
 \begin{document}
 
-\title{\sffamily LaTeX2 \textcolor{green3}{Functional} Interfaces to LaTeX3 Programming Layer}
+\title{\sffamily LaTeX2 \textcolor{green3}{Functional} Interfaces for LaTeX3 Programming Layer}
 \author{Jianrui Lyu (tolvjr at 163.com)\\\url{https://github.com/lvjr/functional}}
 \date{\mydate\vspace{1cm}\\\myabstract\vspace{10cm}}
 
@@ -120,44 +125,48 @@
 
 We will compare our first example with a similar \verb!Lua! example:
 
+\begin{minipage}{0.55\textwidth}
+\begin{codehigh}
+%% function code
+\IgnoreSpacesOn
+\PrgNewFunction \MathSquare { m } {
+  \IntSet \lTmpaInt { \IntEval {#1 * #1} }
+  \Result { \Value \lTmpaInt }
+}
+\IgnoreSpacesOff
+\MathSquare{5}
+\MathSquare{\MathSquare{5}}
+\end{codehigh}
+\end{minipage}%
+\begin{minipage}{0.45\textwidth}
 \begin{code}
--- lua code --
+-- define a function --
 function MathSquare (arg)
   local lTmpaInt = arg * arg
   return lTmpaInt
 end
+-- use the function --
 print(MathSquare(5))
 print(MathSquare(MathSquare(5)))
 \end{code}
+\end{minipage}
 
-\begin{codehigh}
-%% function code
-\ExplSyntaxOn
-\PrgNewFunction \MathSquare { m } {
-  \IntSet \lTmpaInt { \IntEval { #1 * #1 } }
-  \Result { \Value \lTmpaInt }
-}
-\ExplSyntaxOff
-\MathSquare{5}
-\MathSquare{\MathSquare{5}}
-\end{codehigh}
-
-%\ExplSyntaxOn
+%\IgnoreSpacesOn
 %\PrgNewFunction \MathSquare { m }{
 %  \IntSet \lTmpaInt { \IntEval { #1 * #1 } }
 %  \Result { \Value \lTmpaInt }
 %}
-%\ExplSyntaxOff
+%\IgnoreSpacesOff
 %\MathSquare{5}
 %\MathSquare{\MathSquare{5}}
 
-%\ExplSyntaxOn
+%\IgnoreSpacesOn
 %\PrgNewFunction \MathCubic { m }
 %  {
 %    \IntSet \lTmpaInt { \IntEval { #1 * #1 * #1 } }
 %    \Result { \Value \lTmpaInt }
 %  }
-%\ExplSyntaxOff
+%\IgnoreSpacesOff
 %\MathCubic{2}
 %\MathCubic{\MathCubic{2}}
 
@@ -176,38 +185,42 @@
 inserting result tokens to the input stream at the appropriate time.
 
 To remove space tokens inside function code in defining functions,
-you'd better put function definitions inside \verb!\ExplSyntaxOn! and
-\verb!\ExplSyntaxOff! block. Within this block, \verb!~! is used to input a space.
+you'd better put function definitions inside \verb!\IgnoreSpacesOn! and
+\verb!\IgnoreSpacesOff! block. Within this block, \verb!~! is used to input a space.
 
 At the end of this section,
 we will compare our factorial example with a similar \verb!Lua! example:
 
+\begin{minipage}{0.69\textwidth}
+\begin{codehigh}
+\IgnoreSpacesOn
+\PrgNewFunction \Fact { m } {
+  \IntCompareTF {#1} = {0} {
+    \Result {1}
+  }{
+    \Result {\IntMathMult{#1}{\Fact{\IntMathSub{#1}{1}}}}
+  }
+}
+\IgnoreSpacesOff
+\Fact{4}
+\end{codehigh}
+\end{minipage}%
+\begin{minipage}{0.31\textwidth}
 \begin{code}
--- lua code --
-function Factorial (n)
+-- define a function --
+function Fact (n)
   if n == 0 then
     return 1
   else
-    return n * Factorial(n-1)
+    return n * Fact(n-1)
   end
 end
-print(Factorial(4))
+-- use the function --
+print(Fact(4))
 \end{code}
+\end{minipage}
 
-\begin{codehigh}
-\ExplSyntaxOn
-\PrgNewFunction \Factorial { m } {
-  \IntCompareTF {#1} = {0} {
-    \Result {1}
-  }{
-    \Result { \IntMathMult {#1} { \Factorial { \IntMathSub{#1}{1} } } }
-  }
-}
-\ExplSyntaxOff
-\Factorial{4}
-\end{codehigh}
-
-%\ExplSyntaxOn
+%\IgnoreSpacesOn
 %\PrgNewFunction \Factorial { m } {
 %  \IntCompareTF {#1} = {0} {
 %    \Result {1}
@@ -215,7 +228,7 @@
 %    \Result { \IntMathMult {#1} { \Factorial { \IntMathSub{#1}{1} } } }
 %  }
 %}
-%\ExplSyntaxOff
+%\IgnoreSpacesOff
 %\Factorial{0}
 %\Factorial{4}
 
@@ -223,47 +236,50 @@
 
 In \verb!Lua! language, a function or a condition expression makes a block,
 and the values of local variables will be reset after a block.
-For example
-
-\begin{code}
--- lua code --
-local a = 1
-print(a)          ---- 1
-function SomeFun()
-  local a = 2
-  print(a)        ---- 2
-  if 1 > 0 then
-    local a = 3
-    print(a)      ---- 3
-  end
-  print(a)        ---- 2
-end
-SomeFun()
-print(a)          ---- 1
-\end{code}
-
 In \verb!functional! package, a condition expression is in fact a function,
 and you can make every function become a group by setting
 \verb!\Functional{scoping=true}!. For example
 
+\begin{minipage}{0.58\textwidth}
 \begin{codehigh}
 \Functional{scoping=true}
-\ExplSyntaxOn
+\IgnoreSpacesOn
 \IntSet \lTmpaInt {1}
-\IntLog \lTmpaInt             % ---- 1
+\IntLogVar \lTmpaInt            % ---- 1
 \PrgNewFunction \SomeFun { } {
   \IntSet \lTmpaInt {2}
-  \IntLog \lTmpaInt           % ---- 2
+  \IntLogVar \lTmpaInt          % ---- 2
   \IntCompareTF {1} > {0} {
     \IntSet \lTmpaInt {3}
-    \IntLog \lTmpaInt         % ---- 3
+    \IntLogVar \lTmpaInt        % ---- 3
   }{ }
-  \IntLog \lTmpaInt           % ---- 2
+  \IntLogVar \lTmpaInt          % ---- 2
 }
 \SomeFun
-\IntLog \lTmpaInt             % ---- 1
-\ExplSyntaxOff
+\IntLogVar \lTmpaInt            % ---- 1
+\IgnoreSpacesOff
 \end{codehigh}
+\end{minipage}%
+\begin{minipage}{0.42\textwidth}
+\begin{code}
+-- lua code --
+-- begin example --
+local a = 1
+print(a)            ---- 1
+function SomeFun()
+  local a = 2
+  print(a)          ---- 2
+  if 1 > 0 then
+    local a = 3
+    print(a)        ---- 3
+  end
+  print(a)          ---- 2
+end
+SomeFun()
+print(a)            ---- 1
+-- end example --
+\end{code}
+\end{minipage}
 
 Same as \verb!expl3!, the names of local variables \emph{must} start with \verb!l!,
 while names of global variables \emph{must} start with \verb!g!.
@@ -275,22 +291,46 @@
 The previous example will produce different result
 if we change variable from \verb!\lTmpaInt! to \verb!\gTmpaInt!.
 
+\begin{minipage}{0.58\textwidth}
 \begin{codehigh}
 \Functional{scoping=true}
+\IgnoreSpacesOn
 \IntSet \gTmpaInt {1}
-\IntLog \gTmpaInt             % ---- 1
+\IntLogVar \gTmpaInt            % ---- 1
 \PrgNewFunction \SomeFun { } {
   \IntSet \gTmpaInt {2}
-  \IntLog \gTmpaInt           % ---- 2
+  \IntLogVar \gTmpaInt          % ---- 2
   \IntCompareTF {1} > {0} {
     \IntSet \gTmpaInt {3}
-    \IntLog \gTmpaInt         % ---- 3
+    \IntLogVar \gTmpaInt        % ---- 3
   }{ }
-  \IntLog \gTmpaInt           % ---- 3
+  \IntLogVar \gTmpaInt          % ---- 3
 }
 \SomeFun
-\IntLog \gTmpaInt             % ---- 3
+\IntLogVar \gTmpaInt            % ---- 3
+\IgnoreSpacesOff
 \end{codehigh}
+\end{minipage}%
+\begin{minipage}{0.42\textwidth}
+\begin{code}
+-- lua code --
+-- begin example --
+a = 1
+print(a)            ---- 1
+function SomeFun()
+  a = 2
+  print(a)          ---- 2
+  if 1 > 0 then
+    a = 3
+    print(a)        ---- 3
+  end
+  print(a)          ---- 3
+end
+SomeFun()
+print(a)            ---- 3
+-- end example --
+\end{code}
+\end{minipage}
 
 As you can see, the values of global variables will never be reset after a group.
 
@@ -326,9 +366,9 @@
             [I] \Result{25}
             [O] 25
         [O] 25
-    [I] \IntSet\lTmpaInt {25}
-    [O]
-        [I] \Value\lTmpaInt
+    [I] \IntSet{\lTmpaInt }{25}
+    [O] 
+        [I] \Value{\lTmpaInt }
         [O] 25
     [I] \Result{25}
     [O] 25
@@ -340,9 +380,9 @@
             [I] \Result{625}
             [O] 625
         [O] 625
-    [I] \IntSet\lTmpaInt {625}
-    [O]
-        [I] \Value\lTmpaInt
+    [I] \IntSet{\lTmpaInt }{625}
+    [O] 
+        [I] \Value{\lTmpaInt }
         [O] 625
     [I] \Result{625}
     [O] 625
@@ -354,16 +394,22 @@
 Within \verb!expl3!, there are eight commands for defining new functions,
 which is good for power users.
 
+\begin{minipage}{0.5\textwidth}
 \begin{code}[language=latex/latex3]
 \cs_new:Npn
 \cs_new_nopar:Npn
 \cs_new_protected:Npn
 \cs_new_protected_nopar:Npn
+\end{code}
+\end{minipage}%
+\begin{minipage}{0.5\textwidth}
+\begin{code}[language=latex/latex3]
 \cs_new:Nn
 \cs_new_nopar:Nn
 \cs_new_protected:Nn
 \cs_new_protected_nopar:Nn
 \end{code}
+\end{minipage}
 
 Within \verb!functional! package, there is only one command (\cs{PrgNewFunction})
 for defining new functions, which is good for normal users.
@@ -377,6 +423,7 @@
 Within \verb!expl3!, there are several expansion variants for arguments,
 and many expansion functions for expanding them, which are necessary for power users.
 
+\begin{minipage}{0.5\textwidth}
 \begin{code}[language=latex/latex3]
 \module_foo:c
 \module_bar:e
@@ -386,7 +433,8 @@
 \module_bar:V
 \module_bar:v
 \end{code}
-
+\end{minipage}%
+\begin{minipage}{0.5\textwidth}
 \begin{code}[language=latex/latex3]
 \exp_args:Nc
 \exp_args:Ne
@@ -396,6 +444,7 @@
 \exp_args:NV
 \exp_args:Nv
 \end{code}
+\end{minipage}
 
 Within \verb!functional! package, there are only three variants
 (\verb!c!, \verb!e!, \verb!V!) are provided, and these variants are defined
@@ -426,7 +475,7 @@
 \Value{\Name{lTmpaInt}}
 \end{demohigh}
 
-\chapter{Basic Definitions (\texttt{l3basics})}
+\chapter{Functional Progarmming (\texttt{Prg})}
 
 \section{Defining Functions and Conditionals}
 
@@ -470,6 +519,8 @@
 which are \Arg{true code} and \Arg{false code}.\par
 \end{function}
 
+\section{Collecting Returned Values}
+
 \begin{function}{\Result}
 \begin{syntax}
 \cs{Result} \Arg{tokens}
@@ -478,8 +529,10 @@
 This function is normally used in the \meta{code} of \cs{PrgNewFunction} and \cs{PrgNewConditional}.
 \end{function}
 
-\section{Expanding and Using Tokens}
+\chapter{Argument Using (\texttt{Use})}
 
+\section{Expanding Tokens}
+
 \begin{function}{\Name}
 \begin{syntax}
 \cs{Name} \Arg{control sequence name}
@@ -538,6 +591,8 @@
 of this material inside the argument of \cs{Expand} function.
 \end{function}
 
+\section{Using Tokens}
+
 \begin{function}{\UseOne,\GobbleOne}
 \begin{syntax}
 \cs{UseOne} \Arg{argument}
@@ -578,10 +633,19 @@
 \end{demohigh}
 \end{function}
 
-\chapter{Control Structures (\texttt{l3prg})}
+\chapter{Control Structures (\texttt{Bool})}
 
-\section{Scratch Variables of Booleans}
+\section{Constant and Scratch Booleans}
 
+\begin{variable}{\cTrueBool,\cFalseBool}
+Constants that represent \verb|true| and \verb|false|, respectively. Used to
+implement predicates. For example
+\begin{demohigh}
+\BoolVarIfTF \cTrueBool {\Result{True!}} {\Result{False!}}
+\BoolVarIfTF \cFalseBool {\Result{True!}} {\Result{False!}}
+\end{demohigh}
+\end{variable}
+
 \begin{variable}{\lTmpaBool,\lTmpbBool,\lTmpcBool,\lTmpiBool,\lTmpjBool,\lTmpkBool}
 Scratch booleans for local assignment. These are never used by
 the \verb!functional! package, and so are safe for use with any
@@ -596,11 +660,8 @@
 code and so should only be used for short-term storage.
 \end{variable}
 
-%\BoolIfTF\cTrueBool{\Result{true}}{\Result{false}}
-%\BoolIfTF\cFalseBool{\Result{true}}{\Result{false}}
+\section{Creating and Setting Booleans}
 
-\section{Public Functions for Booleans}
-
 \begin{function}{\BoolNew}
 \begin{syntax}
 \cs{BoolNew} \meta{boolean}
@@ -610,6 +671,33 @@
 \meta{boolean} is initially \texttt{false}.
 \end{function}
 
+\begin{function}{\BoolConst}
+\begin{syntax}
+\cs{BoolConst} \meta{boolean} \Arg{boolexpr}
+\end{syntax}
+Creates a new constant \meta{boolean} or raises an error if the name
+is already taken. The value of the \meta{boolean} is set globally to
+the result of evaluating the \meta{boolexpr}.
+For example
+\begin{codehigh}
+\BoolConst \cFooSomeBool {\IntCompare{3}>{2}}
+\BoolVarLog \cFooSomeBool
+\end{codehigh}
+\end{function}
+
+\begin{function}{\BoolSet}
+\begin{syntax}
+\cs{BoolSet} \meta{boolean} \Arg{boolexpr}
+\end{syntax}
+Evaluates the \meta{boolean expression} and sets the \meta{boolean} variable to
+the logical truth of this evaluation.
+For example
+\begin{codehigh}
+\BoolSet \lTmpaBool {\IntCompare{3}<{2}}
+\BoolVarLog \lTmpaBool
+\end{codehigh}
+\end{function}
+
 \begin{function}{\BoolSetTrue}
 \begin{syntax}
 \cs{BoolSetTrue} \meta{boolean}
@@ -624,25 +712,166 @@
 Sets \meta{boolean} logically \texttt{false}.
 \end{function}
 
-\begin{function}{\BoolIf,\BoolIfTF}
+\begin{function}{\BoolSetEq}
 \begin{syntax}
-\cs{BoolIf} \meta{boolean}
-\cs{BoolIfTF} \meta{boolean} \Arg{true code} \Arg{false code}
+\cs{BoolSetEq} \meta{boolean_1} \meta{boolean_2}
 \end{syntax}
+Sets \meta{boolean_1} to the current value of \meta{boolean_2}.
+For example
+\begin{codehigh}
+\BoolSetTrue \lTmpaBool
+\BoolSetEq \lTmpbBool \lTmpaBool
+\BoolVarLog \lTmpbBool
+\end{codehigh}
+\end{function}
+
+\section{Viewing Booleans}
+
+\begin{function}{\BoolLog}
+\begin{syntax}
+\cs{BoolLog} \Arg{boolean expression}
+\end{syntax}
+Writes the logical truth of the \meta{boolean expression} in the log file.
+\end{function}
+
+\begin{function}{\BoolVarLog}
+\begin{syntax}
+\cs{BoolVarLog} \meta{boolean}
+\end{syntax}
+Writes the logical truth of the \meta{boolean} in the log file.
+\end{function}
+
+\begin{function}{\BoolShow}
+\begin{syntax}
+\cs{BoolShow} \Arg{boolean expression}
+\end{syntax}
+Displays the logical truth of the \meta{boolean expression} on the terminal.
+\end{function}
+
+\begin{function}{\BoolVarShow}
+\begin{syntax}
+\cs{BoolVarShow} \meta{boolean}
+\end{syntax}
+Displays the logical truth of the \meta{boolean} on the terminal.
+\end{function}
+
+\section{Booleans and Conditionals}
+
+\begin{function}{\BoolIfExist,\BoolIfExistTF}
+\begin{syntax}
+\cs{BoolIfExist} \meta{boolean}
+\cs{BoolIfExistTF} \meta{boolean} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{boolean} is currently defined.  This does not
+check that the \meta{boolean} really is a boolean variable.
+For example
+\begin{demohigh}
+\BoolIfExistTF \lTmpaBool {\Result{Yes}} {\Result{No}}
+\BoolIfExistTF \lFooUndefinedBool {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\BoolVarIf,\BoolVarIfTF}
+\begin{syntax}
+\cs{BoolVarIf} \meta{boolean}
+\cs{BoolVarIfTF} \meta{boolean} \Arg{true code} \Arg{false code}
+\end{syntax}
 Tests the current truth of \meta{boolean}, and continues evaluation
 based on this result. For example
 \begin{demohigh}
-\BoolSetTrue\lTmpaBool
-\BoolIfTF\lTmpaBool{\Result{True!}}{\Result{False!}}
-\BoolSetFalse\lTmpaBool
-\BoolIfTF\lTmpaBool{\Result{True!}}{\Result{False!}}
+\BoolSetTrue \lTmpaBool
+\BoolVarIfTF \lTmpaBool {\Result{True!}} {\Result{False!}}
+\BoolSetFalse \lTmpaBool
+\BoolVarIfTF \lTmpaBool {\Result{True!}} {\Result{False!}}
 \end{demohigh}
 \end{function}
 
-\chapter{Token Lists (\texttt{l3tl})}
+\begin{function}{\BoolVarNot,\BoolVarNotTF}
+\begin{syntax}
+\cs{BoolVarNot} \meta{boolean}
+\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!.
+For example
+\begin{demohigh}
+\BoolVarNotTF {\IntCompare{3}>{2}} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
 
-\section{Scratch Variables of Token Lists}
+\begin{function}{\BoolVarAnd,\BoolVarAndTF}
+\begin{syntax}
+\cs{BoolVarAnd} \meta{boolean_1} \meta{boolean_2}
+\cs{BoolVarAndTF} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Implements the \enquote{And} operation between two booleans,
+hence is \texttt{true} if both are \texttt{true}.
+%Contrarily to the infix operator \verb|&&|,
+The \meta{boolean_2} is only evaluated if it is needed to determine the result of
+\cs{BoolVarAnd}.
+For example
+\begin{demohigh}
+\BoolVarAndTF {\IntCompare{3}>{2}} {\IntCompare{3}>{4}} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
 
+\begin{function}{\BoolVarOr,\BoolVarOrTF}
+\begin{syntax}
+\cs{BoolVarOr} \meta{boolean_1} \meta{boolean_2}
+\cs{BoolVarOrTF} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Implements the \enquote{Or} operation between two booleans,
+hence is \texttt{true} if either one is \texttt{true}.
+%Contrarily to the infix operator \verb"||",
+The \meta{boolean_2} is only evaluated if it is needed to determine the result of
+\cs{BoolVarOr}.
+For example
+\begin{demohigh}
+\BoolVarOrTF {\IntCompare{3}>{2}} {\IntCompare{3}>{4}} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\BoolVarXor,\BoolVarXorTF}
+\begin{syntax}
+\cs{BoolVarXor} \meta{boolean_1} \meta{boolean_2}
+\cs{BoolVarXorTF} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Implements an \enquote{exclusive or} operation between two booleans.
+For example
+\begin{demohigh}
+\BoolVarXorTF {\IntCompare{3}>{2}} {\IntCompare{3}>{4}} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\chapter{Token Lists (\texttt{Tl})}
+
+\section{Constant and Scratch Token Lists}
+
+\begin{variable}{\cSpaceTl}
+An explicit space character contained in a token list%
+%(compare this with \cs{c_space_token})
+. For use where an explicit space is required.
+\end{variable}
+
+\begin{variable}{\cEmptyTl}
+Constant that is always empty.
+\end{variable}
+
+%\begin{variable}{\cNoValueTl}
+%A marker for the absence of an argument. This constant \verb|tl| can safely
+%be typeset (\emph{cf.}~\cs{qNil}), with the result being \verb|-NoValue-|.
+%It is important to note that \cs{cNoValueTl} is constructed such that it
+%will \emph{not} match the simple text input \verb|-NoValue-|, \emph{i.e.}
+%that
+%\begin{demohigh}
+%\TlIfEqTF {\TlUse\cNoValueTl} {-NoValue-} {Result{Yes}} {\Result{No}}
+%\end{demohigh}
+%The \cs{cNoValueTl} marker is intended for
+%use in creating document-level interfaces, where it serves as an indicator
+%that an (optional) argument was omitted. In particular, it is distinct
+%from a simple empty \verb|tl|.
+%\end{variable}
+
 \begin{variable}{\lTmpaTl,\lTmpbTl,\lTmpcTl,\lTmpiTl,\lTmpjTl,\lTmpkTl}
 Scratch token lists for local assignment. These are never used by
 the \verb!functional! package, and so are safe for use with any
@@ -657,17 +886,26 @@
 code and so should only be used for short-term storage.
 \end{variable}
 
-\section{Public Functions for Token Lists}
+\section{Creating and Using Token Lists}
 
 \begin{function}{\TlNew}
 \begin{syntax}
-\cs{TlNew} \meta{tl~var}
+\cs{TlNew} \meta{tl var}
 \end{syntax}
-Creates a new \meta{tl~var} or raises an error if the
+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.
 \end{function}
 
+\begin{function}{\TlConst}
+\begin{syntax}
+\cs{TlConst} \meta{tl var} \Arg{token list}
+\end{syntax}
+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}.
+\end{function}
+
 \begin{function}{\TlUse}
 \begin{syntax}
 \cs{TlUse} \meta{tl~var}
@@ -678,6 +916,97 @@
 a \meta{tl~var} directly without an accessor function.
 \end{function}
 
+\begin{function}{\TlToStr}
+\begin{syntax}
+\cs{TlToStr} \Arg{token list}
+\end{syntax}
+Converts the \meta{token list} to a \meta{string}, returning the
+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).
+%This function requires only a single expansion.
+%Its argument \emph{must} be braced.
+%\begin{texnote}
+%This is the \eTeX{} primitive \tn{detokenize}.
+%Converting a \meta{token list} to a \meta{string} yields a
+%concatenation of the string representations of every token in the
+%\meta{token list}.
+%The string representation of a control sequence is
+%\begin{itemize}
+%\item an escape character, whose character code is given by the
+%internal parameter \tn{escapechar}, absent if the
+%\tn{escapechar} is negative or greater than the largest
+%character code;
+%\item the control sequence name, as defined by \cs{cs_to_str:N};
+%\item a space, unless the control sequence name is a single
+%character whose category at the time of expansion of
+%\cs{tl_to_str:n} is not \enquote{letter}.
+%\end{itemize}
+%The string representation of an explicit character token is that
+%character, doubled in the case of (explicit) macro parameter
+%characters (normally \verb|#|).
+%In particular, the string representation of a token list may
+%depend on the category codes in effect when it is evaluated, and
+%the value of the \tn{escapechar}: for instance |\tl_to_str:n {\a}|
+%normally produces the three character \enquote{backslash},
+%\enquote{lower-case a}, \enquote{space}, but it may also produce a
+%single \enquote{lower-case a} if the escape character is negative
+%and \texttt{a} is currently not a letter.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\TlVarToStr}
+\begin{syntax}
+\cs{TlVarToStr} \meta{tl var}
+\end{syntax}
+Converts the content of the \meta{tl var} to a string, returning the
+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).
+\end{function}
+
+\section{Viewing Token Lists}
+
+\begin{function}{\TlLog}
+\begin{syntax}
+\cs{TlLog} \Arg{token list}
+\end{syntax}
+Writes the \meta{token list} in the log file. See also
+\cs{TlShow} which displays the result in the terminal.
+\end{function}
+
+\begin{function}{\TlVarLog}
+\begin{syntax}
+\cs{TlVarLog} \meta{tl var}
+\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.
+\end{function}
+
+\begin{function}{\TlShow}
+\begin{syntax}
+\cs{TlShow} \Arg{token list}
+\end{syntax}
+Displays the \meta{token list} on the terminal.
+%\begin{texnote}
+%This is similar to the \eTeX{} primitive \tn{showtokens}, wrapped
+%to a fixed number of characters per line.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\TlVarShow}
+\begin{syntax}
+\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}
+\end{function}
+
+\section{Setting Token List Variables}
+
 \begin{function}{\TlSet}
 \begin{syntax}
 \cs{TlSet} \meta{tl~var} \Arg{tokens}
@@ -685,11 +1014,19 @@
 Sets \meta{tl~var} to contain \meta{tokens},
 removing any previous content from the variable. For example
 \begin{demohigh}
-\TlSet\lTmpiTl{\IntMathMult{4}{5}}
-\TlUse\lTmpiTl
+\TlSet \lTmpiTl {\IntMathMult{4}{5}}
+\TlUse \lTmpiTl
 \end{demohigh}
 \end{function}
 
+\begin{function}{\TlSetEq}
+\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}.
+\end{function}
+
 \begin{function}{\TlClear}
 \begin{syntax}
 \cs{TlClear} \meta{tl~var}
@@ -696,13 +1033,31 @@
 \end{syntax}
 Clears all entries from the \meta{tl~var}. For example
 \begin{demohigh}
-\TlSet\lTmpjTl{One}
-\TlClear\lTmpjTl
-\TlSet\lTmpjTl{Two}
-\TlUse\lTmpjTl
+\TlSet \lTmpjTl {One}
+\TlClear \lTmpjTl
+\TlSet \lTmpjTl {Two}
+\TlUse \lTmpjTl
 \end{demohigh}
 \end{function}
 
+\begin{function}{\TlClearNew}
+\begin{syntax}
+\cs{TlClearNew} \meta{tl var}
+\end{syntax}
+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.
+\end{function}
+
+\begin{function}{\TlConcat}
+\begin{syntax}
+\cs{TlConcat} \meta{tl var_1} \meta{tl var_2} \meta{tl var_3}
+\end{syntax}
+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.
+\end{function}
+
 \begin{function}{\TlPutLeft}
 \begin{syntax}
 \cs{TlPutLeft} \meta{tl~var} \Arg{tokens}
@@ -710,9 +1065,9 @@
 Appends \meta{tokens} to the left side of the current content of
 \meta{tl~var}. For example
 \begin{demohigh}
-\TlSet\lTmpkTl{Functional}
-\TlPutLeft\lTmpkTl{Hello}
-\TlUse\lTmpkTl
+\TlSet \lTmpkTl {Functional}
+\TlPutLeft \lTmpkTl {Hello}
+\TlUse \lTmpkTl
 \end{demohigh}
 \end{function}
 
@@ -723,50 +1078,1234 @@
 Appends \meta{tokens} to the right side of the current content of
 \meta{tl~var}. For example
 \begin{demohigh}
-\TlSet\lTmpkTl{Functional}
-\TlPutRight\lTmpkTl{World}
-\TlUse\lTmpkTl
+\TlSet \lTmpkTl {Functional}
+\TlPutRight \lTmpkTl {World}
+\TlUse \lTmpkTl
 \end{demohigh}
 \end{function}
 
+\section{Replacing Tokens}
+
+Within token lists, replacement takes place at the top level: there is
+no recursion into brace groups (more precisely, within a group defined by
+a categroy code $1$/$2$ pair).
+
+\begin{function}{\TlReplaceOnce}
+\begin{syntax}
+\cs{TlReplaceOnce} \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}
+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$).
+\end{function}
+
+\begin{function}{\TlReplaceAll}
+\begin{syntax}
+\cs{TlReplaceAll} \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}
+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$).
+As this function
+operates from left to right, the pattern \meta{old tokens}
+may remain after the replacement (see \cs{TlRemoveAll}
+for an example).
+\end{function}
+
+\begin{function}{\TlRemoveOnce}
+\begin{syntax}
+\cs{TlRemoveOnce} \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$).
+\end{function}
+
+\begin{function}{\TlRemoveAll}
+\begin{syntax}
+\cs{TlRemoveAll} \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|#|
+(more precisely, explicit character tokens with category code $1$
+(begin-group) or $2$ (end-group), and tokens with category code $6$).
+As this function
+operates from left to right, the pattern \meta{tokens}
+may remain after the removal, for instance,
+\begin{demohigh}
+\TlSet \lTmpaTl {abbccd}
+\TlRemoveAll \lTmpaTl {bc}
+\TlUse \lTmpaTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\TlTrimSpaces}
+\begin{syntax}
+\cs{TlTrimSpaces} \Arg{token list}
+\end{syntax}
+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{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
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\TlVarTrimSpaces}
+\begin{syntax}
+\cs{TlVarTrimSpaces} \meta{tl var}
+\end{syntax}
+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.
+\end{function}
+
+\section{Working with the Content of Token Lists}
+
+\begin{function}{\TlCount}
+\begin{syntax}
+\cs{TlCount} \Arg{tokens}
+\end{syntax}
+Counts the number of \meta{items} in \meta{tokens} and returns this information.
+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}.
+\end{function}
+
+\begin{function}{\TlVarCount}
+\begin{syntax}
+\cs{TlVarCount} \meta{tl var}
+\end{syntax}
+Counts the number of \meta{items} in the \meta{tl var} and returns this information.
+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}.
+\end{function}
+
+\begin{function}{\TlHead}
+\begin{syntax}
+\cs{TlHead} \Arg{token list}
+\end{syntax}
+Returns the first \meta{item} in the \meta{token list},
+discarding the rest of the \meta{token list}.
+All leading explicit space characters
+(explicit tokens with character code $32$ and category code $10$)
+are discarded; for example
+\begin{demohigh}
+\fbox {1\TlHead{ abc }2}
+\fbox {1\TlHead{  abc }2}
+\end{demohigh}
+If the \enquote{head} is a brace group, rather than a single token,
+the braces are removed, and so
+\begin{codehigh}
+\TlHead { { ab} c }
+\end{codehigh}
+yields \verb*| ab|.
+A blank \meta{token list} (see \cs{TlIfBlank}) results in
+\cs{TlHead} returning nothing.
+%\begin{texnote}
+%The result is returned within \cs{exp_not:n}, which means that the token
+%list does not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\TlVarHead}
+\begin{syntax}
+\cs{TlVarHead} \meta{tl var}
+\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.
+\end{function}
+
+\begin{function}{\TlTail}
+\begin{syntax}
+\cs{TlTail} \Arg{token list}
+\end{syntax}
+Discards all leading explicit space characters
+(explicit tokens with character code $32$ and category code $10$)
+and the first \meta{item} in the \meta{token list}, and returns the
+remaining tokens. Thus for example
+\begin{codehigh}
+\TlTail { a {bc} d }
+\end{codehigh}
+and
+\begin{codehigh}
+\TlTail {  a {bc} d }
+\end{codehigh}
+both return \verb*| {bc} d |.  A blank \meta{token list} (see \cs{TlIfBlank})
+results in \cs{TlTail} returning nothing.
+%\begin{texnote}
+%The result is returned within \cs{exp_not:n}, which means that the
+%token list does not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\TlVarTail}
+\begin{syntax}
+\cs{TlVarTail} \meta{tl var}
+\end{syntax}
+Discards all leading explicit space characters
+(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.
+\end{function}
+
+\begin{function}{\TlItem,\TlVarItem}
+\begin{syntax}
+\cs{TlItem} \Arg{token list} \Arg{integer expression}
+\cs{TlVarItem} \meta{tl var} \Arg{integer expression}
+\end{syntax}
+Indexing items in the \meta{token list} from $1$ on the left, this
+function evaluates the \meta{integer expression} and returns the
+appropriate item from the \meta{token list}.
+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{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}{\TlRandItem,\TlVarRandItem}
+\begin{syntax}
+\cs{TlRandItem} \Arg{token list}
+\cs{TlVarRandItem} \meta{tl var}
+\end{syntax}
+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{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{Mapping over Token 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}{\TlMapFunction}
+%\begin{syntax}
+%\cs{TlMapFunction} \Arg{token list} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every \meta{item} in the \meta{token list},
+%The \meta{function} receives one argument for each iteration.
+%This may be a number of tokens if the \meta{item} was stored within
+%braces. Hence the \meta{function} should anticipate receiving
+%\texttt{n}-type arguments.
+%\end{function}
+%
+%\begin{function}{\TlVarMapFunction}
+%\begin{syntax}
+%\cs{TlVarMapFunction} \meta{tl var} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every \meta{item} in the \meta{tl var}.
+%The \meta{function} receives one argument for each iteration.
+%This may be a number of tokens if the \meta{item} was stored within
+%braces. Hence the \meta{function} should anticipate receiving
+%\texttt{n}-type arguments.
+%\end{function}
+
+\begin{function}{\TlMapInline}
+\begin{syntax}
+\cs{TlMapInline} \Arg{token list} \Arg{inline function}
+\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|.
+\end{function}
+
+\begin{function}{\TlVarMapInline}
+\begin{syntax}
+\cs{TlVarMapInline} \meta{tl var} \Arg{inline function}
+\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|.
+\end{function}
+
+%\begin{function}{\TlMapTokens,\TlVarMapTokens}
+%\begin{syntax}
+%\cs{TlMapTokens} \Arg{tokens} \Arg{code}
+%\cs{TlVarMapTokens} \meta{tl var} \Arg{code}
+%\end{syntax}
+%Analogue of \cs{tl_map_function:NN} which maps several tokens
+%instead of a single function.  The \meta{code} receives each \meta{item} in
+%the \meta{tl var} or in \meta{tokens} as a trailing brace group. For
+%instance,
+%\begin{verbatim}
+%\tl_map_tokens:Nn \l_my_tl { \prg_replicate:nn { 2 } }
+%\end{verbatim}
+%expands to twice each \meta{item} in the \meta{tl var}: for each \meta{item} in
+%\cs{l_my_tl} the function \cs{prg_replicate:nn} receives |2| and
+%\meta{item} as its two arguments.  The function
+%\cs{tl_map_inline:Nn} is typically faster but is not expandable.
+%\end{function}
+
+\begin{function}{\TlMapVariable}
+\begin{syntax}
+\cs{TlMapVariable} \Arg{token list} \meta{variable} \Arg{code}
+\end{syntax}
+Stores each \meta{item} of the \meta{token list} 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{tl var}, or its original value if the \meta{tl var} is blank.
+\end{function}
+
+\begin{function}{\TlVarMapVariable}
+\begin{syntax}
+\cs{TlVarMapVariable} \meta{tl var} \meta{variable} \Arg{code}
+\end{syntax}
+Stores each \meta{item} of the \meta{tl var} 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{tl var},
+or its original value if the \meta{tl var} is blank.
+\end{function}
+
+%\begin{function}{\TlMapBreak}
+%\begin{syntax}
+%\cs{TlMapBreak}
+%\end{syntax}
+%Used to terminate a tl map function before all
+%entries in the \meta{token list variable} have been processed. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\tl_map_inline:Nn \l_my_tl
+%{
+%\str_if_eq:nnT { #1 } { bingo } { \tl_map_break: }
+%Do something useful
+%}
+%\end{verbatim}
+%See also \cs{tl_map_break:n}.
+%Use outside of a tl map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before the \meta{tokens} are
+%inserted into the input stream.
+%This depends on the design of the mapping function.
+%\end{texnote}
+%\end{function}
+%
+%\begin{function}{\TlMapBreakDo}
+%\begin{syntax}
+%\cs{TlMapBreakDo} \Arg{code}
+%\end{syntax}
+%Used to terminate a tl map function before all
+%entries in the \meta{token list variable} have been processed, inserting
+%the \meta{code} after the mapping has ended. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\tl_map_inline:Nn \l_my_tl
+%{
+%\str_if_eq:nnT { #1 } { bingo }
+%{ \tl_map_break:n { <code> } }
+%Do something useful
+%}
+%\end{verbatim}
+%Use outside of a tl 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{Token List Conditionals}
+
+\begin{function}{\TlIfExist,\TlIfExistTF}
+\begin{syntax}
+\cs{TlIfExist} \meta{tl var}
+\cs{TlIfExistTF} \meta{tl var} \Arg{true code} \Arg{false code}
+\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.
+\end{function}
+
 \begin{function}{\TlIfEmpty,\TlIfEmptyTF}
 \begin{syntax}
-\cs{TlIfEmpty} \meta{tl~var}
-\cs{TlIfEmptyTF} \meta{tl~var} \Arg{true code} \Arg{false code}
+\cs{TlIfEmpty} \Arg{token list}
+\cs{TlIfEmptyTF} \Arg{token list} \Arg{true code} \Arg{false code}
 \end{syntax}
+Tests if the \meta{token list} is entirely empty
+(\emph{i.e.}~contains no tokens at all). For example
+\begin{demohigh}
+\TlIfEmptyTF {abc} {\Result{Empty}} {\Result{NonEmpty}}
+\TlIfEmptyTF {} {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\TlVarIfEmpty,\TlVarIfEmptyTF}
+\begin{syntax}
+\cs{TlVarIfEmpty} \meta{tl~var}
+\cs{TlVarIfEmptyTF} \meta{tl~var} \Arg{true code} \Arg{false code}
+\end{syntax}
 Tests if the \meta{token list variable} is entirely empty
 (\emph{i.e.}~contains no tokens at all). For example
 \begin{demohigh}
-\TlSet\lTmpaTl{abc}
-\TlIfEmptyTF\lTmpaTl{\Result{Empty}}{\Result{NonEmpty}}
-\TlClear\lTmpaTl
-\TlIfEmptyTF\lTmpaTl{\Result{Empty}}{\Result{NonEmpty}}
+\TlSet \lTmpaTl {abc}
+\TlVarIfEmptyTF \lTmpaTl {\Result{Empty}} {\Result{NonEmpty}}
+\TlClear \lTmpaTl
+\TlVarIfEmptyTF \lTmpaTl {\Result{Empty}} {\Result{NonEmpty}}
 \end{demohigh}
 \end{function}
 
+\begin{function}{\TlIfBlank}
+\begin{syntax}
+\cs{TlIfBlank} \Arg{token list}
+\cs{TlIfBlankTF} \Arg{token list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{token list} consists only of blank spaces
+(\emph{i.e.} contains no item). The test is \texttt{true} if
+\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.
+\end{function}
+
 \begin{function}{\TlIfEq,\TlIfEqTF}
 \begin{syntax}
-\cs{TlIfEq} \meta{tl~var_1} \meta{tl~var_2}
-\cs{TlIfEqTF} \meta{tl~var_1} \meta{tl~var_2} \Arg{true code} \Arg{false code}
+\cs{TlIfEq} \Arg{token list_1} \Arg{token list_2}
+\cs{TlIfEqTF} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code}
 \end{syntax}
+Tests if \meta{token list_1} and \meta{token list_2} contain the
+same list of tokens, both in respect of character codes and category
+codes. See \cs{StrIfEq} if category codes are not important.
+For example
+\begin{demohigh}
+\TlIfEqTF {abc} {abc} {\Result{Yes}} {\Result{No}}
+\TlIfEqTF {abc} {xyz} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+%\begin{demohigh}
+%\TlSet\lTmpaTl{abc}
+%\TlSet\lTmpbTl{abc}
+%\TlSet\lTmpcTl{xyz}
+%\TlIfEqTF{\TlUse\lTmpaTl}{\TlUse\lTmpbTl}{\Result{Yes}}{\Result{No}}
+%\TlIfEqTF{\TlUse\lTmpaTl}{\TlUse\lTmpcTl}{\Result{Yes}}{\Result{No}}
+%\end{demohigh}
+\end{function}
+
+\begin{function}{\TlVarIfEq,\TlVarIfEqTF}
+\begin{syntax}
+\cs{TlVarIfEq} \meta{tl var_1} \meta{tl var_2}
+\cs{TlVarIfEqTF} \meta{tl var_1} \meta{tl var_2} \Arg{true code} \Arg{false code}
+\end{syntax}
 Compares the content of two \meta{token list variables} and
 is logically \texttt{true} if the two contain the same list of
 tokens (\emph{i.e.}~identical in both the list of characters they
 contain and the category codes of those characters). For example
 \begin{demohigh}
-\TlSet\lTmpaTl{abc}
-\TlSet\lTmpbTl{abc}
-\TlSet\lTmpcTl{xyz}
-\TlIfEqTF\lTmpaTl\lTmpbTl{\Result{Yes}}{\Result{No}}
-\TlIfEqTF\lTmpaTl\lTmpcTl{\Result{Yes}}{\Result{No}}
+\TlSet \lTmpaTl {abc}
+\TlSet \lTmpbTl {abc}
+\TlSet \lTmpcTl {xyz}
+\TlVarIfEqTF \lTmpaTl \lTmpbTl {\Result{Yes}} {\Result{No}}
+\TlVarIfEqTF \lTmpaTl \lTmpcTl {\Result{Yes}} {\Result{No}}
 \end{demohigh}
-%See also \cs{StrIfEqTF} for a comparison that ignores category codes.
+See also \cs{StrVarIfEq} for a comparison that ignores category codes.
 \end{function}
 
-\chapter{Integers (\texttt{l3int})}
+\begin{function}{\TlIfIn,\TlIfInTF}
+\begin{syntax}
+\cs{TlIfIn} \Arg{token list_1} \Arg{token list_2}
+\cs{TlIfInTF} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if \meta{token list_2} is found inside \meta{token list_1}.
+The \meta{token list_2} cannot contain 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$).
+The search does \emph{not} enter brace (category code $1$/$2$) groups.
+\end{function}
 
-\section{Scratch Variables of Integers}
+\begin{function}{\TlVarIfIn,\TlVarIfInTF}
+\begin{syntax}
+\cs{TlVarIfIn} \meta{tl var} \Arg{token list}
+\cs{TlVarIfInTF} \meta{tl var} \Arg{token list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{token list} is found in the content of the
+\meta{tl var}. The \meta{token list} cannot contain
+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$).
+\end{function}
 
+\begin{function}{\TlIfSingle,\TlIfSingleTF}
+\begin{syntax}
+\cs{TlIfSingle} \Arg{token list}
+\cs{TlIfSingleTF} \Arg{token list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{token list} has exactly one \meta{item}, \emph{i.e.} is
+a single normal token (neither an explicit space 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{TlCount}.
+\end{function}
+
+\begin{function}{\TlVarIfSingle,\TlVarIfSingleTF}
+\begin{syntax}
+\cs{TlVarIfSingle} \meta{tl var}
+\cs{TlVarIfSingleTF} \meta{tl var} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the content of the \meta{tl var} consists of a single \meta{item},
+\emph{i.e.} is a single normal token (neither an explicit space
+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}.
+\end{function}
+
+\section{Token List Case Functions}
+
+\begin{function}{\TlVarCase}
+\begin{syntax}
+\cs{TlVarCase} \meta{test token list variable}
+~ ~ \verb"{"
+~ ~ ~ ~ \meta{token list variable case_1} \Arg{code case_1}
+~ ~ ~ ~ \meta{token list variable case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \meta{token list variable case_n} \Arg{code case_n}
+~ ~ \verb"}"
+\end{syntax}
+This function compares the \meta{test token list variable} in turn
+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. The function
+does nothing if there is no match.
+\end{function}
+
+\begin{function}{\TlVarCaseT}
+\begin{syntax}
+\cs{TlVarCaseT} \meta{test token list variable}
+~ ~ \verb"{"
+~ ~ ~ ~ \meta{token list variable case_1} \Arg{code case_1}
+~ ~ ~ ~ \meta{token list variable case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \meta{token list variable case_n} \Arg{code case_n}
+~ ~ \verb"}"
+~ ~ \Arg{true code}
+\end{syntax}
+This function compares the \meta{test token list variable} in turn
+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 any of the
+cases are matched, the \meta{true code} is also inserted into the
+input stream (after the code for the appropriate case).
+\end{function}
+
+\begin{function}{\TlVarCaseF}
+\begin{syntax}
+\cs{TlVarCaseF} \meta{test token list variable}
+~ ~ \verb"{"
+~ ~ ~ ~ \meta{token list variable case_1} \Arg{code case_1}
+~ ~ ~ ~ \meta{token list variable case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \meta{token list variable case_n} \Arg{code case_n}
+~ ~ \verb"}"
+~ ~ \Arg{false code}
+\end{syntax}
+This function compares the \meta{test token list variable} in turn
+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).
+\end{function}
+
+\begin{function}{\TlVarCaseTF}
+\begin{syntax}
+\cs{TlVarCaseTF} \meta{test token list variable}
+~ ~ \verb"{"
+~ ~ ~ ~ \meta{token list variable case_1} \Arg{code case_1}
+~ ~ ~ ~ \meta{token list variable case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \meta{token list variable case_n} \Arg{code case_n}
+~ ~ \verb"}"
+~ ~ \Arg{true code}
+~ ~ \Arg{false code}
+\end{syntax}
+This function compares the \meta{test token list variable} in turn
+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 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.
+\end{function}
+
+\chapter{Strings (\texttt{Str})}
+
+\section{Constant and Scratch Strings}
+
+\begin{variable}{\cAmpersandStr,\cAtsignStr,\cBackslashStr,\cLeftBraceStr,\cRightBraceStr,
+\cCircumflexStr,\cColonStr,\cDollarStr,\cHashStr,\cPercentStr,\cTildeStr,\cUnderscoreStr,\cZeroStr}
+Constant strings, containing a single character token, with category code $12$.
+\end{variable}
+
+\begin{variable}{\lTmpaStr,\lTmpbStr,\lTmpcStr,\lTmpiStr,\lTmpjStr,\lTmpkStr}
+Scratch strings 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}{\gTmpaStr,\gTmpbStr,\gTmpcStr,\gTmpiStr,\gTmpjStr,\gTmpkStr}
+Scratch strings 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 Strings}
+
+\begin{function}{\StrNew}
+\begin{syntax}
+\cs{StrNew} \meta{str var}
+\end{syntax}
+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.
+\end{function}
+
+\begin{function}{\StrConst}
+\begin{syntax}
+\cs{StrConst} \meta{str var} \Arg{token list}
+\end{syntax}
+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.
+\end{function}
+
+\begin{function}{\StrUse}
+\begin{syntax}
+\cs{StrUse} \meta{str var}
+\end{syntax}
+Recovers the content of a \meta{str var} and returns the value.
+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.
+\end{function}
+
+\section{Viewing Strings}
+
+\begin{function}{\StrLog}
+\begin{syntax}
+\cs{StrLog} \Arg{token list}
+\end{syntax}
+Writes \meta{token list} in the log file.
+\end{function}
+
+\begin{function}{\StrVarLog}
+\begin{syntax}
+\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
+\end{codehigh}
+\end{function}
+
+\begin{function}{\StrShow}
+\begin{syntax}
+\cs{StrShow} \Arg{token list}
+\end{syntax}
+Displays \meta{token list} on the terminal.
+\end{function}
+
+\begin{function}{\StrVarShow}
+\begin{syntax}
+\cs{StrVarShow} \meta{str var}
+\end{syntax}
+Displays the content of the \meta{str var} on the terminal.
+\end{function}
+
+\section{Setting String Variables}
+
+\begin{function}{\StrSet}
+\begin{syntax}
+\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
+\begin{demohigh}
+\StrSet \lTmpiStr {\IntMathMult{4}{5}}
+\StrUse \lTmpiStr
+\end{demohigh}
+\end{function}
+
+\begin{function}{\StrSetEq}
+\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}.
+\end{function}
+
+\begin{function}{\StrClear}
+\begin{syntax}
+\cs{StrClear} \meta{str var}
+\end{syntax}
+Clears the content of the \meta{str var}. For example
+\begin{demohigh}
+\StrSet \lTmpjStr {One}
+\StrClear \lTmpjStr
+\StrSet \lTmpjStr {Two}
+\StrUse \lTmpjStr
+\end{demohigh}
+\end{function}
+
+\begin{function}{\StrClearNew}
+\begin{syntax}
+\cs{StrClearNew} \meta{str var}
+\end{syntax}
+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.
+\end{function}
+
+\begin{function}{\StrConcat}
+\begin{syntax}
+\cs{StrConcat} \meta{str var_1} \meta{str var_2} \meta{str var_3}
+\end{syntax}
+Concatenates the content of \meta{str var_2} and \meta{str var_3}
+together and saves the result in \meta{str var_1}. The \meta{str var_2}
+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.
+\end{function}
+
+\begin{function}{\StrPutLeft}
+\begin{syntax}
+\cs{StrPutLeft} \meta{str var} \Arg{token list}
+\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
+\begin{demohigh}
+\StrSet \lTmpkStr {Functional}
+\StrPutLeft \lTmpkStr {Hello}
+\StrUse \lTmpkStr
+\end{demohigh}
+\end{function}
+
+\begin{function}{\StrPutRight}
+\begin{syntax}
+\cs{StrPutRight} \meta{str var} \Arg{token list}
+\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
+\begin{demohigh}
+\StrSet \lTmpkStr {Functional}
+\StrPutRight \lTmpkStr {World}
+\StrUse \lTmpkStr
+\end{demohigh}
+\end{function}
+
+\section{Modifying String Variables}
+
+\begin{function}{\StrReplaceOnce}
+\begin{syntax}
+\cs{StrReplaceOnce} \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}.
+\end{function}
+
+\begin{function}{\StrReplaceAll}
+\begin{syntax}
+\cs{StrReplaceAll} \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
+\meta{str var} with \meta{new string}.
+As this function
+operates from left to right, the pattern \meta{old string}
+may remain after the replacement.
+\end{function}
+
+\begin{function}{\StrRemoveOnce}
+\begin{syntax}
+\cs{StrRemoveOnce} \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}.
+\end{function}
+
+\begin{function}{\StrRemoveAll}
+\begin{syntax}
+\cs{StrRemoveAll} \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}.
+As this function operates from left to right,
+the pattern \meta{string} may remain after the removal, for instance,
+\begin{demohigh}
+\StrSet \lTmpaStr {abbccd}
+\StrRemoveAll \lTmpaStr {bc}
+\TlUse \lTmpaStr
+\end{demohigh}
+\end{function}
+
+\section{Working with the Content of Strings}
+
+\begin{function}{\StrCount}
+\begin{syntax}
+\cs{StrCount} \Arg{token list}
+\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
+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}
+
+\begin{function}{\StVarCount}
+\begin{syntax}
+\cs{StrVarCount} \meta{tl var}
+\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.
+\end{function}
+
+\begin{function}{\StrHead}
+\begin{syntax}
+\cs{StrHead} \Arg{token list}
+\end{syntax}
+Converts the \meta{token list} into a \meta{string}.
+The first character in the \meta{string} is then returned,
+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.
+\end{function}
+
+\begin{function}{\StrVarHead}
+\begin{syntax}
+\cs{StrVarHead} \meta{tl var}
+\end{syntax}
+Converts the \meta{tl var} into a \meta{string}.
+The first character in the \meta{string} is then returned,
+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.
+\end{function}
+
+\begin{function}{\StrTail}
+\begin{syntax}
+\cs{StrTail} \Arg{token list}
+\end{syntax}
+Converts the \meta{token list} to a \meta{string}, removes the first
+character, and returns the remaining characters (if any)
+with category codes $12$ and $10$ (for spaces).
+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.
+\end{function}
+
+\begin{function}{\StrVarTail}
+\begin{syntax}
+\cs{StrVarTail} \meta{tl var}
+\end{syntax}
+Converts the \meta{tl var} to a \meta{string}, removes the first
+character, and returns the remaining characters (if any)
+with category codes $12$ and $10$ (for spaces).
+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.
+\end{function}
+
+\begin{function}{\StrItem}
+\begin{syntax}
+\cs{StrItem} \Arg{token list} \Arg{integer expression}
+\end{syntax}
+Converts the \meta{token list} to a \meta{string},
+and returns the character in position \meta{integer expression} of
+the \meta{string}, starting at $1$ for the first (left-most)
+character. All characters including spaces are taken into account.
+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.}
+\end{function}
+
+\begin{function}{\StrVarItem}
+\begin{syntax}
+\cs{StrVarItem} \meta{tl var} \Arg{integer expression}
+\end{syntax}
+Converts the \meta{tl var} to a \meta{string},
+and returns the character in position \meta{integer expression} of
+the \meta{string}, starting at $1$ for the first (left-most)
+character. All characters including spaces are taken into account.
+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.}
+\end{function}
+
+\section{Mapping over Strings}
+
+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}{\StrMapFunction,\StrVarMapFunction}
+%\begin{syntax}
+%\cs{StrMapFunction} \Arg{token list} \meta{function}
+%\cs{StrVarMapFunction} \meta{str var} \meta{function}
+%\end{syntax}
+%Converts the \meta{token list} to a \meta{string} then
+%applies \meta{function} to every \meta{character} in the
+%\meta{string} including spaces.
+%\end{function}
+
+\begin{function}{\StrMapInline,\StrVarMapInline}
+\begin{syntax}
+\cs{StrMapInline} \Arg{token list} \Arg{inline function}
+\cs{StrVarMapInline} \meta{str var} \Arg{inline function}
+\end{syntax}
+Converts the \meta{token list} to a \meta{string} then
+applies the \meta{inline function} to every \meta{character} in the
+\meta{str var} including spaces.
+The \meta{inline function} should consist of code which
+receives the \meta{character} as \verb|#1|.
+\end{function}
+
+%\begin{function}{\StrMapTokens, \StrVarMapTokens}
+%\begin{syntax}
+%\cs{StrMapTokens} \Arg{token list} \Arg{code}
+%\cs{StrVarMapTokens} \meta{str var} \Arg{code}
+%\end{syntax}
+%Converts the \meta{token list} to a \meta{string} then applies
+%\meta{code} to every \meta{character} in the \meta{string} including spaces.
+%The \meta{code} receives each character as a trailing brace group.
+%This is equivalent to \cs{StrMapFunction} if the
+%\meta{code} consists of a single function.
+%\end{function}
+
+\begin{function}{\StrMapVariable,\StrMapVariable}
+\begin{syntax}
+\cs{StrMapVariable} \Arg{token list} \meta{variable} \Arg{code}
+\cs{StrVarMapVariable} \meta{str var} \meta{variable} \Arg{code}
+\end{syntax}
+Converts the \meta{token list} to a \meta{string} then stores each
+\meta{character} in the \meta{string} (including spaces) in turn in
+the (string or 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{character} in the \meta{string}, or its original value if the
+\meta{string} is empty.
+\end{function}
+
+%\begin{function}{\StrMapBreak}
+%\begin{syntax}
+%\cs{StrMapBreak}
+%\end{syntax}
+%Used to terminate a string map function before all
+%characters in the \meta{string} have been processed. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\str_map_inline:Nn \l_my_str
+%{
+%\str_if_eq:nnT { #1 } { bingo } { \str_map_break: }
+%Do something useful
+%}
+%\end{verbatim}
+%See also \cs{StrMapBreakDo}.
+%Use outside of a string map scenario leads to low
+%level \TeX{} errors.
+%\begin{texnote}
+%When the mapping is broken, additional tokens may be inserted
+%before continuing with the
+%code that follows the loop.
+%This depends on the design of the mapping function.
+%\end{texnote}
+%\end{function}
+%
+%\begin{function}{\StrMapBreakDo}
+%\begin{syntax}
+%\cs{StrMapBreakDo} \Arg{code}
+%\end{syntax}
+%Used to terminate a string map function before all
+%characters in the \meta{string} have been processed, inserting
+%the \meta{code} after the mapping has ended. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\str_map_inline:Nn \l_my_str
+%{
+%\str_if_eq:nnT { #1 } { bingo }
+%{ \str_map_break:n { <code> } }
+%Do something useful
+%}
+%\end{verbatim}
+%Use outside of a string 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{String Conditionals}
+
+\begin{function}{\StrIfExist,\StrIfExistTF}
+\begin{syntax}
+\cs{StrIfExist} \meta{str var}
+\cs{StrIfExistTF} \meta{str var} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{str var} is currently defined.  This does not
+check that the \meta{str var} really is a string.
+\end{function}
+
+\begin{function}{\StrVarIfEmpty,\StrVarIfEmptyTF}
+\begin{syntax}
+\cs{StrVarIfEmpty} \meta{str var}
+\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
+\begin{demohigh}
+\StrSet \lTmpaStr {abc}
+\StrVarIfEmptyTF \lTmpaStr {\Result{Empty}} {\Result{NonEmpty}}
+\StrClear \lTmpaStr
+\StrVarIfEmptyTF \lTmpaStr {\Result{Empty}} {\Result{NonEmpty}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\StrIfEq,\StrIfEqTF}
+\begin{syntax}
+\cs{StrIfEq} \Arg{tl_1} \Arg{tl_2}
+\cs{StrIfEqTF} \Arg{tl_1} \Arg{tl_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Compares the two \meta{token lists} on a character by character
+basis (namely after converting them to strings),
+and is \texttt{true} if the two \meta{strings} contain the same
+characters in the same order.
+%Thus for example
+%\begin{codehigh}
+%\StrIfEq{abc}{\TlToStr{abc}}
+%\end{codehigh}
+%is logically \texttt{true}.
+See \cs{TlIfEq} to compare
+tokens (including their category codes) rather than characters.
+For example
+\begin{demohigh}
+\StrIfEqTF {abc} {abc} {\Result{Yes}} {\Result{No}}
+\StrIfEqTF {abc} {xyz} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+%\begin{demohigh}
+%\StrSet\lTmpaStr{abc}
+%\StrSet\lTmpbStr{abc}
+%\StrSet\lTmpcStr{xyz}
+%\StrIfEqTF{\lTmpaStr}{\lTmpbStr}{\Result{Yes}}{\Result{No}}
+%\StrIfEqTF{\lTmpaStr}{\lTmpcStr}{\Result{Yes}}{\Result{No}}
+%\StrIfEqTF{\StrUse\lTmpaStr}{\StrUse\lTmpbStr}{\Result{Yes}}{\Result{No}}
+%\StrIfEqTF{\StrUse\lTmpaStr}{\StrUse\lTmpcStr}{\Result{Yes}}{\Result{No}}
+%\end{demohigh}
+\end{function}
+
+\begin{function}{\StrVarIfEq,\StrVarIfEqTF}
+\begin{syntax}
+\cs{StrVarIfEq} \meta{str var_1} \meta{str var_2}
+\cs{StrVarIfEqTF} \meta{str var_1} \meta{str var_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Compares the content of two \meta{str variables} and
+is logically \texttt{true} if the two contain the same characters
+in the same order.  See \cs{TlVarIfEq} to compare tokens
+(including their category codes) rather than characters.
+\begin{demohigh}
+\StrSet \lTmpaStr {abc}
+\StrSet \lTmpbStr {abc}
+\StrSet \lTmpcStr {xyz}
+\StrVarIfEqTF \lTmpaStr \lTmpbStr {\Result{Yes}} {\Result{No}}
+\StrVarIfEqTF \lTmpaStr \lTmpcStr {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\StrIfIn,\StrIfInTF}
+\begin{syntax}
+\cs{StrIfInTF} \Arg{tl_1} \Arg{tl_2}
+\cs{StrIfInTF} \Arg{tl_1} \Arg{tl_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Converts both \meta{token lists} to \meta{strings} and
+tests whether \meta{string_2} is found inside \meta{string_1}.
+\end{function}
+
+\begin{function}{\StrVarIfIn,\StrVarIfInTF}
+\begin{syntax}
+\cs{StrVarIfInTF} \meta{str var} \Arg{token list}
+\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}.
+\end{function}
+
+\begin{function}{\StrCompare,\StrCompareTF}
+\begin{syntax}
+\cs{StrCompare} \Arg{tl_1} \meta{relation} \Arg{tl_2}
+\cs{StrCompareTF} \Arg{tl_1} \meta{relation} \Arg{tl_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Compares the two \meta{token lists} on a character by character
+basis (namely after converting them to strings) in a lexicographic
+order according to the character codes of the characters.  The
+\meta{relation} can be \verb|<|, \verb|=|, or \verb|>| and the test is
+\texttt{true} under the following conditions:
+\begin{itemize}[nosep]
+\item for \verb|<|, if the first string is earlier than the second in lexicographic order;
+\item for \verb|=|, if the two strings have exactly the same characters;
+\item for \verb|>|, if the first string is later than the second in lexicographic order.
+\end{itemize}
+For example:
+\begin{demohigh}
+\StrCompareTF {ab} < {abc} {\Result{Yes}} {\Result{No}}
+\StrCompareTF {ab} < {aa} {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+%\begin{texnote}
+%This is a wrapper around the \TeX{} primitive
+%\cs{(pdf)strcmp}.  It is meant for programming
+%and not for sorting textual contents, as it simply considers
+%character codes and not more elaborate considerations of grapheme
+%clusters, locale, etc.
+%\end{texnote}
+\par
+Due to naming conflict, you need to use \cs{StrIfCompare}/\cs{StrIfCompareTF} as a replacement
+if you want to use \verb!functional! package together with \verb!xstring! package.
+\end{function}
+
+\section{String Case Functions}
+
+\begin{function}{\StrCase}
+\begin{syntax}
+\cs{StrCase} \Arg{test string}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{string case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{string case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{string case_n} \Arg{code case_n}
+~ ~ \verb|}|
+\end{syntax}
+Compares the \meta{test string} in turn with each
+of the \meta{string cases} (all token lists are converted to strings).
+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.
+\end{function}
+
+\begin{function}{\StrCaseT}
+\begin{syntax}
+\cs{StrCaseT} \Arg{test string}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{string case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{string case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{string case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+\end{syntax}
+Compares the \meta{test string} in turn with each
+of the \meta{string cases} (all token lists are converted to strings).
+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. 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).
+\end{function}
+
+\begin{function}{\StrCaseF}
+\begin{syntax}
+\cs{StrCaseF} \Arg{test string}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{string case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{string case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{string case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{false code}
+\end{syntax}
+Compares the \meta{test string} in turn with each
+of the \meta{string cases} (all token lists are converted to strings).
+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. If none
+match then the \meta{false code} is inserted.
+\end{function}
+
+\begin{function}{\StrCaseTF}
+\begin{syntax}
+\cs{StrCaseTF} \Arg{test string}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{string case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{string case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{string case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+~ ~ \Arg{false code}
+\end{syntax}
+Compares the \meta{test string} in turn with each
+of the \meta{string cases} (all token lists are converted to strings).
+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. 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.
+\end{function}
+
+\chapter{Integers (\texttt{Int})}
+
+\section{Constant and Scratch Integers}
+
+\begin{variable}{\cZeroInt,\cOneInt}
+Integer values used with primitive tests and assignments: their
+self-terminating nature makes these more convenient and faster than
+literal numbers.
+\end{variable}
+
+\begin{variable}{\cMaxInt}
+The maximum value that can be stored as an integer.
+\end{variable}
+
+\begin{variable}{\cMaxRegisterInt}
+Maximum number of registers.
+\end{variable}
+
+\begin{variable}{\cMaxCharInt}
+Maximum character code completely supported by the engine.
+\end{variable}
+
 \begin{variable}{\lTmpaInt,\lTmpbInt,\lTmpcInt,\lTmpiInt,\lTmpjInt,\lTmpkInt}
 Scratch integer for local assignment. These are never used by
 the \verb!functional! package, and so are safe for use with any
@@ -781,7 +2320,7 @@
 code and so should only be used for short-term storage.
 \end{variable}
 
-\section{Public Functions for Integers}
+\section{Integer Expressions}
 
 \begin{function}{\IntEval}
 \begin{syntax}
@@ -793,7 +2332,7 @@
 for negative results \texttt{-}~followed by such a sequence, and
 \texttt{0}~for zero. For example
 \begin{demohigh}
-\IntEval{(1+4)*(2-3)/5}
+\IntEval {(1+4)*(2-3)/5}
 \end{demohigh}
 \end{function}
 
@@ -804,7 +2343,7 @@
 Adds \Arg{integer expression_1} and \Arg{integer expression_2},
 and returns the result. For example
 \begin{demohigh}
-\IntMathAdd{7}{3}
+\IntMathAdd {7} {3}
 \end{demohigh}
 \end{function}
 
@@ -812,10 +2351,10 @@
 \begin{syntax}
 \cs{IntMathSub} \Arg{integer expression_1} \Arg{integer expression_2}
 \end{syntax}
-Subtracts \Arg{integer expression_1} from \Arg{integer expression_2},
+Subtracts \Arg{integer expression_2} from \Arg{integer expression_1},
 and returns the result. For example
 \begin{demohigh}
-\IntMathSub{7}{3}
+\IntMathSub {7} {3}
 \end{demohigh}
 \end{function}
 
@@ -826,7 +2365,7 @@
 Multiplies \Arg{integer expression_1} by \Arg{integer expression_2},
 and returns the result. For example
 \begin{demohigh}
-\IntMathMult{7}{3}
+\IntMathMult {7} {3}
 \end{demohigh}
 \end{function}
 
@@ -834,13 +2373,85 @@
 \begin{syntax}
 \cs{IntMathDiv} \Arg{integer expression_1} \Arg{integer expression_2}
 \end{syntax}
-Divides \Arg{integer expression_1} by \Arg{integer expression_2},
-and returns the result. For example
+Evaluates the two \meta{integer expressions} as described earlier,
+then divides the first value by the second, and rounds the result
+to the closest integer. Ties are rounded away from zero. Note that
+this is identical to using \verb|/| directly in an \meta{integer expression}.
+The result is returned as an \meta{integer denotation}.
+For example
 \begin{demohigh}
-\IntMathDiv{7}{3}
+\IntMathDiv {8} {3}
 \end{demohigh}
 \end{function}
 
+\begin{function}{\IntMathDivTrancate}
+\begin{syntax}
+\cs{IntMathDivTrancate} \Arg{integer expression_1} \Arg{integer expression_2}
+\end{syntax}
+Evaluates the two \meta{integer expressions} as described earlier,
+then divides the first value by the second, and rounds the result towards zero.
+Note that division using \verb|/| rounds to the closest integer instead.
+The result is returned as an \meta{integer denotation}.
+For example
+\begin{demohigh}
+\IntMathDivTruncate {8} {3}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\IntMathSign}
+\begin{syntax}
+\cs{IntMathSign} \Arg{intexpr}
+\end{syntax}
+Evaluates the \meta{integer expression} then leaves $1$ or $0$ or
+$-1$ in the input stream according to the sign of the result.
+\end{function}
+
+\begin{function}{\IntMathAbs}
+\begin{syntax}
+\cs{IntMathAbs} \Arg{integer expression}
+\end{syntax}
+Evaluates the \meta{integer expression} as described for
+\cs{IntEval} and leaves the absolute value of the result in
+the input stream as an \meta{integer denotation} after two
+expansions.
+\end{function}
+
+\begin{function}{\IntMathMax,\IntMathMin}
+\begin{syntax}
+\cs{IntMathMax} \Arg{intexpr_1} \Arg{intexpr_2}
+\cs{IntMathMin} \Arg{intexpr_1} \Arg{intexpr_2}
+\end{syntax}
+Evaluates the \meta{integer expressions} as described for
+\cs{IntEval} and leaves either the larger or smaller value
+in the input stream as an \meta{integer denotation} after two
+expansions.
+\end{function}
+
+\begin{function}{\IntMathMod}
+\begin{syntax}
+\cs{IntMathMod} \Arg{intexpr_1} \Arg{intexpr_2}
+\end{syntax}
+Evaluates the two \meta{integer expressions} as described earlier,
+then calculates the integer remainder of dividing the first
+expression by the second.  This is obtained by subtracting
+\cs{IntMathDivTruncate} \Arg{intexpr_1} \Arg{intexpr_2} times
+\meta{intexpr_2} from \meta{intexpr_1}.  Thus, the result has the
+same sign as \meta{intexpr_1} and its absolute value is strictly
+less than that of \meta{intexpr_2}.  The result is left in the input
+stream as an \meta{integer denotation} after two expansions.
+\end{function}
+
+\begin{function}{\IntMathRand}
+\begin{syntax}
+\cs{IntMathRand} \Arg{intexpr_1} \Arg{intexpr_2}
+\end{syntax}
+Evaluates the two \meta{integer expressions} and produces a
+pseudo-random number between the two (with bounds included).
+%This is not available in older versions of \XeTeX{}.
+\end{function}
+
+\section{Creating and Using Integers}
+
 \begin{function}{\IntNew}
 \begin{syntax}
 \cs{IntNew} \meta{integer}
@@ -850,21 +2461,57 @@
 initially equal to $0$.
 \end{function}
 
+\begin{function}{\IntConst}
+\begin{syntax}
+\cs{IntConst} \meta{integer} \Arg{integer expression}
+\end{syntax}
+Creates a new constant \meta{integer} or raises an error if the name
+is already taken. The value of the \meta{integer} is set
+globally to the \meta{integer expression}.
+\end{function}
+
 \begin{function}{\IntUse}
 \begin{syntax}
 \cs{IntUse} \meta{integer}
 \end{syntax}
 Recovers the content of an \meta{integer} and returns the value.
-An error is raised if the variable does
-not exist or if it is invalid. Can be omitted in places where an
-\meta{integer} is required (such as in the first and third arguments
-of \cs{IntCompareTF}).%
-%\begin{texnote}
-%\cs{IntUse} is the \TeX{} primitive \tn{the}: this is one of
-%several \verb!functional! names for this primitive.
-%\end{texnote}
+An error is raised if the variable does not exist or if it is invalid.
 \end{function}
 
+\section{Viewing Integers}
+
+\begin{function}{\IntLog}
+\begin{syntax}
+\cs{IntLog} \Arg{integer expression}
+\end{syntax}
+Writes the result of evaluating the \meta{integer expression}
+in the log file.
+\end{function}
+
+\begin{function}{\IntVarLog}
+\begin{syntax}
+\cs{IntVarLog} \meta{integer}
+\end{syntax}
+Writes the value of the \meta{integer} in the log file.
+\end{function}
+
+\begin{function}{\IntShow}
+\begin{syntax}
+\cs{IntShow} \Arg{integer expression}
+\end{syntax}
+Displays the result of evaluating the \meta{integer expression}
+on the terminal.
+\end{function}
+
+\begin{function}{\IntVarShow}
+\begin{syntax}
+\cs{IntVarShow} \meta{integer}
+\end{syntax}
+Displays the value of the \meta{integer} on the terminal.
+\end{function}
+
+\section{Setting Integer Variables}
+
 \begin{function}{\IntSet}
 \begin{syntax}
 \cs{IntSet} \meta{integer} \Arg{integer expression}
@@ -873,11 +2520,19 @@
 which must evaluate to an integer (as described for \cs{IntEval}).
 For example
 \begin{demohigh}
-\IntSet\lTmpaInt{3+5}
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {3+5}
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
+\begin{function}{\IntSetEq}
+\begin{syntax}
+\cs{IntSetEq} \meta{integer_1} \meta{integer_2}
+\end{syntax}
+Sets the content of \meta{integer_1} equal to that of
+\meta{integer_2}.
+\end{function}
+
 \begin{function}{\IntZero}
 \begin{syntax}
 \cs{IntZero} \meta{integer}
@@ -884,12 +2539,21 @@
 \end{syntax}
 Sets \meta{integer} to $0$. For example
 \begin{demohigh}
-\IntSet\lTmpaInt{5}
-\IntZero\lTmpaInt
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {5}
+\IntZero \lTmpaInt
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
+\begin{function}{\IntZeroNew}
+\begin{syntax}
+\cs{IntZeroNew} \meta{integer}
+\end{syntax}
+Ensures that the \meta{integer} exists globally by applying
+\cs{IntNew} if necessary, then applies \cs{IntZero} to leave
+the \meta{integer} set to zero.
+\end{function}
+
 \begin{function}{\IntIncr}
 \begin{syntax}
 \cs{IntIncr} \meta{integer}
@@ -897,9 +2561,9 @@
 Increases the value stored in \meta{integer} by $1$.
 For example
 \begin{demohigh}
-\IntSet\lTmpaInt{5}
-\IntIncr\lTmpaInt
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {5}
+\IntIncr \lTmpaInt
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
@@ -910,9 +2574,9 @@
 Decreases the value stored in \meta{integer} by $1$.
 For example
 \begin{demohigh}
-\IntSet\lTmpaInt{5}
-\IntDecr\lTmpaInt
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {5}
+\IntDecr \lTmpaInt
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
@@ -923,9 +2587,9 @@
 Adds the result of the \meta{integer expression} to the current
 content of the \meta{integer}. For example
 \begin{demohigh}
-\IntSet\lTmpaInt{5}
-\IntAdd\lTmpaInt{2}
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {5}
+\IntAdd \lTmpaInt {2}
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
@@ -936,15 +2600,69 @@
 Subtracts the result of the \meta{integer expression} from the
 current content of the \meta{integer}. For example
 \begin{demohigh}
-\IntSet\lTmpaInt{5}
-\IntSub\lTmpaInt{3}
-\IntUse\lTmpaInt
+\IntSet \lTmpaInt {5}
+\IntSub \lTmpaInt {3}
+\IntUse \lTmpaInt
 \end{demohigh}
 \end{function}
 
+\section{Integer Step Functions}
+
+%\begin{function}{\IntStepFunction}
+%\begin{syntax}
+%\cs{IntStepFunction} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
+%\end{syntax}
+%This function first evaluates the \meta{initial value}, \meta{step}
+%and \meta{final value}, all of which should be integer expressions.
+%The \meta{function} is then placed in front of each \meta{value}
+%from the \meta{initial value} to the \meta{final value} in turn
+%(using \meta{step} between each \meta{value}).  The \meta{step} must
+%be non-zero.  If the \meta{step} is positive, the loop stops when
+%the \meta{value} becomes larger than the \meta{final value}.  If the
+%\meta{step} is negative, the loop stops when the \meta{value}
+%becomes smaller than the \meta{final value}.  The \meta{function}
+%should absorb one numerical argument. For example
+%\begin{verbatim}
+%\cs_set:Npn \my_func:n #1 { [I~saw~#1] \quad }
+%\int_step_function:nnnN { 1 } { 1 } { 5 } \my_func:n
+%\end{verbatim}
+%would print
+%\begin{quote}
+%[I saw 1] \quad
+%[I saw 2] \quad
+%[I saw 3] \quad
+%[I saw 4] \quad
+%[I saw 5] \quad
+%\end{quote}
+%\end{function}
+
+\begin{function}{\IntStepInline}
+\begin{syntax}
+\cs{IntStepInline} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
+\end{syntax}
+This function first evaluates the \meta{initial value}, \meta{step}
+and \meta{final value}, all of which should be integer expressions.
+Then for each \meta{value} from the \meta{initial value} to the
+\meta{final value} in turn (using \meta{step} between each
+\meta{value}), the \meta{code} is inserted into the input stream
+with \verb|#1| replaced by the current \meta{value}. Thus the
+\meta{code} should define a function of one argument~(\verb|#1|).
+For example
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\IntStepInline {1} {3} {30} {
+  \TlPutRight \lTmpaTl {[#1]}
+}
+\Result {\Value\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [1][4][7][10][13][16][19][22][25][28].
+\end{function}
+
 \begin{function}{\IntStepVariable}
 \begin{syntax}
-\cs{IntStepVariable} \Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code}
+\cs{IntStepVariable} \Arg{initial value} \Arg{step} \Arg{final value} \meta{tl var} \Arg{code}
 \end{syntax}
 This function first evaluates the \meta{initial value}, \meta{step}
 and \meta{final value}, all of which should be integer expressions.
@@ -951,19 +2669,52 @@
 Then for each \meta{value} from the \meta{initial value} to the
 \meta{final value} in turn (using \meta{step} between each
 \meta{value}), the \meta{code} is evaluated,
-with the \meta{tl~var} defined as the current \meta{value}.  Thus
+with the \meta{tl~var} defined as the current \meta{value}. Thus
 the \meta{code} should make use of the \meta{tl~var}.
-For example
-\begin{demohigh}
-\TlClear\lTmpaTl
-\IntStepVariable{1}{3}{30}\lTmpiTl{
-  \TlPutRight\lTmpaTl{\Value\lTmpiTl}
-  \TlPutRight\lTmpaTl{ }
-}
-\Result{\Value\lTmpaTl}
-\end{demohigh}
+%For example
+%\begin{demohigh}
+%\IgnoreSpacesOn
+%\TlClear\lTmpaTl
+%\IntStepVariable{1}{3}{30}\lTmpiTl{
+%  \TlPutRight\lTmpaTl{\Value\lTmpiTl}
+%  \TlPutRight\lTmpaTl{~}
+%}
+%\Result{\Value\lTmpaTl}
+%\IgnoreSpacesOff
+%\end{demohigh}
 \end{function}
 
+\section{Integer Conditionals}
+
+\begin{function}{\IntIfExist, \IntIfExistTF}
+\begin{syntax}
+\cs{IntIfExist} \meta{integer}
+\cs{IntIfExistTF} \meta{integer} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{integer} is currently defined.  This does not
+check that the \meta{integer} really is an integer variable.
+\end{function}
+
+\begin{function}{\IntIfOdd,\IntIfOddTF}
+\begin{syntax}
+\cs{IntIfOdd} \Arg{integer expression}
+\cs{IntIfOddTF} \Arg{integer expression} \Arg{true code} \Arg{false code}
+\end{syntax}
+This function first evaluates the \meta{integer expression}
+as described for \cs{IntEval}.
+It then evaluates if this is odd or even, as appropriate.
+\end{function}
+
+\begin{function}{\IntIfEven,\IntIfEvenTF}
+\begin{syntax}
+\cs{IntIfEven} \Arg{integer expression}
+\cs{IntIfEvenTF} \Arg{integer expression} \Arg{true code} \Arg{false code}
+\end{syntax}
+This function first evaluates the \meta{integer expression}
+as described for \cs{IntEval}.
+It then evaluates if this is even or odd, as appropriate.
+\end{function}
+
 \begin{function}{\IntCompare,\IntCompareTF}
 \begin{syntax}
 \cs{IntCompare} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2}
@@ -979,11 +2730,1632 @@
 \end{tabular}\par}
 For example
 \begin{demohigh}
-\IntCompareTF{2}>{1}{\Result{Greater}}{\Result{Less}}
-\IntCompareTF{2}>{3}{\Result{Greater}}{\Result{Less}}
+\IntCompareTF {2} > {1} {\Result{Greater}} {\Result{Less}}
+\IntCompareTF {2} > {3} {\Result{Greater}} {\Result{Less}}
 \end{demohigh}
 \end{function}
 
+\section{Integer Case Functions}
+
+\begin{function}{\IntCase}
+\begin{syntax}
+\cs{IntCase} \Arg{test integer expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{intexpr case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{intexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{intexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+\end{syntax}
+This function evaluates the \meta{test integer expression} and
+compares this in turn to each of the
+\meta{integer expression cases}. If the two are equal then the
+associated \meta{code} is left in the input stream
+and other cases are discarded.
+\end{function}
+
+\begin{function}{\IntCaseT}
+\begin{syntax}
+\cs{IntCaseT} \Arg{test integer expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{intexpr case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{intexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{intexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+\end{syntax}
+This function evaluates the \meta{test integer expression} and
+compares this in turn to each of the
+\meta{integer expression cases}. If the two are equal then the
+associated \meta{code} is left in the 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).
+\end{function}
+
+\begin{function}{\IntCaseF}
+\begin{syntax}
+\cs{IntCaseF} \Arg{test integer expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{intexpr case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{intexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{intexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{false code}
+\end{syntax}
+This function evaluates the \meta{test integer expression} and
+compares this in turn to each of the
+\meta{integer expression cases}. If the two are equal 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 into the input stream 
+(after the code for the appropriate case).
+For example
+\begin{demohigh}
+\IgnoreSpacesOn
+\IntCaseF { 2 * 5 }
+  {
+    { 5 }       { Small }
+    { 4 + 6 }   { Medium }
+    { -2 * 10 } { Negative }
+  }
+  { No idea! }
+\IgnoreSpacesOff
+\end{demohigh}
+\end{function}
+
+\begin{function}{\IntCaseTF}
+\begin{syntax}
+\cs{IntCaseTF} \Arg{test integer expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{intexpr case_1} \Arg{code case_1}
+~ ~ ~ ~ \Arg{intexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ $\cdots$
+~ ~ ~ ~ \Arg{intexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+~ ~ \Arg{false code}
+\end{syntax}
+This function evaluates the \meta{test integer expression} and
+compares this in turn to each of the
+\meta{integer expression cases}. If the two are equal then the
+associated \meta{code} is left in the 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), while if none
+match then the \meta{false code} is inserted.
+\end{function}
+
+\chapter{Floating Point Numbers (\texttt{Fp})}
+
+\section{Constant and Scratch Floating Points}
+
+\begin{variable}{\cZeroFp, \cMinusZeroFp}
+Zero, with either sign.
+\end{variable}
+
+\begin{variable}{\cOneFp}
+One as an \texttt{fp}: useful for comparisons in some places.
+\end{variable}
+
+\begin{variable}{\cInfFp,\cMinusInfFp}
+Infinity, with either sign. These can be input directly in a
+floating point expression as \texttt{inf} and \texttt{-inf}.
+\end{variable}
+
+\begin{variable}{\cEFp}
+The value of the base of the natural logarithm, $\mathrm{e} = \exp(1)$.
+\end{variable}
+
+\begin{variable}{\cPiFp}
+The value of $\pi$.  This can be input directly in a floating point
+expression as \texttt{pi}.
+\end{variable}
+
+\begin{variable}{\cOneDegreeFp}
+The value of $1^{\circ}$ in radians. Multiply an angle given in
+degrees by this value to obtain a result in radians.  Note that
+trigonometric functions expecting an argument in radians or in
+degrees are both available.  Within floating point expressions, this
+can be accessed as \texttt{deg}.
+\end{variable}
+
+\begin{variable}{\lTmpaFp,\lTmpbFp,\lTmpcFp,\lTmpiFp,\lTmpjFp,\lTmpkFp}
+Scratch floating point numbers 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}{\gTmpaFp,\gTmpbFp,\gTmpcFp,\gTmpiFp,\gTmpjFp,\gTmpkFp}
+Scratch floating point numbers 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{Floating Point Expressions}
+
+\begin{function}{\FpEval}
+\begin{syntax}
+\cs{FpEval} \Arg{floating point expression}
+\end{syntax}
+Evaluates the \meta{floating point expression} and returns the
+result as a decimal number with no
+exponent.  Leading or trailing zeros may be inserted to compensate
+for the exponent.  Non-significant trailing zeros are trimmed, and
+integers are expressed without a decimal separator.  The values
+$\pm\infty$ and \nan{} trigger an \enquote{invalid operation}
+exception.
+For a tuple, each item is converted using \cs{FpEval} and they are combined as
+\verb|(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}\verb|)|
+if $n>1$ and \verb|(|\meta{fp_1}\verb|,)| or \verb|()| for fewer items.
+%This function is identical to \cs{fp_to_decimal:n}.
+For example
+\begin{demohigh}
+\FpEval {(1.2+3.4)*(5.6-7.8)/9}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathAdd}
+\begin{syntax}
+\cs{FpMathAdd} \Arg{fpexpr_1} \Arg{fpexpr_2}
+\end{syntax}
+Adds \Arg{fpexpr_1} and \Arg{fpexpr_2},
+and returns the result. For example
+\begin{demohigh}
+\FpMathAdd {2.8} {3.7}
+\FpMathAdd {3.8-1} {2.7+1}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathSub}
+\begin{syntax}
+\cs{FpMathSub} \Arg{fpexpr_1} \Arg{fpexpr_2}
+\end{syntax}
+Subtracts \Arg{fpexpr_2} from \Arg{fpexpr_1},
+and returns the result. For example
+\begin{demohigh}
+\FpMathSub {2.8} {3.7}
+\FpMathSub {3.8-1} {2.7+1}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathMult}
+\begin{syntax}
+\cs{FpMathMult} \Arg{fpexpr_1} \Arg{fpexpr_2}
+\end{syntax}
+Multiplies \Arg{fpexpr_1} by \Arg{fpexpr_2},
+and returns the result. For example
+\begin{demohigh}
+\FpMathMult {2.8} {3.7}
+\FpMathMult {3.8-1} {2.7+1}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathDiv}
+\begin{syntax}
+\cs{FpMathDiv} \Arg{fpexpr_1} \Arg{fpexpr_2}
+\end{syntax}
+Divides \Arg{fpexpr_1} by \Arg{fpexpr_2},
+and returns the result. For example
+\begin{demohigh}
+\FpMathDiv {2.8} {3.7}
+\FpMathDiv {3.8-1} {2.7+1}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathSign}
+\begin{syntax}
+\cs{FpMathSign} \Arg{fpexpr}
+\end{syntax}
+Evaluates the \meta{fpexpr} and returns the value
+using \cs{FpEval}\verb|{sign(|\meta{result}\verb|)}|: $+1$ for positive
+numbers and for $+\infty$, $-1$ for negative numbers and for
+$-\infty$, $\pm 0$ for $\pm 0$.  If the operand is a tuple or is
+\nan{}, then \enquote{invalid operation} occurs and the result
+is $0$. For example
+\begin{demohigh}
+\FpMathSign {3.5}
+\FpMathSign {-2.7}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpMathAbs}
+\begin{syntax}
+\cs{FpMathAbs} \Arg{floating point expression}
+\end{syntax}
+Evaluates the \meta{floating point expression} as described for
+\cs{FpEval} and returns the absolute value.
+If the argument is $\pm\infty$, \nan{} or a tuple,
+\enquote{invalid operation} occurs.  Within floating point
+expressions, \verb|abs()| can be used; it accepts $\pm\infty$ and \nan{}
+as arguments.
+\end{function}
+
+\begin{function}{\FpMathMax,\FpMathMin}
+\begin{syntax}
+\cs{FpMathMax} \Arg{fp expression_1} \Arg{fp expression_2}
+\cs{FpMathMin} \Arg{fp expression_1} \Arg{fp expression_2}
+\end{syntax}
+Evaluates the \meta{floating point expressions} as described for \cs{FpEval}
+and returns the resulting larger (\texttt{max}) or smaller (\texttt{min}) value.
+If the argument is a tuple, \enquote{invalid operation} occurs,
+but no other case raises exceptions. Within floating point expressions,
+\verb|max()| and \verb|min()| can be used.
+\end{function}
+
+\section{Creating and Using Floating Points}
+
+\begin{function}{\FpNew}
+\begin{syntax}
+\cs{FpNew} \meta{fp var}
+\end{syntax}
+Creates a new \meta{fp var} or raises an error if the name is
+already taken. The declaration is global. The \meta{fp~var} is
+initially $+0$.
+\end{function}
+
+\begin{function}{\FpConst}
+\begin{syntax}
+\cs{FpConst} \meta{fp var} \Arg{floating point expression}
+\end{syntax}
+Creates a new constant \meta{fp var} or raises an error if the name
+is already taken. The \meta{fp var} is set globally equal to
+the result of evaluating the \meta{floating point expression}.
+For example
+\begin{demohigh}
+\FpConst \cMyPiFp {3.1415926}
+\FpUse \cMyPiFp
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpUse}
+\begin{syntax}
+\cs{FpUse} \meta{fp var}
+\end{syntax}
+Recovers the value of the \meta{fp var} and returns the value as a
+decimal number with no exponent.
+%Leading or trailing zeros may be inserted to compensate for the
+%exponent.  Non-significant trailing zeros are trimmed.  Integers are
+%expressed without a decimal separator.  The values $\pm\infty$
+%and \nan{} trigger an \enquote{invalid operation} exception.
+%For a tuple, each item is converted using \cs{fp_to_decimal:n} and they are combined as
+%|(|\meta{fp_1}\verb*|, |\meta{fp_2}\verb*|, |\ldots{}\meta{fp_n}|)|
+%if $n>1$ and |(|\meta{fp_1}|,)| or |()| for fewer items.
+%This function is identical to \cs{fp_to_decimal:N}.
+\end{function}
+
+\section{Viewing Floating Points}
+
+\begin{function}{\FpLog}
+\begin{syntax}
+\cs{FpLog} \Arg{floating point expression}
+\end{syntax}
+Evaluates the \meta{floating point expression} and writes the
+result in the log file.
+\end{function}
+
+\begin{function}{\FpVarLog}
+\begin{syntax}
+\cs{FpVarLog} \meta{fp var}
+\end{syntax}
+Writes the value of \meta{fp var} in the log file.
+\end{function}
+
+\begin{function}{\FpShow}
+\begin{syntax}
+\cs{FpShow} \Arg{floating point expression}
+\end{syntax}
+Evaluates the \meta{floating point expression} and displays the
+result in the terminal.
+\end{function}
+
+\begin{function}{\FpVarShow}
+\begin{syntax}
+\cs{FpVarShow} \meta{fp var}
+\end{syntax}
+Displays the value of \meta{fp var} in the terminal.
+\end{function}
+
+\section{Setting Floating Point Variables}
+
+\begin{function}{\FpSet}
+\begin{syntax}
+\cs{FpSet} \meta{fp var} \Arg{floating point expression}
+\end{syntax}
+Sets \meta{fp var} equal to the result of computing the
+\meta{floating point expression}. For example
+\begin{demohigh}
+\FpSet \lTmpaFp {4/7}
+\FpUse \lTmpaFp
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpSetEq}
+\begin{syntax}
+\cs{FpSetEq} \meta{fp var_1} \meta{fp var_2}
+\end{syntax}
+Sets the floating point variable \meta{fp var_1} equal to the current
+value of \meta{fp var_2}.
+\end{function}
+
+\begin{function}{\FpZero}
+\begin{syntax}
+\cs{FpZero} \meta{fp var}
+\end{syntax}
+Sets the \meta{fp var} to $+0$. For example
+\begin{demohigh}
+\FpSet \lTmpaFp {5.3}
+\FpZero \lTmpaFp
+\FpUse \lTmpaFp
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpZeroNew}
+\begin{syntax}
+\cs{FpZeroNew} \meta{fp var}
+\end{syntax}
+Ensures that the \meta{fp var} exists globally
+by applying \cs{FpNew} if necessary, then applies
+\cs{FpZero} to leave the \meta{fp var} set to $+0$.
+\end{function}
+
+\begin{function}{\FpAdd}
+\begin{syntax}
+\cs{FpAdd} \meta{fp var} \Arg{floating point expression}
+\end{syntax}
+Adds the result of computing the \meta{floating point expression} to
+the \meta{fp var}.
+This also applies if \meta{fp var} and \meta{floating point
+expression} evaluate to tuples of the same size. For example
+\begin{demohigh}
+\FpSet \lTmpaFp {5.3}
+\FpAdd \lTmpaFp {2.11}
+\FpUse \lTmpaFp
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpSub}
+\begin{syntax}
+\cs{FpSub} \meta{fp var} \Arg{floating point expression}
+\end{syntax}
+Subtracts the result of computing the \meta{floating point
+expression} from the \meta{fp var}.
+This also applies if \meta{fp var} and \meta{floating point
+expression} evaluate to tuples of the same size. For example
+\begin{demohigh}
+\FpSet \lTmpaFp {5.3}
+\FpSub \lTmpaFp {2.11}
+\FpUse \lTmpaFp
+\end{demohigh}
+\end{function}
+
+\section{Floating Point Step Functions}
+
+%\begin{function}{\FpStepFunction}
+%\begin{syntax}
+%\cs{FpStepFunction} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
+%\end{syntax}
+%This function first evaluates the \meta{initial value}, \meta{step}
+%and \meta{final value}, each of which should be a floating point
+%expression evaluating to a floating point number, not a tuple.
+%The \meta{function} is then placed in front of each \meta{value}
+%from the \meta{initial value} to the \meta{final value} in turn
+%(using \meta{step} between each \meta{value}).  The \meta{step} must
+%be non-zero.  If the \meta{step} is positive, the loop stops when
+%the \meta{value} becomes larger than the \meta{final value}.  If the
+%\meta{step} is negative, the loop stops when the \meta{value}
+%becomes smaller than the \meta{final value}. The \meta{function}
+%should absorb one numerical argument. For example
+%\begin{verbatim}
+%\cs_set:Npn \my_func:n #1 { [I saw #1] \quad }
+%\fp_step_function:nnnN { 1.0 } { 0.1 } { 1.5 } \my_func:n
+%\end{verbatim}
+%would print
+%\begin{quote}
+%[I saw 1.0] \quad
+%[I saw 1.1] \quad
+%[I saw 1.2] \quad
+%[I saw 1.3] \quad
+%[I saw 1.4] \quad
+%[I saw 1.5] \quad
+%\end{quote}
+%\begin{texnote}
+%Due to rounding, it may happen that adding the \meta{step} to the
+%\meta{value} does not change the \meta{value}; such cases give an
+%error, as they would otherwise lead to an infinite loop.
+%\end{texnote}
+%\end{function}
+
+\begin{function}{\FpStepInline}
+\begin{syntax}
+\cs{FpStepInline} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
+\end{syntax}
+This function first evaluates the \meta{initial value}, \meta{step}
+and \meta{final value}, all of which should be floating point
+expressions evaluating to a floating point number, not a tuple.
+Then for each \meta{value} from the \meta{initial value} to the
+\meta{final value} in turn (using \meta{step} between each
+\meta{value}), the \meta{code} is inserted into the input stream
+with \verb|#1| replaced by the current \meta{value}. Thus the
+\meta{code} should define a function of one argument (\verb|#1|).
+For example
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\FpStepInline {1} {0.1} {1.5} {
+  \TlPutRight \lTmpaTl {[#1]}
+}
+\Result {\Value\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [1][1.1][1.2][1.3][1.4][1.5].
+\end{function}
+
+\begin{function}{\FpStepVariable}
+\begin{syntax}
+\cs{FpStepVariable} \Arg{initial value} \Arg{step} \Arg{final value} \meta{tl var} \Arg{code}
+\end{syntax}
+This function first evaluates the \meta{initial value}, \meta{step}
+and \meta{final value}, all of which should be floating point
+expressions evaluating to a floating point number, not a tuple.
+Then for each \meta{value} from the \meta{initial value} to the
+\meta{final value} in turn (using \meta{step} between each
+\meta{value}), the \meta{code} is inserted into the input stream,
+with the \meta{tl var} defined as the current \meta{value}.  Thus
+the \meta{code} should make use of the \meta{tl var}.
+%For example
+%\begin{demohigh}
+%\IgnoreSpacesOn
+%\TlClear\lTmpaTl
+%\FpStepVariable{1}{0.1}{1.5}\lTmpiTl{
+%  \TlPutRight\lTmpaTl{\Value\lTmpiTl}
+%  \TlPutRight\lTmpaTl{~}
+%}
+%\Result{\Value\lTmpaTl}
+%\IgnoreSpacesOff
+%\end{demohigh}
+\end{function}
+
+\section{Float Point Conditionals}
+
+\begin{function}{\FpIfExist,\FpIfExistTF}
+\begin{syntax}
+\cs{FpIfExist} \meta{fp var}
+\cs{FpIfExistTF} \meta{fp var} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{fp var} is currently defined.  This does not
+check that the \meta{fp var} really is a floating point variable.
+For example
+\begin{demohigh}
+\FpIfExistTF \lTmpaFp {\Result{Yes}} {\Result{No}}
+\FpIfExistTF \lMyUndefinedFp {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\FpCompare,\FpCompareTF}
+\begin{syntax}
+\cs{FpCompare} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2}
+\cs{FpCompareTF} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Compares the \meta{fpexpr_1} and the \meta{fpexpr_2}, and returns
+\texttt{true} if the \meta{relation} is obeyed. For example
+\begin{demohigh}
+\FpCompareTF {1} > {0.9999} {\Result{Greater}} {\Result{Less}}
+\FpCompareTF {1} > {1.0001} {\Result{Greater}} {\Result{Less}}
+\end{demohigh}
+Two floating points
+$x$ and $y$ may obey four mutually exclusive relations:
+$x<y$, $x=y$, $x>y$, or $x?y$ (\enquote{not ordered}).  The last
+case occurs exactly if one or both operands is \nan{} or is a tuple,
+unless they are equal tuples.  Note that a \nan{} is distinct from
+any value, even another \nan{}, hence $x=x$ is not true for
+a \nan{}.  To test if a value is \nan{}, compare it to an arbitrary
+number with the \enquote{not ordered} relation.\par
+%\begin{demohigh}
+%\FpCompareTF{0/0}?{0}{\Result{Is~a~Nan}}{\Result{Isn't~a~NaN}}
+%\end{demohigh}
+Tuples are equal if they have the same number of items and items
+compare equal (in particular there must be no \nan{}).
+At present any other comparison with tuples yields \verb|?| (not ordered).
+This is experimental.
+\end{function}
+
+\chapter{Dimensions (\texttt{Dim})}
+
+\section{Constant and Scratch Dimensions}
+
+\begin{variable}{\cMaxDim}
+The maximum value that can be stored as a dimension.  This can also
+be used as a component of a skip.
+\end{variable}
+
+\begin{variable}{\cZeroDim}
+A zero length as a dimension.  This can also be used as a component
+of a skip.
+\end{variable}
+
+\begin{variable}{\lTmpaDim,\lTmpbDim,\lTmpcDim,\lTmpiDim,\lTmpjDim,\lTmpkDim}
+Scratch dimensions 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}{\gTmpaDim,\gTmpbDim,\gTmpcDim,\gTmpiDim,\gTmpjDim,\gTmpkDim}
+Scratch dimensions 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{Dimension Expressions}
+
+\begin{function}{\DimEval}
+\begin{syntax}
+\cs{DimEval} \Arg{dimension expression}
+\end{syntax}
+Evaluates the \meta{dimension expression}, expanding any
+dimensions and token list variables within the \meta{expression}
+to their content (without requiring \cs{DimUse}/\cs{TlUse})
+and applying the standard mathematical rules. The result of the
+calculation is returned as a \meta{dimension denotation}.
+%This is expressed in points (\texttt{pt}), and requires suitable
+%termination if used in a \TeX{}-style assignment as it is \emph{not}
+%an \meta{internal dimension}.
+For example
+\begin{demohigh}
+\DimEval {(1.2pt+3.4pt)/9}
+\end{demohigh}
+%\DimEval{(1.2pt+3.4pt)*(5.6-7.8)/9}
+\end{function}
+
+\begin{function}{\DimMathAdd}
+\begin{syntax}
+\cs{DimMathAdd} \Arg{dimexpr_1} \Arg{dimexpr_2}
+\end{syntax}
+Adds \Arg{dimexpr_1} and \Arg{dimexpr_2},
+and returns the result. For example
+\begin{demohigh}
+\DimMathAdd {2.8pt} {3.7pt}
+\DimMathAdd {3.8pt-1pt} {2.7pt+1pt}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimMathSub}
+\begin{syntax}
+\cs{DimMathSub} \Arg{dimexpr_1} \Arg{dimexpr_2}
+\end{syntax}
+Subtracts \Arg{dimexpr_2} from \Arg{dimexpr_1},
+and returns the result. For example
+\begin{demohigh}
+\DimMathSub {2.8pt} {3.7pt}
+\DimMathSub {3.8pt-1pt} {2.7pt+1pt}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimMathRatio}
+\begin{syntax}
+\cs{DimMathRatio} \Arg{dimexpr_1} \Arg{dimexpr_2}
+\end{syntax}
+Parses the two \meta{dimension expressions},
+then calculates the ratio of the two and returns it.
+The result is a ratio expression
+between two integers, with all distances converted to scaled points.
+For example
+\begin{demohigh}
+\DimMathRatio {5pt} {10pt}
+\end{demohigh}
+The returned value is suitable for use inside a \meta{dimension expression}
+such as
+\begin{codehigh}
+\DimSet \lTmpaDim {10pt*\DimMathRatio{5pt}{10pt}}
+\end{codehigh}
+\end{function}
+
+\begin{function}{\DimMathSign}
+\begin{syntax}
+\cs{DimMathSign} \Arg{dimexpr}
+\end{syntax}
+Evaluates the \meta{dimexpr} then returns $1$ or $0$ or $-1$
+according to the sign of the result. For example
+\begin{demohigh}
+\DimMathSign {3.5pt}
+\DimMathSign {-2.7pt}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimMathAbs}
+\begin{syntax}
+\cs{DimMathAbs} \Arg{dimexpr}
+\end{syntax}
+Converts the \meta{dimexpr} to its absolute value,
+returning the result as a \meta{dimension denotation}.
+For example
+\begin{demohigh}
+\DimMathAbs {3.5pt}
+\DimMathAbs {-2.7pt}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimMathMax,\DimMathMin}
+\begin{syntax}
+\cs{DimMathMax} \Arg{dimexpr_1} \Arg{dimexpr_2}
+\cs{DimMathMin} \Arg{dimexpr_1} \Arg{dimexpr_2}
+\end{syntax}
+Evaluates the two \meta{dimension expressions} and returns either the
+maximum or minimum value as appropriate as a \meta{dimension denotation}.
+For example
+\begin{demohigh}
+\DimMathMax {3.5pt} {-2.7pt}
+\DimMathMin {3.5pt} {-2.7pt}
+\end{demohigh}
+\end{function}
+
+\section{Creating and Using Dimensions}
+
+\begin{function}{\DimNew}
+\begin{syntax}
+\cs{DimNew} \meta{dimension}
+\end{syntax}
+Creates a new \meta{dimension} or raises an error if the name is
+already taken. The declaration is global. The \meta{dimension}
+is initially equal to $0$\,pt.
+\end{function}
+
+\begin{function}{\DimConst}
+\begin{syntax}
+\cs{DimConst} \meta{dimension} \Arg{dimension expression}
+\end{syntax}
+Creates a new constant \meta{dimension} or raises an error if the
+name is already taken. The value of the \meta{dimension} is set
+globally to the \meta{dimension expression}. For example
+\begin{demohigh}
+\DimConst \cFooSomeDim {1cm}
+\DimUse \cFooSomeDim
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimUse}
+\begin{syntax}
+\cs{DimUse} \meta{dimension}
+\end{syntax}
+Recovers the content of a \meta{dimension} and returns the value.
+An error is raised if the variable does not exist or if it is invalid.
+\end{function}
+
+\section{Viewing Dimensions}
+
+\begin{function}{\DimLog}
+\begin{syntax}
+\cs{DimLog} \Arg{dimension expression}
+\end{syntax}
+Writes the result of evaluating the \meta{dimension expression}
+in the log file. For example
+\begin{codehigh}
+\DimLog {\lFooSomeDim+1cm}
+\end{codehigh}
+\end{function}
+
+\begin{function}{\DimVarLog}
+\begin{syntax}
+\cs{DimVarLog} \meta{dimension}
+\end{syntax}
+Writes the value of the \meta{dimension} in the log file. For example
+\begin{codehigh}
+\DimVarLog \lFooSomeDim
+\end{codehigh}
+\end{function}
+
+\begin{function}{\DimShow}
+\begin{syntax}
+\cs{DimShow} \Arg{dimension expression}
+\end{syntax}
+Displays the result of evaluating the \meta{dimension expression}
+on the terminal. For example
+\begin{codehigh}
+\DimShow {\lFooSomeDim+1cm}
+\end{codehigh}
+\end{function}
+
+\begin{function}{\DimVarShow}
+\begin{syntax}
+\cs{DimVarShow} \meta{dimension}
+\end{syntax}
+Displays the value of the \meta{dimension} on the terminal. For example
+\begin{codehigh}
+\DimVarShow \lFooSomeDim
+\end{codehigh}
+\end{function}
+
+\section{Setting Dimension Variables}
+
+\begin{function}{\DimSet}
+\begin{syntax}
+\cs{DimSet} \meta{dimension} \Arg{dimension expression}
+\end{syntax}
+Sets \meta{dimension} to the value of \meta{dimension expression}, which
+must evaluate to a length with units.
+\end{function}
+
+\begin{function}{\DimSetEq}
+\begin{syntax}
+\cs{DimSetEq} \meta{dimension_1} \meta{dimension_2}
+\end{syntax}
+Sets the content of \meta{dimension_1} equal to that of
+\meta{dimension_2}. For example
+\begin{demohigh}
+\DimSet \lTmpaDim {10pt}
+\DimSetEq \lTmpbDim \lTmpaDim
+\DimUse \lTmpbDim
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimZero}
+\begin{syntax}
+\cs{DimZero} \meta{dimension}
+\end{syntax}
+Sets \meta{dimension} to $0$\,pt. For example
+\begin{demohigh}
+\DimSet \lTmpaDim {1em}
+\DimZero \lTmpaDim
+\DimUse \lTmpaDim
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimZeroNew}
+\begin{syntax}
+\cs{DimZeroNew} \meta{dimension}
+\end{syntax}
+Ensures that the \meta{dimension} exists globally by applying
+\cs{DimNew} if necessary, then applies
+\cs{DimZero} to set the \meta{dimension} to zero. For example
+\begin{demohigh}
+\DimZeroNew \lFooSomeDim
+\DimUse \lFooSomeDim
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimAdd}
+\begin{syntax}
+\cs{DimAdd} \meta{dimension} \Arg{dimension expression}
+\end{syntax}
+Adds the result of the \meta{dimension expression} to the current
+content of the \meta{dimension}. For example
+\begin{demohigh}
+\DimSet \lTmpaDim {5.3pt}
+\DimAdd \lTmpaDim {2.11pt}
+\DimUse \lTmpaDim
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimSub}
+\begin{syntax}
+\cs{DimSub} \meta{dimension} \Arg{dimension expression}
+\end{syntax}
+Subtracts the result of the \meta{dimension expression} from the
+current content of the \meta{dimension}. For example
+\begin{demohigh}
+\DimSet \lTmpaDim {5.3pt}
+\DimSub \lTmpaDim {2.11pt}
+\DimUse \lTmpaDim
+\end{demohigh}
+\end{function}
+
+\section{Dimension Step Functions}
+
+%\begin{function}{\DimStepFunction}
+%\begin{syntax}
+%\cs{DimStepFunction} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
+%\end{syntax}
+%This function first evaluates the \meta{initial value}, \meta{step}
+%and \meta{final value}, all of which should be dimension expressions.
+%The \meta{function} is then placed in front of each \meta{value}
+%from the \meta{initial value} to the \meta{final value} in turn
+%(using \meta{step} between each \meta{value}).  The \meta{step} must
+%be non-zero.  If the \meta{step} is positive, the loop stops when
+%the \meta{value} becomes larger than the \meta{final value}.  If the
+%\meta{step} is negative, the loop stops when the \meta{value}
+%becomes smaller than the \meta{final value}.  The \meta{function}
+%should absorb one argument.
+%\end{function}
+
+\begin{function}{\DimStepInline}
+\begin{syntax}
+\cs{DimStepInline} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
+\end{syntax}
+This function first evaluates the \meta{initial value}, \meta{step}
+and \meta{final value}, all of which should be dimension expressions.
+Then for each \meta{value} from the \meta{initial value} to the
+\meta{final value} in turn (using \meta{step} between each
+\meta{value}), the \meta{code} is inserted into the input stream
+with \verb|#1| replaced by the current \meta{value}.  Thus the
+\meta{code} should define a function of one argument (\verb|#1|).
+For example
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\DimStepInline {1pt} {0.1pt} {1.5pt} {
+  \TlPutRight \lTmpaTl {[#1]}
+}
+\Result {\Value\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces [1.0pt][1.1pt][1.20001pt][1.30002pt][1.40002pt].
+\end{function}
+
+\begin{function}{\DimStepVariable}
+\begin{syntax}
+\cs{DimStepVariable} \Arg{initial value} \Arg{step} \Arg{final value} \meta{tl var} \Arg{code}
+\end{syntax}
+This function first evaluates the \meta{initial value}, \meta{step}
+and \meta{final value}, all of which should be dimension expressions.
+Then for each \meta{value} from the \meta{initial value} to the
+\meta{final value} in turn (using \meta{step} between each
+\meta{value}), the \meta{code} is inserted into the input stream,
+with the \meta{tl var} defined as the current \meta{value}.  Thus
+the \meta{code} should make use of the \meta{tl var}.
+%For example
+%\begin{demohigh}
+%\IgnoreSpacesOn
+%\TlClear\lTmpaTl
+%\DimStepVariable{1pt}{0.1pt}{1.5pt}\lTmpiTl{
+%  \TlPutRight\lTmpaTl{\Value\lTmpiTl}
+%  \TlPutRight\lTmpaTl{~}
+%}
+%\Result{\Value\lTmpaTl}
+%\IgnoreSpacesOff
+%\end{demohigh}
+\end{function}
+
+\section{Dimension Conditionals}
+
+\begin{function}{\DimIfExist,\DimIfExistTF}
+\begin{syntax}
+\cs{DimIfExist} \meta{dimension}
+\cs{DimIfExistTF} \meta{dimension} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests whether the \meta{dimension} is currently defined.  This does
+not check that the \meta{dimension} really is a dimension variable.
+For example
+\begin{demohigh}
+\DimIfExistTF \lTmpaDim {\Result{Yes}} {\Result{No}}
+\DimIfExistTF \lFooUndefinedDim {\Result{Yes}} {\Result{No}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimCompare,\DimCompareTF}
+\begin{syntax}
+\cs{DimCompare} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2}
+\cs{DimCompareTF} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+This function first evaluates each of the \meta{dimension expressions}
+as described for \cs{DimEval}. The two results are then
+compared using the \meta{relation}:\par
+{\centering
+\begin{tabular}{ll}
+Equal        & \verb|=| \\
+Greater than & \verb|>| \\
+Less than    & \verb|<| \\
+\end{tabular}\par}
+For example
+\begin{demohigh}
+\DimCompareTF {1pt} > {0.9999pt} {\Result{Greater}} {\Result{Less}}
+\DimCompareTF {1pt} > {1.0001pt} {\Result{Greater}} {\Result{Less}}
+\end{demohigh}
+\end{function}
+
+\section{Dimension Case Functions}
+
+\begin{function}{\DimCase}
+\begin{syntax}
+\cs{DimCase} \Arg{test dimension expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{dimexpr case_1} \Arg{code case_1}
+~ ~ ~ ~  \Arg{dimexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ \ldots
+~ ~ ~ ~ \Arg{dimexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+\end{syntax}
+This function evaluates the \meta{test dimension expression} and
+compares this in turn to each of the
+\meta{dimension expression cases}. If the two are equal then the
+associated \meta{code} is left in the input stream
+and other cases are discarded.
+\end{function}
+
+\begin{function}{\DimCaseT}
+\begin{syntax}
+\cs{DimCaseT} \Arg{test dimension expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{dimexpr case_1} \Arg{code case_1}
+~ ~ ~ ~  \Arg{dimexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ \ldots
+~ ~ ~ ~ \Arg{dimexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+\end{syntax}
+This function evaluates the \meta{test dimension expression} and
+compares this in turn to each of the
+\meta{dimension expression cases}. If the two are equal then the
+associated \meta{code} is left in the 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).
+\end{function}
+
+\begin{function}{\DimCaseF}
+\begin{syntax}
+\cs{DimCaseF} \Arg{test dimension expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{dimexpr case_1} \Arg{code case_1}
+~ ~ ~ ~  \Arg{dimexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ \ldots
+~ ~ ~ ~ \Arg{dimexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{false code}
+\end{syntax}
+This function evaluates the \meta{test dimension expression} and
+compares this in turn to each of the
+\meta{dimension expression cases}. If the two are equal then the
+associated \meta{code} is left in the input stream
+and other cases are discarded. If none of the cases
+match then the \meta{false code} is inserted.
+For example
+\begin{demohigh}
+\IgnoreSpacesOn
+\DimSet \lTmpaDim {5pt}
+\DimCaseF {2\lTmpaDim} {
+  {5pt}     {\Result{Small}}
+  {4pt+6pt} {\Result{Medium}}
+  {-10pt}   {\Result{Negative}}
+}{
+  \Result {No Match}
+}
+\IgnoreSpacesOff
+\end{demohigh}
+\end{function}
+
+\begin{function}{\DimCaseTF}
+\begin{syntax}
+\cs{DimCaseTF} \Arg{test dimension expression}
+~ ~ \verb|{|
+~ ~ ~ ~ \Arg{dimexpr case_1} \Arg{code case_1}
+~ ~ ~ ~  \Arg{dimexpr case_2} \Arg{code case_2}
+~ ~ ~ ~ \ldots
+~ ~ ~ ~ \Arg{dimexpr case_n} \Arg{code case_n}
+~ ~ \verb|}|
+~ ~ \Arg{true code}
+~ ~ \Arg{false code}
+\end{syntax}
+This function evaluates the \meta{test dimension expression} and
+compares this in turn to each of the
+\meta{dimension expression cases}. If the two are equal then the
+associated \meta{code} is left in the 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), while if none
+match then the \meta{false code} is inserted.
+%For example
+%\begin{demohigh}
+%\IgnoreSpacesOn
+%\DimSet\lTmpaDim{5pt}
+%\DimCaseTF{2\lTmpaDim}{
+%  {5pt}     {\Result{Small}}
+%  {4pt+6pt} {\Result{Medium}}
+%  {-10pt}   {\Result{Negative}}
+%}{
+%  \Result{[Some Match]}
+%}{
+%  \Result{[No Match]}
+%}
+%\IgnoreSpacesOff
+%\end{demohigh}
+\end{function}
+
+\chapter{Comma Separated Lists (\texttt{Clist})}
+
+\section{Constant and Scratch Comma Lists}
+
+\begin{variable}{\cEmptyClist}
+Constant that is always empty.
+\end{variable}
+
+\begin{variable}{\lTmpaClist,\lTmpbClist,\lTmpcClist,\lTmpiClist,\lTmpjClist,\lTmpkClist}
+Scratch comma 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}{\gTmpaClist,\gTmpbClist,\gTmpcClist,\gTmpiClist,\gTmpjClist,\gTmpkClist}
+Scratch comma 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 Comma Lists}
+
+\begin{function}{\ClistNew}
+\begin{syntax}
+\cs{ClistNew} \meta{comma list}
+\end{syntax}
+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.
+\end{function}
+ 
+\begin{function}{\ClistConst}
+\begin{syntax}
+\cs{ClistConst} \meta{clist var} \Arg{comma list}
+\end{syntax}
+Creates a new constant \meta{clist var} or raises an error
+if the name is already taken. The value of the
+\meta{clist var} is set globally to the
+\meta{comma list}.
+\end{function}
+
+\begin{function}{\ClistVarJoin}
+\begin{syntax}
+\cs{ClistVarJoin} \meta{clist var} \Arg{separator}
+\end{syntax}
+Returns the contents of the \meta{clist var},
+with the \meta{separator} between the items.
+%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 }
+\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}{\ClistVarJoinExtended}
+\begin{syntax}
+\cs{ClistVarJoinExtended} \meta{clist var} \Arg{separator between two} \Arg{separator between more than two} \Arg{separator between final two}
+\end{syntax}
+Returns the contents of the \meta{clist var},
+with the appropriate \meta{separator} between the items. Namely, if
+the comma list 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 comma list has exactly two items, then they are joined with
+the \meta{separator between two} and returns.
+%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 }
+\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}
+%do not expand further when appearing in an \texttt{x}-type
+%or \texttt{e}-type argument expansion.
+%\end{texnote}
+\end{function}
+
+\begin{function}{\ClistJoin,\ClistJoinExtended}
+\begin{syntax}
+\cs{ClistJoin} \meta{comma list} \Arg{separator}
+\cs{ClistJoinExtended} \meta{comma list} \Arg{separator between two} \Arg{separator between more than two} \Arg{separator between final two}
+\end{syntax}
+Returns the contents of the \meta{comma list},
+with the appropriate \meta{separator} between the items. As for
+\cs{ClistSet}, blank items are omitted, spaces are removed from
+both sides of each item, then a set of braces is removed if the
+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{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 Comma Lists}
+
+\begin{function}{\ClistLog}
+\begin{syntax}
+\cs{ClistLog} \Arg{tokens}
+\end{syntax}
+Writes the entries in the comma list in the log file. See also
+\cs{ClistShow} which displays the result in the terminal.
+\end{function}
+
+\begin{function}{\ClistVarLog}
+\begin{syntax}
+\cs{ClistVarLog} \meta{comma list}
+\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.
+\end{function}
+
+\begin{function}{\ClistShow}
+\begin{syntax}
+\cs{ClistShow} \Arg{tokens}
+\end{syntax}
+Displays the entries in the comma list in the terminal.
+\end{function}
+
+\begin{function}{\ClistVarShow}
+\begin{syntax}
+\cs{ClistVarShow} \meta{comma list}
+\end{syntax}
+Displays the entries in the \meta{comma list} in the terminal.
+\end{function}
+
+\section{Setting Comma Lists}
+
+\begin{function}{\ClistSet}
+\begin{syntax}
+\cs{ClistSet} \meta{comma list} \verb|{|\meta{item_1},\ldots{},\meta{item_n}\verb|}|
+\end{syntax}
+Sets \meta{comma list} to contain the \meta{items},
+removing any previous content from the variable.
+Blank items are omitted, spaces are removed from both sides of each
+item, then a set of braces is removed if the resulting space-trimmed
+item is braced.
+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|}|.
+\end{function}
+
+\begin{function}{\ClistSetEq}
+\begin{syntax}
+\cs{ClistSetEq} \meta{comma list_1} \meta{comma list_2}
+\end{syntax}
+Sets the content of \meta{comma list_1} equal to that of
+\meta{comma list_2}.  To set a token list variable equal to a comma
+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.
+\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}{\ClistClear}
+\begin{syntax}
+\cs{ClistClear} \meta{comma list}
+\end{syntax}
+Clears all items from the \meta{comma list}.
+\end{function}
+
+\begin{function}{\ClistClearNew}
+\begin{syntax}
+\cs{ClistClearNew} \meta{comma list}
+\end{syntax}
+Ensures that the \meta{comma list} exists globally by applying
+\cs{ClistNew} if necessary, then applies \cs{ClistClear} to leave
+the list empty.
+\end{function}
+
+\begin{function}{\ClistConcat}
+\begin{syntax}
+\cs{ClistConcat} \meta{comma list_1} \meta{comma list_2} \meta{comma list_3}
+\end{syntax}
+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.
+\end{function}
+
+\begin{function}{\ClistPutLeft}
+\begin{syntax}
+\cs{ClistPutLeft} \meta{comma list} \verb|{|\meta{item_1},\ldots{},\meta{item_n}\verb|}|
+\end{syntax}
+Appends the \meta{items} to the left of the \meta{comma list}.
+Blank items are omitted, spaces are removed from both sides of each
+item, then a set of braces is removed if the resulting space-trimmed
+item is braced.
+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|}|.
+\end{function}
+ 
+\begin{function}{\ClistPutRight}
+\begin{syntax}
+\cs{ClistPutRight} \meta{comma list} \verb|{|\meta{item_1},\ldots{},\meta{item_n}\verb|}|
+\end{syntax}
+Appends the \meta{items} to the right of the \meta{comma list}.
+Blank items are omitted, spaces are removed from both sides of each
+item, then a set of braces is removed if the resulting space-trimmed
+item is braced.
+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|}|.
+\end{function}
+ 
+\section{Modifying Comma Lists}
+ 
+While comma lists are normally used as ordered lists, it may be
+necessary to modify the content. The functions here may be used
+to update comma lists, while retaining the order of the unaffected
+entries.
+ 
+\begin{function}{\ClistRemoveDuplicates}
+\begin{syntax}
+\cs{ClistRemoveDuplicates} \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}
+\end{function}
+ 
+\begin{function}{\ClistRemoveAll}
+\begin{syntax}
+\cs{ClistRemoveAll} \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}
+\end{function}
+ 
+\begin{function}{\ClistReverse}
+\begin{syntax}
+\cs{ClistReverse} \meta{comma list}
+\end{syntax}
+Reverses the order of items stored in the \meta{comma list}.
+\end{function}
+ 
+%\begin{function}{\ClistSort}
+%\begin{syntax}
+%\cs{ClistSort} \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
+%\meta{clist var}. The details of sorting comparison are
+%described in Section \ref{sec:l3sort:mech}.
+%\end{function}
+
+\section{Working with the Contents of Comma Lists}
+
+\begin{function}{\ClistCount,\ClistVarCount}
+\begin{syntax}
+\cs{ClistCount} \Arg{comma list}
+\cs{ClistVarCount} \meta{comma list}
+\end{syntax}
+Returns the number of items in the \meta{comma list}
+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.
+\end{function}
+
+\begin{function}{\ClistItem}
+\begin{syntax}
+\cs{ClistItem} \Arg{comma list} \Arg{integer expression}
+\end{syntax}
+Indexing items in the \meta{comma list} from $1$ at the top (left), this
+function evaluates the \meta{integer expression} and returns the
+appropriate item from the comma list. If the
+\meta{integer expression} is negative, indexing occurs from the
+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{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}{\ClistVarItem}
+\begin{syntax}
+\cs{ClistVarItem} \meta{comma list} \Arg{integer expression}
+\end{syntax}
+Indexing items in the \meta{comma list} from $1$ at the top (left), this
+function evaluates the \meta{integer expression} and returns the
+appropriate item from the comma list. If the
+\meta{integer expression} is negative, indexing occurs from the
+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{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}{\ClistRandItem,\ClistVarRandItem}
+\begin{syntax}
+\cs{ClistRandItem} \Arg{comma list}
+\cs{ClistVarRandItem} \meta{clist var}
+\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{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{Comma Lists as Stacks}
+ 
+Comma lists can be used as stacks, where data is pushed to and popped
+from the top of the comma list. (The left of a comma list is the top, for
+performance reasons.) The stack functions for comma lists are not
+intended to be mixed with the general ordered data functions detailed
+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{syntax}
+\cs{ClistGet} \meta{comma list} \meta{token list variable}
+\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}.
+\end{function}
+ 
+\begin{function}{\ClistPop,\ClistPopT,\ClistPopF,\ClistPopTF}
+\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. 
+\end{function}
+ 
+\begin{function}{\ClistPush}
+\begin{syntax}
+\cs{ClistPush} \meta{comma list} \Arg{items}
+\end{syntax}
+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.
+\end{function}
+
+\section{Mapping over Comma Lists}
+ 
+%The functions described in this section apply a specified function
+%to each item of a comma list.
+%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.
+ 
+When the comma list is given explicitly, %as an \texttt{n}-type argument,
+spaces are trimmed around each item.
+If the result of trimming spaces is empty, the item is ignored.
+Otherwise, if the item is surrounded by braces, one set is removed,
+and the result is passed to the mapped function. Thus, if the
+comma list that is being mapped is \verb*|{a , {{b} }, ,{}, {c},}|
+then the arguments passed to the mapped function are
+`\verb*|a|', `\verb*|{b} |', an empty argument, and `\verb*|c|'.
+ 
+When the comma list is given as a variable, spaces
+have already been trimmed on input, and items are simply stripped
+of one set of braces if any. This case is more efficient than using
+explicit comma lists.
+
+%\begin{function}{\ClistMapFunction,\ClistVarMapFunction}
+%\begin{syntax}
+%\cs{ClistMapFunction} \Arg{comma list} \meta{function}
+%\cs{ClistVarMapFunction} \meta{comma list} \meta{function}
+%\end{syntax}
+%Applies \meta{function} to every \meta{item} stored in the
+%\meta{comma list}. The \meta{function} receives one argument for
+%each iteration. The \meta{items} are returned from left to right.
+%The function \cs{ClistMapInline} is in general more efficient
+%than \cs{ClistMapFunction}.
+%\end{function}
+
+\begin{function}{\ClistMapInline,\ClistVarMapInline}
+\begin{syntax}
+\cs{ClistMapInline} \Arg{comma list} \Arg{inline function}
+\cs{ClistVarMapInline} \meta{comma list} \Arg{inline function}
+\end{syntax}
+Applies \meta{inline function} to every \meta{item} stored
+within the \meta{comma list}. The \meta{inline function} should
+consist of code which receives the \meta{item} as \verb|#1|.
+The \meta{items} are returned from left to right.
+For example
+\begin{codehigh}
+\IgnoreSpacesOn
+\TlClear \lTmpaTl
+\ClistMapInline {one,two,three} {
+  \TlPutRight \lTmpaTl {(#1)}
+}
+\Result {\TlUse\lTmpaTl}
+\IgnoreSpacesOff
+\end{codehigh}
+produces (one)(two)(three).
+\end{function}
+
+\begin{function}{\ClistMapVariable,\ClistVarMapVariable}
+\begin{syntax}
+\cs{ClistMapVariable} \Arg{comma list} \meta{variable} \Arg{code}
+\cs{ClistVarMapVariable} \meta{comma list} \meta{variable} \Arg{code}
+\end{syntax}
+Stores each \meta{item} of the \meta{comma list} 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{comma
+list}, or its original value if there were no \meta{item}.  The
+\meta{items} are returned from left to right.
+\end{function}
+ 
+%\begin{function}{\ClistMapTokens,\ClistVarMapTokens}
+%\begin{syntax}
+%\cs{ClistMapTokens} \Arg{comma list} \Arg{code}
+%\cs{ClistVarMapTokens} \meta{clist var} \Arg{code}
+%\end{syntax}
+%Calls \meta{code} \Arg{item} for every \meta{item} stored in the
+%\meta{comma list}. The \meta{code} receives each \meta{item} as a
+%trailing brace group.  If the \meta{code} consists of a single
+%function this is equivalent to \cs{ClistMapFunction} or \cs{ClistVarMapFunction}.
+%\end{function}
+ 
+%\begin{function}{\ClistMapBreak}
+%\begin{syntax}
+%\cs{ClistMapBreak}
+%\end{syntax}
+%Used to terminate a clist map function before all
+%entries in the \meta{comma list} have been processed. This
+%normally takes place within a conditional statement, for example
+%\begin{verbatim}
+%\clist_map_inline:Nn \l_my_clist
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \clist_map_break: }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a clist 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}{\ClistMapBreakDo}
+%\begin{syntax}
+%\cs{ClistMapBreakDo} \Arg{code}
+%\end{syntax}
+%Used to terminate a clist map  function before all
+%entries in the \meta{comma 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}
+%\clist_map_inline:Nn \l_my_clist
+%{
+%\str_if_eq:nnTF { #1 } { bingo }
+%{ \clist_map_break:n { <code> } }
+%{
+%Do something useful
+%}
+%}
+%\end{verbatim}
+%Use outside of a clist 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{Comma List Conditionals}
+
+\begin{function}{\ClistIfExist,\ClistIfExistTF}
+\begin{syntax}
+\cs{ClistIfExist} \meta{comma list}
+\cs{ClistIfExistTF} \meta{comma list} \Arg{true code} \Arg{false code}
+\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.
+\end{function}
+
+\begin{function}{\ClistIfEmpty,\ClistIfEmptyTF}
+\begin{syntax}
+\cs{ClistIfEmpty} \Arg{comma list}
+\cs{ClistIfEmptyTF} \Arg{comma list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{comma list} is empty (containing no items).
+The rules for space trimming are as for other \texttt{n}-type
+comma-list functions, hence the comma list \verb|{ , ,, }| (without
+outer braces) is empty, while \verb|{ ,{},}| (without outer braces)
+contains one element, which happens to be empty: the comma-list
+is not empty.
+\end{function}
+
+\begin{function}{\ClistVarIfEmpty,\ClistVarIfEmptyTF}
+\begin{syntax}
+\cs{ClistVarIfEmpty} \meta{comma list}
+\cs{ClistVarIfEmptyTF} \meta{comma list} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{comma list} is empty (containing no items).
+\end{function}
+ 
+\begin{function}{\ClistIfIn,\ClistIfInTF}
+\begin{syntax}
+\cs{ClistIfIn} \Arg{comma list} \Arg{item}
+\cs{ClistIfInTF} \Arg{comma list} \Arg{item} \Arg{true code} \Arg{false code}
+\end{syntax}
+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. For example
+\begin{demohigh}
+\ClistIfInTF { a , {b}  , {b} , c } {b} {Yes} {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).
+%\end{texnote}
+\end{function}
+
+\begin{function}{\ClistVarIfIn,\ClistVarIfInTF}
+\begin{syntax}
+\cs{ClistVarIfIn} \meta{comma list} \Arg{item}
+\cs{ClistVarIfInTF} \meta{comma list} \Arg{item} \Arg{true code} \Arg{false code}
+\end{syntax}
+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{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}
+
 \chapter{The Source Code}
 
 %\CodeHigh{lite}
@@ -991,4 +4363,3 @@
 \dochighinput[language=latex/latex3]{functional.sty}
 
 \end{document}
-

Modified: trunk/Master/texmf-dist/tex/latex/functional/functional.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/functional/functional.sty	2022-03-19 20:00:30 UTC (rev 62803)
+++ trunk/Master/texmf-dist/tex/latex/functional/functional.sty	2022-03-19 20:01:01 UTC (rev 62804)
@@ -1,22 +1,24 @@
 %%% -*- coding: utf-8 -*-
 %% ----------------------------------------------------------------------------
-%% Functional: LaTeX2 functional interfaces to LaTeX3 programming layer
+%% Functional: LaTeX2 functional interfaces for LaTeX3 programming layer
 %% Copyright : 2022 (c) Jianrui Lyu <tolvjr at 163.com>
 %% Repository: https://github.com/lvjr/functional
+%% Repository: https://bitbucket.org/lvjr/functional
 %% License   : The LaTeX Project Public License 1.3c
 %% ----------------------------------------------------------------------------
 
 %%% --------------------------------------------------------
-%%> \section{Interfaces for Function Definitions (l3basics)}
+%%> \section{Interfaces for Functional Programming (Prg)}
 %%% --------------------------------------------------------
 
 \NeedsTeXFormat{LaTeX2e}[2018-04-01]
 
 \RequirePackage{expl3}
-\ProvidesExplPackage{functional}{2022-03-10}{2022A}
-  {^^JLaTeX2 functional interfaces to LaTeX3 programming layer}
+\ProvidesExplPackage{functional}{2022-03-19}{2022B}
+  {^^JLaTeX2 functional interfaces for LaTeX3 programming layer}
 
 \cs_generate_variant:Nn \iow_log:n { V }
+\cs_generate_variant:Nn \tl_log:n { e }
 \cs_generate_variant:Nn \tl_set:Nn { Ne }
 
 \tl_new:N \gResultTl
@@ -51,16 +53,6 @@
 \tl_const:Nn \c__fun_parameter_called_vii_tl  { {#7} }
 \tl_const:Nn \c__fun_parameter_called_viii_tl { {#8} }
 \tl_const:Nn \c__fun_parameter_called_ix_tl   { {#9} }
-\tl_new:N \l__fun_argument_tl
-\tl_new:N \l__fun_argument_i_tl
-\tl_new:N \l__fun_argument_ii_tl
-\tl_new:N \l__fun_argument_iii_tl
-\tl_new:N \l__fun_argument_iv_tl
-\tl_new:N \l__fun_argument_v_tl
-\tl_new:N \l__fun_argument_vi_tl
-\tl_new:N \l__fun_argument_vii_tl
-\tl_new:N \l__fun_argument_viii_tl
-\tl_new:N \l__fun_argument_ix_tl
 
 %% #1: function name; #2: argument specification; #3 function body
 \cs_new_protected:Npn \__fun_new_function:Nnn #1 #2 #3
@@ -113,6 +105,8 @@
 
 \cs_set_eq:NN \PrgNewConditional \__fun_new_conditional:Nnn
 
+\int_new:N \g__fun_nesting_level_int
+
 %% #1: function name; #2: argument specifications; #3 parameters tl defined
 %% Some times we need to create a function without arguments
 \cs_new_protected:Npn \__fun_new_with_arg_:Nnn #1 #2 #3
@@ -119,7 +113,10 @@
   {
     \cs_new_protected:Npn #1 #3
       {
+        \int_gincr:N \g__fun_nesting_level_int
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_:Nnn { NnV }
@@ -129,8 +126,11 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl { ##1 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_i:Nnn { NnV }
@@ -140,9 +140,12 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl  { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl { ##2 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_ii:Nnn { NnV }
@@ -152,10 +155,13 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_iii:Nnn { NnV }
@@ -165,11 +171,14 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_iv:Nnn { NnV }
@@ -179,12 +188,15 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
-        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
+        \__fun_one_argument_gset:nn { 5 } { ##5 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_v:Nnn { NnV }
@@ -194,13 +206,16 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
-        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
-        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
+        \__fun_one_argument_gset:nn { 5 } { ##5 }
+        \__fun_one_argument_gset:nn { 6 } { ##6 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_vi:Nnn { NnV }
@@ -210,14 +225,17 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
-        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
-        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
-        \tl_set:Nn \l__fun_argument_vii_tl { ##7 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
+        \__fun_one_argument_gset:nn { 5 } { ##5 }
+        \__fun_one_argument_gset:nn { 6 } { ##6 }
+        \__fun_one_argument_gset:nn { 7 } { ##7 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_vii:Nnn { NnV }
@@ -227,15 +245,18 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
-        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
-        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
-        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
-        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
+        \__fun_one_argument_gset:nn { 5 } { ##5 }
+        \__fun_one_argument_gset:nn { 6 } { ##6 }
+        \__fun_one_argument_gset:nn { 7 } { ##7 }
+        \__fun_one_argument_gset:nn { 8 } { ##8 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_viii:Nnn { NnV }
@@ -245,39 +266,39 @@
   {
     \cs_new_protected:Npn #1 #3
       {
-        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
-        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
-        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
-        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
-        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
-        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
-        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
-        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
-        \tl_set:Nn \l__fun_argument_ix_tl   { ##9 }
+        \int_gincr:N \g__fun_nesting_level_int
+        \__fun_one_argument_gset:nn { 1 } { ##1 }
+        \__fun_one_argument_gset:nn { 2 } { ##2 }
+        \__fun_one_argument_gset:nn { 3 } { ##3 }
+        \__fun_one_argument_gset:nn { 4 } { ##4 }
+        \__fun_one_argument_gset:nn { 5 } { ##5 }
+        \__fun_one_argument_gset:nn { 6 } { ##6 }
+        \__fun_one_argument_gset:nn { 7 } { ##7 }
+        \__fun_one_argument_gset:nn { 8 } { ##8 }
+        \__fun_one_argument_gset:nn { 9 } { ##9 }
         \__fun_evaluate:Nn #1 {#2}
+        \int_gdecr:N \g__fun_nesting_level_int
+        \__fun_return_result:
       }
   }
 \cs_generate_variant:Nn \__fun_new_with_arg_ix:Nnn { NnV }
 
-\int_new:N \g__fun_nesting_level_int
-\int_new:N \l__fun_argtype_number_int
 \tl_new:N \l__fun_argtype_tl
 \tl_const:Nn \c__fun_argtype_m_tl { m }
 \tl_const:Nn \c__fun_argtype_M_tl { M }
 \tl_const:Nn \c__fun_argtype_n_tl { n }
 \tl_const:Nn \c__fun_argtype_N_tl { N }
+\tl_new:N \l__fun_argument_tl
 
 %% #1: function name; #2: argument specifications
 \cs_new_protected:Npn \__fun_evaluate:Nn #1 #2
   {
-    \int_zero:N \l__fun_argtype_number_int
-    \int_gincr:N \g__fun_nesting_level_int
+    \__fun_argtype_index_gzero:
     \__fun_arguments_gclear:
     \tl_map_variable:nNn { #2 } \l__fun_argtype_tl % spaces are ignored
       {
-        \int_incr:N \l__fun_argtype_number_int
-        \tl_set_eq:Nc \l__fun_argument_tl
-          { l__fun_argument_ \int_to_roman:n { \l__fun_argtype_number_int } _tl }
+        \__fun_argtype_index_gincr:
+        \__fun_one_argument_get:eN { \__fun_argtype_index_use: } \l__fun_argument_tl
         \tl_case:Nn \l__fun_argtype_tl
           {
             \c__fun_argtype_m_tl
@@ -300,19 +321,14 @@
       }
     \__fun_arguments_log:N #1
     \__fun_arguments_called:c { __fun_defined_ \cs_to_str:N #1 : w }
-    \int_gdecr:N \g__fun_nesting_level_int
-    \__fun_return_result:
   }
 
-\cs_set_eq:NN \__fun_cs_temp:w \scan_stop:
-
 \cs_new_protected:Npn \__fun_evaluate_and_put_argument:N #1
   {
-    \cs_set_eq:Nc \__fun_cs_temp:w
+    \cs_if_exist:cTF
       {
         __fun_defined_ \exp_last_unbraced:Ne \cs_to_str:N { \tl_head:N #1 } : w
       }
-    \cs_if_exist:NTF \__fun_cs_temp:w
       {
         #1
         \__fun_arguments_gput:e { { \exp_not:V \gResultTl } }
@@ -322,6 +338,57 @@
       }
   }
 
+%% #1: argument number; #2: token lists
+\cs_new_protected:Npn \__fun_one_argument_gset:nn #1 #2
+  {
+    \tl_gset:cn
+      { g__fun_one_argument_ \int_use:N \g__fun_nesting_level_int _#1_tl } { #2 }
+    %\__fun_one_argument_log:nn { #1 } { set }
+  }
+
+%% #1: argument number; #2: variable of token lists
+\cs_new_protected:Npn \__fun_one_argument_get:nN #1 #2
+  {
+    \tl_set_eq:Nc
+      #2 { g__fun_one_argument_ \int_use:N \g__fun_nesting_level_int _ #1 _tl }
+    %\__fun_one_argument_log:nn { #1 } { get }
+  }
+\cs_generate_variant:Nn \__fun_one_argument_get:nN { eN }
+
+%% #1: argument number; #2: get or set
+\cs_new_protected:Npn \__fun_one_argument_log:nn #1 #2
+  {
+    \tl_log:e
+      {
+        #2 ~ level _ \int_use:N \g__fun_nesting_level_int _ arg _ #1 ~ = ~
+        \exp_not:v
+          { g__fun_one_argument_ \int_use:N \g__fun_nesting_level_int _#1_tl }
+      }
+  }
+
+\int_new:c  { g__fun_argtype_index_ 1 _int }
+\int_new:c  { g__fun_argtype_index_ 2 _int }
+\int_new:c  { g__fun_argtype_index_ 3 _int }
+\int_new:c  { g__fun_argtype_index_ 4 _int }
+\int_new:c  { g__fun_argtype_index_ 5 _int }
+
+\cs_new_protected:Npn \__fun_argtype_index_gzero:
+  {
+    \int_gzero_new:c
+      { g__fun_argtype_index_ \int_use:N \g__fun_nesting_level_int _int }
+  }
+
+\cs_new_protected:Npn \__fun_argtype_index_gincr:
+  {
+    \int_gincr:c
+      { g__fun_argtype_index_ \int_use:N \g__fun_nesting_level_int _int }
+  }
+
+\cs_new:Npn \__fun_argtype_index_use:
+  {
+    \int_use:c { g__fun_argtype_index_ \int_use:N \g__fun_nesting_level_int _int }
+  }
+
 \cs_new_protected:Npn \__fun_arguments_called:N #1
   {
     \exp_last_unbraced:Nv
@@ -350,6 +417,12 @@
   }
 \cs_generate_variant:Nn \__fun_arguments_gput:n { e }
 
+\cs_set_eq:NN \Break \prg_break:
+\cs_set_eq:NN \PrgBreak \prg_break:
+
+\cs_set_eq:NN \BreakDo \prg_break:n
+\cs_set_eq:NN \PrgBreakDo \prg_break:n
+
 \cs_new_protected:Npn \__fun_put_result:n #1
   {
     \tl_gput_right:Nn \gResultTl { #1 }
@@ -361,27 +434,6 @@
     \__fun_put_result:n { #1 }
   }
 
-\PrgNewFunction \Name { m }
-  {
-    \exp_args:Nc \__fun_put_result:n { #1 }
-  }
-\cs_set_eq:NN \UseName \Name
-
-\PrgNewFunction \Expand { m }
-  {
-    \__fun_put_result:e { #1 }
-  }
-\cs_set_eq:NN \UseExpand \Expand
-
-\PrgNewFunction \Value { M }
-  {
-    \__fun_put_result:V #1
-  }
-\cs_set_eq:NN \UseValue \Value
-
-\cs_set_eq:NN \ExpNot \exp_not:n
-\cs_set_eq:NN \ExpValue \exp_not:V
-
 \cs_new_protected:Npn \__fun_return_result:
   {
     \int_compare:nNnT { \g__fun_nesting_level_int } = { 0 }
@@ -484,28 +536,50 @@
 
 \Functional { scoping = false, tracing = false }
 
-\PrgNewFunction \UseOne { n }
+\cs_new_protected:Npn \__fun_ignore_spaces_on:
   {
-    \Result { #1 }
+    \ExplSyntaxOn
+    \char_set_catcode_math_subscript:N \_
+    \char_set_catcode_other:N \:
   }
+\cs_set_eq:NN \IgnoreSpacesOn \__fun_ignore_spaces_on:
+\cs_set_eq:NN \IgnoreSpacesOff \ExplSyntaxOff
 
-\PrgNewFunction \GobbleOne { n }
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Argument Using (Use)}
+%%% --------------------------------------------------------
+
+\PrgNewFunction \Name { m }
   {
-    \Result { }
+    \exp_args:Nc \__fun_put_result:n { #1 }
   }
+\cs_set_eq:NN \UseName \Name
 
-\PrgNewFunction \UseGobble { n n }
+\PrgNewFunction \Value { M }
   {
-    \UseOne { #1 }
+    \__fun_put_result:V #1
   }
+\cs_set_eq:NN \UseValue \Value
 
-\PrgNewFunction \GobbleUse { n n }
+\PrgNewFunction \Expand { m }
   {
-    \UseOne { #2 }
+    \__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
+
+\PrgNewFunction \UseOne { n } { \Result { #1 } }
+
+\PrgNewFunction \GobbleOne { n } { \Result { } }
+
+\PrgNewFunction \UseGobble { n n } { \UseOne { #1 } }
+
+\PrgNewFunction \GobbleUse { n n } { \UseOne { #2 } }
+
 %%% --------------------------------------------------------
-%%> \section{Interfaces for Control Structures (l3prg)}
+%%> \section{Interfaces for Control Structures (Bool)}
 %%% --------------------------------------------------------
 
 \bool_const:Nn \cTrueBool { \c_true_bool }
@@ -519,9 +593,15 @@
 \bool_new:N \gTmpiBool   \bool_new:N \gTmpjBool   \bool_new:N \gTmpkBool
 \bool_new:N \g at Funx@Bool \bool_new:N \g at Funy@Bool \bool_new:N \g at Funz@Bool
 
-\cs_set_eq:NN \BoolNew \bool_new:N
-\cs_set_eq:NN \BoolLog \bool_log:N
+\PrgNewFunction \BoolNew { M } { \bool_new:N #1 }
 
+\PrgNewFunction \BoolConst { M m } { \bool_const:Nn #1 { #2 } }
+
+\PrgNewFunction \BoolSet { M m } {
+  \__fun_do_assignment:Nnn #1
+    { \bool_gset:Nn #1 { #2 } } { \bool_set:Nn #1 { #2 } }
+}
+
 \PrgNewFunction \BoolSetTrue { M }
   {
     \__fun_do_assignment:Nnn #1 { \bool_gset_true:N #1 } { \bool_set_true:N #1 }
@@ -532,15 +612,59 @@
     \__fun_do_assignment:Nnn #1 { \bool_gset_false:N #1 } { \bool_set_false:N #1 }
   }
 
-\PrgNewConditional \BoolIf { N }
+\PrgNewFunction \BoolSetEq { M M }
   {
-    \Result { #1 }
+    \__fun_do_assignment:Nnn #1
+      { \bool_gset_eq:NN #1 #2 } { \bool_set_eq:NN #1 #2 }
   }
 
+\PrgNewFunction \BoolLog { m } { \bool_log:n { #1 } }
+
+\PrgNewFunction \BoolVarLog { M } { \bool_log:N #1 }
+
+\PrgNewFunction \BoolShow { m } { \bool_show:n { #1 } }
+
+\PrgNewFunction \BoolVarShow { M } { \bool_show:N #1 }
+
+\PrgNewConditional \BoolIfExist { M }
+  {
+    \bool_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \BoolVarIf { M } { \Result { #1 } }
+
+\PrgNewConditional \BoolVarNot { M }
+  {
+    \bool_if:NTF #1
+      { \Result { \cFalseBool } } { \Result { \cTrueBool } }
+  }
+
+\PrgNewConditional \BoolVarAnd { M M }
+  {
+    \bool_lazy_and:nnTF {#1} {#2}
+      { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \BoolVarOr { M M }
+  {
+    \bool_lazy_or:nnTF {#1} {#2}
+      { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \BoolVarXor { M M }
+  {
+    \bool_xor:nnTF {#1} {#2}
+      { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
 %%% --------------------------------------------------------
-%%> \section{Interfaces for Token Lists (l3tl)}
+%%> \section{Interfaces for Token Lists (Tl)}
 %%% --------------------------------------------------------
 
+\tl_set_eq:NN \cEmptyTl \c_empty_tl
+\tl_set_eq:NN \cSpaceTl \c_space_tl
+\tl_set_eq:NN \cNoValueTl \c_novalue_tl
+
 \tl_new:N \lTmpaTl   \tl_new:N \lTmpbTl   \tl_new:N \lTmpcTl
 \tl_new:N \lTmpiTl   \tl_new:N \lTmpjTl   \tl_new:N \lTmpkTl
 \tl_new:N \l at Funx@Tl \tl_new:N \l at Funy@Tl \tl_new:N \l at Funz@Tl
@@ -549,17 +673,48 @@
 \tl_new:N \gTmpiTl   \tl_new:N \gTmpjTl   \tl_new:N \gTmpkTl
 \tl_new:N \g at Funx@Tl \tl_new:N \g at Funy@Tl \tl_new:N \g at Funz@Tl
 
-\cs_set_eq:NN \TlNew \tl_new:N
-\cs_set_eq:NN \TlLog \tl_log:N
+\PrgNewFunction \TlNew { M } { \tl_new:N #1 }
 
+\PrgNewFunction \TlLog { m } { \tl_log:n { #1 } }
+
+\PrgNewFunction \TlVarLog { M } { \tl_log:N #1 }
+
+\PrgNewFunction \TlShow { m } { \tl_show:n { #1 } }
+
+\PrgNewFunction \TlVarShow { M } { \tl_show:N #1 }
+
+\PrgNewFunction \TlUse { M } { \Result { \Value #1 } }
+
+\PrgNewFunction \TlToStr { m } { \Expand { \tl_to_str:n { #1 } } }
+
+\PrgNewFunction \TlVarToStr { M } { \Expand { \tl_to_str:N #1 } }
+
+\PrgNewFunction \TlConst { M m } { \tl_const:Nn #1 { #2 } }
+
+\PrgNewFunction \TlSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \tl_gset:Nn #1 {#2} } { \tl_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1 { \tl_gset_eq:NN #1 #2 } { \tl_set_eq:NN #1 #2 }
+  }
+
+\PrgNewFunction \TlConcat { M M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \tl_gconcat:NNN #1 #2 #3 } { \tl_concat:NNN #1 #2 #3 }
+  }
+
 \PrgNewFunction \TlClear { M }
   {
     \__fun_do_assignment:Nnn #1 { \tl_gclear:N #1 } { \tl_clear:N #1 }
   }
 
-\PrgNewFunction \TlSet { M m }
+\PrgNewFunction \TlClearNew { M }
   {
-    \__fun_do_assignment:Nnn #1 { \tl_gset:Nn #1 {#2} } { \tl_set:Nn #1 {#2} }
+    \__fun_do_assignment:Nnn #1 { \tl_gclear_new:N #1 } { \tl_clear_new:N #1 }
   }
 
 \PrgNewFunction \TlPutLeft { M m }
@@ -574,29 +729,339 @@
       { \tl_gput_right:Nn #1 {#2} } { \tl_put_right:Nn #1 {#2} }
   }
 
-\PrgNewFunction \TlUse { M }
+\PrgNewFunction \TlReplaceOnce { M m m }
   {
-    \Result { \Value #1 }
+    \__fun_do_assignment:Nnn #1
+      { \tl_greplace_once:Nnn #1 {#2} {#3} } { \tl_replace_once:Nnn #1 {#2} {#3} }
   }
 
-\PrgNewConditional \TlIfEmpty { N }
+\PrgNewFunction \TlReplaceAll { M m m }
   {
-    \tl_if_empty:NTF #1
-      { \Result { \cTrueBool } }
-      { \Result { \cFalseBool } }
+    \__fun_do_assignment:Nnn #1
+      { \tl_greplace_all:Nnn #1 {#2} {#3} } { \tl_replace_all:Nnn #1 {#2} {#3} }
   }
 
-\PrgNewConditional \TlIfEq { N N }
+\PrgNewFunction \TlRemoveOnce { M m }
   {
-    \tl_if_eq:NNTF #1 #2
+    \__fun_do_assignment:Nnn #1
+      { \tl_gremove_once:Nn #1 {#2} } { \tl_remove_once:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlRemoveAll { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \tl_gremove_all:Nn #1 {#2} } { \tl_remove_all:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlTrimSpaces { m } { \Expand { \tl_trim_spaces:n { #1 } } }
+
+\PrgNewFunction \TlVarTrimSpaces { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \tl_gtrim_spaces:N #1 } { \tl_trim_spaces:N #1 }
+  }
+
+\PrgNewFunction \TlCount { m } { \Expand { \tl_count:n { #1 } } }
+
+\PrgNewFunction \TlVarCount { M } { \Expand { \tl_count:N #1 } }
+
+\PrgNewFunction \TlHead { m } { \Expand { \tl_head:n { #1 } } }
+
+\PrgNewFunction \TlVarHead { M } { \Expand { \tl_head:N #1 } }
+
+\PrgNewFunction \TlTail { m } { \Expand { \tl_tail:n { #1 } } }
+
+\PrgNewFunction \TlVarTail { M } { \Expand { \tl_tail:N #1 } }
+
+\PrgNewFunction \TlItem { m m } { \Expand { \tl_item:nn {#1} {#2} } }
+
+\PrgNewFunction \TlVarItem { M m } { \Expand { \tl_item:Nn #1 {#2} } }
+
+\PrgNewFunction \TlRandItem { m } { \Expand { \tl_rand_item:n {#1} } }
+
+\PrgNewFunction \TlVarRandItem { M } { \Expand { \tl_rand_item:N #1 } }
+
+\PrgNewFunction \TlVarCase   { M m }     { \tl_case:Nn {#1} {#2} }
+\PrgNewFunction \TlVarCaseT  { M m n }   { \tl_case:NnT {#1} {#2} {#3} }
+\PrgNewFunction \TlVarCaseF  { M m n }   { \tl_case:NnF {#1} {#2} {#3} }
+\PrgNewFunction \TlVarCaseTF { M m n n } { \tl_case:NnTF {#1} {#2} {#3} {#4} }
+
+\PrgNewFunction \TlMapInline { m n }
+  {
+    \tl_map_inline:nn {#1} {#2}
+  }
+
+\PrgNewFunction \TlVarMapInline { M n }
+  {
+    \tl_map_inline:Nn #1 {#2}
+  }
+
+\PrgNewFunction \TlMapVariable { m M n }
+  {
+    \tl_map_variable:nNn {#1} #2 {#3}
+  }
+
+\PrgNewFunction \TlVarMapVariable { M M n }
+  {
+    \tl_map_variable:NNn #1 #2 {#3}
+  }
+
+\PrgNewConditional \TlIfExist { M }
+  {
+    \tl_if_exist:NTF #1 { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfEmpty { m }
+  {
+    \tl_if_empty:nTF {#1} { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlVarIfEmpty { M }
+  {
+    \tl_if_empty:NTF #1 { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfBlank { m }
+  {
+    \tl_if_blank:nTF {#1} { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfEq { m m }
+  {
+    \tl_if_eq:nnTF {#1} {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlVarIfEq { M M }
+  {
+    \tl_if_eq:NNTF #1 #2 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfIn { m m }
+  {
+    \tl_if_in:nnTF {#1} {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlVarIfIn { M m }
+  {
+    \tl_if_in:NnTF #1 {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfSingle { m }
+  {
+    \tl_if_single:nTF {#1} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlVarIfSingle { M }
+  {
+    \tl_if_single:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Strings (Str)}
+%%% --------------------------------------------------------
+
+\str_set_eq:NN \cAmpersandStr  \c_ampersand_str
+\str_set_eq:NN \cAttignStr     \c_atsign_str
+\str_set_eq:NN \cBackslashStr  \c_backslash_str
+\str_set_eq:NN \cLeftBraceStr  \c_left_brace_str
+\str_set_eq:NN \cRightBraceStr \c_right_brace_str
+\str_set_eq:NN \cCircumflexStr \c_circumflex_str
+\str_set_eq:NN \cColonStr      \c_colon_str
+\str_set_eq:NN \cDollarStr     \c_dollar_str
+\str_set_eq:NN \cHashStr       \c_hash_str
+\str_set_eq:NN \cPercentStr    \c_percent_str
+\str_set_eq:NN \cTildeStr      \c_tilde_str
+\str_set_eq:NN \cUnderscoreStr \c_underscore_str
+\str_set_eq:NN \cZeroStr       \c_zero_str
+
+\str_new:N \lTmpaStr   \str_new:N \lTmpbStr   \str_new:N \lTmpcStr
+\str_new:N \lTmpiStr   \str_new:N \lTmpjStr   \str_new:N \lTmpkStr
+\str_new:N \l at Funx@Str \str_new:N \l at Funy@Str \str_new:N \l at Funz@Str
+
+\str_new:N \gTmpaStr   \str_new:N \gTmpbStr   \str_new:N \gTmpcStr
+\str_new:N \gTmpiStr   \str_new:N \gTmpjStr   \str_new:N \gTmpkStr
+\str_new:N \g at Funx@Str \str_new:N \g at Funy@Str \str_new:N \g at Funz@Str
+
+\PrgNewFunction \StrNew { M } { \str_new:N #1 }
+
+\PrgNewFunction \StrLog { m } { \str_log:n { #1 } }
+
+\PrgNewFunction \StrVarLog { M } { \str_log:N #1 }
+
+\PrgNewFunction \StrShow { m } { \str_show:n { #1 } }
+
+\PrgNewFunction \StrVarShow { M } { \str_show:N #1 }
+
+\PrgNewFunction \StrUse { M } { \Result { \Value #1 } }
+
+\PrgNewFunction \StrConst { M m } { \str_const:Nn #1 {#2} }
+
+\PrgNewFunction \StrSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \str_gset:Nn #1 {#2} } { \str_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \StrSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1 { \str_gset_eq:NN #1 #2 } { \str_set_eq:NN #1 #2 }
+  }
+
+\PrgNewFunction \StrConcat { M M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_gconcat:NNN #1 #2 #3 } { \str_concat:NNN #1 #2 #3 }
+  }
+
+\PrgNewFunction \StrClear { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \str_gclear:N #1 } { \str_clear:N #1 }
+  }
+
+\PrgNewFunction \StrClearNew { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \str_gclear_new:N #1 } { \str_clear_new:N #1 }
+  }
+
+\PrgNewFunction \StrPutLeft { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_gput_left:Nn #1 {#2} } { \str_put_left:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \StrPutRight { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_gput_right:Nn #1 {#2} } { \str_put_right:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \StrReplaceOnce { 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 }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_greplace_all:Nnn #1 {#2} {#3} } { \str_replace_all:Nnn #1 {#2} {#3} }
+  }
+
+\PrgNewFunction \StrRemoveOnce { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_gremove_once:Nn #1 {#2} } { \str_remove_once:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \StrRemoveAll { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \str_gremove_all:Nn #1 {#2} } { \str_remove_all:Nn #1 {#2} }
+  }
+
+%% Avoid naming confict with xstring package
+\cs_if_exist:NF \StrCount
+  { \PrgNewFunction \StrCount { m } { \Expand { \str_count:n { #1 } } } }
+
+%% Provide another name for \StrCount function
+\PrgNewFunction \StrSize { m } { \Expand { \str_count:n { #1 } } }
+
+\PrgNewFunction \StrVarCount { M } { \Expand { \str_count:N #1 } }
+
+\PrgNewFunction \StrHead { m } { \Expand { \str_head:n { #1 } } }
+
+\PrgNewFunction \StrVarHead { M } { \Expand { \str_head:N #1 } }
+
+\PrgNewFunction \StrTail { m } { \Expand { \str_tail:n { #1 } } }
+
+\PrgNewFunction \StrVarTail { M } { \Expand { \str_tail:N #1 } }
+
+\PrgNewFunction \StrItem { m m } { \Expand { \str_item:nn {#1} {#2} } }
+
+\PrgNewFunction \StrVarItem { M m } { \Expand { \str_item:Nn #1 {#2} } }
+
+\PrgNewFunction \StrCase   { m m }     { \str_case:nn {#1} {#2} }
+\PrgNewFunction \StrCaseT  { m m n }   { \str_case:nnT {#1} {#2} {#3} }
+\PrgNewFunction \StrCaseF  { m m n }   { \str_case:nnF {#1} {#2} {#3} }
+\PrgNewFunction \StrCaseTF { m m n n } { \str_case:nnTF {#1} {#2} {#3} {#4} }
+
+\PrgNewFunction \StrMapInline { m n }
+  {
+    \str_map_inline:nn {#1} {#2}
+  }
+
+\PrgNewFunction \StrVarMapInline { M n }
+  {
+    \str_map_inline:Nn #1 {#2}
+  }
+
+\PrgNewFunction \StrMapVariable { m M n }
+  {
+    \str_map_variable:nNn {#1} #2 {#3}
+  }
+
+\PrgNewFunction \StrVarMapVariable { M M n }
+  {
+    \str_map_variable:NNn #1 #2 {#3}
+  }
+
+\PrgNewConditional \StrIfExist { M }
+  {
+    \str_if_exist:NTF #1 { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \StrVarIfEmpty { M }
+  {
+    \str_if_empty:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \StrIfEq { m m }
+  {
+    \str_if_eq:nnTF {#1} {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \StrVarIfEq { M M }
+  {
+    \str_if_eq:NNTF #1 #2 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \StrIfIn { m m }
+  {
+    \str_if_in:nnTF {#1} {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \StrVarIfIn { M m }
+  {
+    \str_if_in:NnTF #1 {#2} { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+%% Avoid naming confict with xstring package
+\cs_if_exist:NF \StrCompare
+  {
+    \PrgNewConditional \StrCompare { m N m }
+      {
+        \str_compare:nNnTF {#1} #2 {#3}
+          { \Result { \cTrueBool } }
+          { \Result { \cFalseBool } }
+      }
+  }
+
+%% Provide another name for \StrCompare function
+\PrgNewConditional \StrIfCompare { m N m }
+  {
+    \str_compare:nNnTF {#1} #2 {#3}
       { \Result { \cTrueBool } }
       { \Result { \cFalseBool } }
   }
 
 %%% --------------------------------------------------------
-%%> \section{Interfaces for Integers (l3int)}
+%%> \section{Interfaces for Integers (Int)}
 %%% --------------------------------------------------------
 
+\cs_set_eq:NN \cZeroInt        \c_zero_int
+\cs_set_eq:NN \cOneInt         \c_one_int
+\cs_set_eq:NN \cMaxInt         \c_max_int
+\cs_set_eq:NN \cMaxRegisterInt \c_max_register_int
+\cs_set_eq:NN \cMaxCharInt     \c_max_char_in
+
 \int_new:N \lTmpaInt   \int_new:N \lTmpbInt   \int_new:N \lTmpcInt
 \int_new:N \lTmpiInt   \int_new:N \lTmpjInt   \int_new:N \lTmpkInt
 \int_new:N \l at Funx@Int \int_new:N \l at Funy@Int \int_new:N \l at Funz@Int
@@ -605,14 +1070,85 @@
 \int_new:N \gTmpiInt   \int_new:N \gTmpjInt   \int_new:N \gTmpkInt
 \int_new:N \g at Funx@Int \int_new:N \g at Funy@Int \int_new:N \g at Funz@Int
 
-\cs_set_eq:NN \IntNew \int_new:N
-\cs_set_eq:NN \IntLog \int_log:N
+\PrgNewFunction \IntEval { m }
+  {
+    \Result { \Expand { \int_eval:n { #1 } } }
+  }
 
+\PrgNewFunction \IntMathAdd { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { (#1) + (#2) } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathSub { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { (#1) - (#2) } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathMult { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { (#1) * (#2) } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathDiv { m m }
+  {
+    \Expand { \int_div_round:nn { #1 } { #2 } }
+  }
+
+\PrgNewFunction \IntMathDivTruncate { m m }
+  {
+    \Expand { \int_div_truncate:nn { #1 } { #2 } }
+  }
+
+\PrgNewFunction \IntMathSign { m } { \Expand { \int_sign:n { #1 } } }
+
+\PrgNewFunction \IntMathAbs { m } { \Expand { \int_abs:n { #1 } } }
+
+\PrgNewFunction \IntMathMax { m m } { \Expand { \int_max:nn { #1 } { #2 } } }
+
+\PrgNewFunction \IntMathMin { m m } { \Expand { \int_min:nn { #1 } { #2 } } }
+
+\PrgNewFunction \IntMathMod { m m } { \Expand { \int_mod:nn { #1 } { #2 } } }
+
+\PrgNewFunction \IntMathRand { m m } { \Expand { \int_rand:nn { #1 } { #2 } } }
+
+\PrgNewFunction \IntNew { M } { \int_new:N #1 }
+
+\PrgNewFunction \IntConst { M m } { \int_const:Nn #1 { #2 } }
+
+\PrgNewFunction \IntLog { m } { \int_log:n { #1 } }
+
+\PrgNewFunction \IntVarLog { M } { \int_log:N #1 }
+
+\PrgNewFunction \IntShow { m } { \int_show:n { #1 } }
+
+\PrgNewFunction \IntVarShow { M } { \int_show:N #1 }
+
+\PrgNewFunction \IntUse { M } { \Result { \Value #1 } }
+
+\PrgNewFunction \IntSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gset:Nn #1 {#2} } { \int_set:Nn #1 {#2} }
+  }
+
 \PrgNewFunction \IntZero { M }
   {
     \__fun_do_assignment:Nnn #1 { \int_gzero:N #1 } { \int_zero:N #1 }
   }
 
+\PrgNewFunction \IntZeroNew { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gzero_new:N #1 } { \int_zero_new:N #1 }
+  }
+
+\PrgNewFunction \IntSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gset_eq:NN #1 #2 } { \int_set_eq:NN #1 #2 }
+  }
+
 \PrgNewFunction \IntIncr { M }
   {
     \__fun_do_assignment:Nnn #1 { \int_gincr:N #1 } { \int_incr:N #1 }
@@ -623,11 +1159,6 @@
     \__fun_do_assignment:Nnn #1 { \int_gdecr:N #1 } { \int_decr:N #1 }
   }
 
-\PrgNewFunction \IntSet { M m }
-  {
-    \__fun_do_assignment:Nnn #1 { \int_gset:Nn #1 {#2} } { \int_set:Nn #1 {#2} }
-  }
-
 \PrgNewFunction \IntAdd { M m }
   {
     \__fun_do_assignment:Nnn #1 { \int_gadd:Nn #1 {#2} } { \int_add:Nn #1 {#2} }
@@ -638,49 +1169,524 @@
     \__fun_do_assignment:Nnn #1 { \int_gsub:Nn #1 {#2} } { \int_sub:Nn #1 {#2} }
   }
 
-\PrgNewFunction \IntUse { M }
+\PrgNewFunction \IntStepInline { m m m n }
   {
-    \Result { \Value #1 }
+    \int_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
   }
 
-\PrgNewFunction \IntEval { m }
+\PrgNewFunction \IntStepVariable { m m m M n }
   {
-    \Result { \Expand { \int_eval:n { #1 } } }
+    \int_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
   }
 
-\PrgNewFunction \IntMathAdd { m m }
+\PrgNewConditional \IntIfExist { M }
   {
-    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 + #2 } }
-    \Result { \Value \l at Funx@Int }
+    \int_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
   }
 
-\PrgNewFunction \IntMathSub { m m }
+\PrgNewConditional \IntIfOdd { m }
   {
-    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 - #2 } }
-    \Result { \Value \l at Funx@Int }
+    \int_if_odd:nTF { #1 } { \Result { \cTrueBool } } { \Result { \cFalseBool } }
   }
 
-\PrgNewFunction \IntMathMult { m m }
+\PrgNewConditional \IntIfEven { m }
   {
-    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 * #2 } }
-    \Result { \Value \l at Funx@Int }
+    \int_if_even:nTF { #1 } { \Result { \cTrueBool } } { \Result { \cFalseBool } }
   }
 
-\PrgNewFunction \IntMathDiv { m m }
+\PrgNewConditional \IntCompare { m N m }
   {
-    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 / #2 } }
-    \Result { \Value \l at Funx@Int }
+    \int_compare:nNnTF {#1} #2 {#3}
+      { \Result { \cTrueBool } }
+      { \Result { \cFalseBool } }
   }
 
-\PrgNewFunction \IntStepVariable { m m m M n }
+\PrgNewFunction \IntCase   { m m }     { \int_case:nn {#1} {#2} }
+\PrgNewFunction \IntCaseT  { m m n }   { \int_case:nnT {#1} {#2} {#3} }
+\PrgNewFunction \IntCaseF  { m m n }   { \int_case:nnF {#1} {#2} {#3} }
+\PrgNewFunction \IntCaseTF { m m n n } { \int_case:nnTF {#1} {#2} {#3} {#4} }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Floating Point Numbers (Fp)}
+%%% --------------------------------------------------------
+
+\fp_set_eq:NN \cZeroFp      \c_zero_fp
+\fp_set_eq:NN \cMinusZeroFp \c_minus_zero_fp
+\fp_set_eq:NN \cOneFp       \c_one_fp
+\fp_set_eq:NN \cInfFp       \c_inf_fp
+\fp_set_eq:NN \cMinusInfFp  \c_minus_inf_fp
+\fp_set_eq:NN \cEFp         \c_e_fp
+\fp_set_eq:NN \cPiFp        \c_pi_fp
+\fp_set_eq:NN \cOneDegreeFp \c_one_degree_fp
+
+\fp_new:N \lTmpaFp   \fp_new:N \lTmpbFp   \fp_new:N \lTmpcFp
+\fp_new:N \lTmpiFp   \fp_new:N \lTmpjFp   \fp_new:N \lTmpkFp
+\fp_new:N \l at Funx@Fp \fp_new:N \l at Funy@Fp \fp_new:N \l at Funz@Fp
+
+\fp_new:N \gTmpaFp   \fp_new:N \gTmpbFp   \fp_new:N \gTmpcFp
+\fp_new:N \gTmpiFp   \fp_new:N \gTmpjFp   \fp_new:N \gTmpkFp
+\fp_new:N \g at Funx@Fp \fp_new:N \g at Funy@Fp \fp_new:N \g at Funz@Fp
+
+\PrgNewFunction \FpEval { m }
   {
-    \int_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
+    \Result { \Expand { \fp_eval:n { #1 } } }
   }
 
-\PrgNewConditional \IntCompare { m N m }
+\PrgNewFunction \FpMathAdd { m m }
   {
-    \int_compare:nNnTF {#1} #2 {#3}
+    \fp_set:Nn \l at Funx@Fp { \fp_eval:n { (#1) + (#2) } }
+    \Result { \FpUse \l at Funx@Fp }
+  }
+
+\PrgNewFunction \FpMathSub { m m }
+  {
+    \fp_set:Nn \l at Funx@Fp { \fp_eval:n { (#1) - (#2) } }
+    \Result { \FpUse \l at Funx@Fp }
+  }
+
+\PrgNewFunction \FpMathMult { m m }
+  {
+    \fp_set:Nn \l at Funx@Fp { \fp_eval:n { (#1) * (#2) } }
+    \Result { \FpUse \l at Funx@Fp }
+  }
+
+\PrgNewFunction \FpMathDiv { m m }
+  {
+    \fp_set:Nn \l at Funx@Fp { \fp_eval:n { (#1) / (#2) } }
+    \Result { \FpUse \l at Funx@Fp }
+  }
+
+\PrgNewFunction \FpMathSign { m }
+  {
+    \Result { \Expand { \fp_sign:n { #1 } } }
+  }
+
+\PrgNewFunction \FpMathAbs { m }
+  {
+    \Result { \Expand { \fp_abs:n { #1 } } }
+  }
+
+\PrgNewFunction \FpMathMax { m m }
+  {
+    \Result { \Expand { \fp_max:nn { #1 } { #2 } } }
+  }
+
+\PrgNewFunction \FpMathMin { m m }
+  {
+    \Result { \Expand { \fp_min:nn { #1 } { #2 } } }
+  }
+
+\PrgNewFunction \FpNew { M } { \fp_new:N #1 }
+
+\PrgNewFunction \FpConst { M m } { \fp_const:Nn #1 {#2} }
+
+\PrgNewFunction \FpUse { M } { \Result { \Expand { \fp_use:N #1 } } }
+
+\PrgNewFunction \FpLog { m } { \fp_log:n { #1 } }
+
+\PrgNewFunction \FpVarLog { M } { \fp_log:N #1 }
+
+\PrgNewFunction \FpShow { m } { \fp_show:n { #1 } }
+
+\PrgNewFunction \FpVarShow { M } { \fp_show:N #1 }
+
+\PrgNewFunction \FpSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gset:Nn #1 {#2} } { \fp_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \FpSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gset_eq:NN #1 #2 } { \fp_set_eq:NN #1 #2 }
+  }
+
+\PrgNewFunction \FpZero { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gzero:N #1 } { \fp_zero:N #1 }
+  }
+
+\PrgNewFunction \FpZeroNew { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gzero_new:N #1 } { \fp_zero_new:N #1 }
+  }
+
+\PrgNewFunction \FpAdd { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gadd:Nn #1 {#2} } { \fp_add:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \FpSub { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \fp_gsub:Nn #1 {#2} } { \fp_sub:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \FpStepInline { m m m n }
+  {
+    \fp_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
+  }
+
+\PrgNewFunction \FpStepVariable { m m m M n }
+  {
+    \fp_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
+  }
+
+\PrgNewConditional \FpIfExist { M }
+  {
+    \fp_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \FpCompare { m N m }
+  {
+    \fp_compare:nNnTF {#1} #2 {#3}
       { \Result { \cTrueBool } }
       { \Result { \cFalseBool } }
   }
 
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Dimensions (Dim)}
+%%% --------------------------------------------------------
+
+\cs_set_eq:NN \cMaxDim  \c_max_dim
+\cs_set_eq:NN \cZeroDim \c_zero_dim
+
+\dim_new:N \lTmpaDim   \dim_new:N \lTmpbDim   \dim_new:N \lTmpcDim
+\dim_new:N \lTmpiDim   \dim_new:N \lTmpjDim   \dim_new:N \lTmpkDim
+\dim_new:N \l at Funx@Dim \dim_new:N \l at Funy@Dim \dim_new:N \l at Funz@Dim
+
+\dim_new:N \gTmpaDim   \dim_new:N \gTmpbDim   \dim_new:N \gTmpcDim
+\dim_new:N \gTmpiDim   \dim_new:N \gTmpjDim   \dim_new:N \gTmpkDim
+\dim_new:N \g at Funx@Dim \dim_new:N \g at Funy@Dim \dim_new:N \g at Funz@Dim
+
+\PrgNewFunction \DimEval { m }
+  {
+    \Result { \Expand { \dim_eval:n { #1 } } }
+  }
+
+\PrgNewFunction \DimMathAdd { m m }
+  {
+    \dim_set:Nn \l at Funx@Dim { \dim_eval:n { (#1) + (#2) } }
+    \Result { \Value \l at Funx@Dim }
+  }
+
+\PrgNewFunction \DimMathSub { m m }
+  {
+    \dim_set:Nn \l at Funx@Dim { \dim_eval:n { (#1) - (#2) } }
+    \Result { \Value \l at Funx@Dim }
+  }
+
+\PrgNewFunction \DimMathSign { m }
+  {
+    \Result { \Expand { \dim_sign:n { #1 } } }
+  }
+
+\PrgNewFunction \DimMathAbs { m }
+  {
+    \Result { \Expand { \dim_abs:n { #1 } } }
+  }
+
+\PrgNewFunction \DimMathMax { m m }
+  {
+    \Result { \Expand { \dim_max:nn { #1 } { #2 } } }
+  }
+
+\PrgNewFunction \DimMathMin { m m }
+  {
+    \Result { \Expand { \dim_min:nn { #1 } { #2 } } }
+  }
+
+\PrgNewFunction \DimMathRatio { m m }
+  {
+    \Result { \Expand { \dim_ratio:nn { #1 } { #2 } } }
+  }
+
+\PrgNewFunction \DimNew { M } { \dim_new:N #1 }
+
+\PrgNewFunction \DimConst { M m } { \dim_const:Nn #1 {#2} }
+
+\PrgNewFunction \DimUse { M } { \Result { \Value #1 } }
+
+\PrgNewFunction \DimLog { m } { \dim_log:n { #1 } }
+
+\PrgNewFunction \DimVarLog { M } { \dim_log:N #1 }
+
+\PrgNewFunction \DimShow { m } { \dim_show:n { #1 } }
+
+\PrgNewFunction \DimVarShow { M } { \dim_show:N #1 }
+
+\PrgNewFunction \DimSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gset:Nn #1 {#2} } { \dim_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \DimSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gset_eq:NN #1 #2 } { \dim_set_eq:NN #1 #2 }
+  }
+
+\PrgNewFunction \DimZero { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gzero:N #1 } { \dim_zero:N #1 }
+  }
+
+\PrgNewFunction \DimZeroNew { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gzero_new:N #1 } { \dim_zero_new:N #1 }
+  }
+
+\PrgNewFunction \DimAdd { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gadd:Nn #1 {#2} } { \dim_add:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \DimSub { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \dim_gsub:Nn #1 {#2} } { \dim_sub:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \DimStepInline { m m m n }
+  {
+    \dim_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
+  }
+
+\PrgNewFunction \DimStepVariable { m m m M n }
+  {
+    \dim_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
+  }
+
+\PrgNewConditional \DimIfExist { M }
+  {
+    \dim_if_exist:NTF #1 { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \DimCompare { m N m }
+  {
+    \dim_compare:nNnTF {#1} #2 {#3}
+      { \Result { \cTrueBool } } { \Result { \cFalseBool } }
+  }
+
+\PrgNewFunction \DimCase   { m m }     { \dim_case:nn {#1} {#2} }
+\PrgNewFunction \DimCaseT  { m m n }   { \dim_case:nnT {#1} {#2} {#3} }
+\PrgNewFunction \DimCaseF  { m m n }   { \dim_case:nnF {#1} {#2} {#3} }
+\PrgNewFunction \DimCaseTF { m m n n } { \dim_case:nnTF {#1} {#2} {#3} {#4} }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Sorting Functions (Sort)}
+%%% --------------------------------------------------------
+
+\cs_set_eq:NN \SortReturnSame \sort_return_same:
+\cs_set_eq:NN \SortReturnSwapped \sort_return_swapped:
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Comma Separated Lists (Clist)}
+%%% --------------------------------------------------------
+
+\clist_new:N \lTmpaClist   \clist_new:N \lTmpbClist   \clist_new:N \lTmpcClist
+\clist_new:N \lTmpiClist   \clist_new:N \lTmpjClist   \clist_new:N \lTmpkClist
+\clist_new:N \l at Funx@Clist \clist_new:N \l at Funy@Clist \clist_new:N \l at Funz@Clist
+
+\clist_new:N \gTmpaClist   \clist_new:N \gTmpbClist   \clist_new:N \gTmpcClist
+\clist_new:N \gTmpiClist   \clist_new:N \gTmpjClist   \clist_new:N \gTmpkClist
+\clist_new:N \g at Funx@Clist \clist_new:N \g at Funy@Clist \clist_new:N \g at Funz@Clist
+
+\clist_set_eq:NN \cEmptyClist \c_empty_clist
+
+\PrgNewFunction \ClistNew { M } { \clist_new:N #1 }
+
+\PrgNewFunction \ClistLog { m } { \clist_log:n { #1 } }
+
+\PrgNewFunction \ClistVarLog { M } { \clist_log:N #1 }
+
+\PrgNewFunction \ClistShow { m } { \clist_show:n { #1 } }
+
+\PrgNewFunction \ClistVarShow { M } { \clist_show:N #1 }
+
+\PrgNewFunction \ClistVarJoin { M m }
+  {
+    \Expand { \clist_use:Nn #1 { #2 } }
+  }
+
+\PrgNewFunction \ClistVarJoinExtended { M m m m }
+  {
+    \Expand { \clist_use:Nnnn #1 { #2 } { #3 } { #4 } }
+  }
+
+\PrgNewFunction \ClistJoin { m m }
+  {
+    \Expand { \clist_use:nn { #1 } { #2 } }
+  }
+
+\PrgNewFunction \ClistJoinExtended { m m m m }
+  {
+    \Expand { \clist_use:nnnn { #1 } { #2 } { #3 } { #4 } }
+  }
+
+\PrgNewFunction \ClistConst { M m } { \clist_const:Nn #1 { #2 } }
+
+\PrgNewFunction \ClistSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gset:Nn #1 {#2} } { \clist_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \ClistSetEq { M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gset_eq:NN #1 #2 } { \clist_set_eq:NN #1 #2 }
+  }
+
+\PrgNewFunction \ClistSetFromSeq { M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gset_from_seq:NN #1 #2 } { \clist_set_from_seq:NN #1 #2 }
+  }
+
+\PrgNewFunction \ClistConcat { M M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gconcat:NNN #1 #2 #3 } { \clist_concat:NNN #1 #2 #3 }
+  }
+
+\PrgNewFunction \ClistClear { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \clist_gclear:N #1 } { \clist_clear:N #1 }
+  }
+
+\PrgNewFunction \ClistClearNew { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \clist_gclear_new:N #1 } { \clist_clear_new:N #1 }
+  }
+
+\PrgNewFunction \ClistPutLeft { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gput_left:Nn #1 {#2} } { \clist_put_left:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \ClistPutRight { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gput_right:Nn #1 {#2} } { \clist_put_right:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \ClistRemoveDuplicates { M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gremove_duplicates:N #1 } { \clist_remove_duplicates:N #1 }
+  }
+
+\PrgNewFunction \ClistRemoveAll { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gremove_all:Nn #1 {#2} } { \clist_remove_all:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \ClistReverse { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \clist_greverse:N #1 } { \clist_reverse:N #1 }
+  }
+
+\PrgNewFunction \ClistSort { 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 \ClistVarCount { m }
+  {
+    \Result { \Expand { \clist_count:N #1 } }
+  }
+
+\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} }
+
+\PrgNewFunction \ClistPop { M M }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gpop:NN #1 #2 } { \clist_pop:NN #1 #2 }
+  }
+\PrgNewFunction \ClistPopT { M M n }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gpop:NNT #1 #2 {#3} } { \clist_pop:NNT #1 #2 {#3} }
+  }
+\PrgNewFunction \ClistPopF { M M n }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gpop:NNF #1 #2 {#3} } { \clist_pop:NNF #1 #2 {#3} }
+  }
+\PrgNewFunction \ClistPopTF { M M n n }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gpop:NNTF #1 #2 {#3} {#4} } { \clist_pop:NNTF #1 #2 {#3} {#4} }
+  }
+
+\PrgNewFunction \ClistPush { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \clist_gpush:Nn #1 {#2} } { \clist_push:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \ClistItem { m m } { \Expand { \clist_item:nn {#1} {#2} } }
+
+\PrgNewFunction \ClistVarItem { M m } { \Expand { \clist_item:Nn #1 {#2} } }
+
+\PrgNewFunction \ClistRandItem { m } { \Expand { \clist_rand_item:n {#1} } }
+
+\PrgNewFunction \ClistVarRandItem { M } { \Expand { \clist_rand_item:N #1 } }
+
+\PrgNewFunction \ClistMapInline { m n }
+  {
+    \clist_map_inline:nn {#1} {#2}
+  }
+
+\PrgNewFunction \ClistVarMapInline { M n }
+  {
+    \clist_map_inline:Nn #1 {#2}
+  }
+
+\PrgNewFunction \ClistMapVariable { m M n }
+  {
+    \clist_map_variable:nNn {#1} #2 {#3}
+  }
+
+\PrgNewFunction \ClistVarMapVariable { M M n }
+  {
+    \clist_map_variable:NNn #1 #2 {#3}
+  }
+
+\cs_set_eq:NN \ClistMapBreak \clist_map_break:
+
+\PrgNewConditional \ClistIfExist { M }
+  {
+    \clist_if_exist:NTF #1 { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \ClistIfEmpty { m }
+  {
+    \clist_if_empty:nTF {#1} { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \ClistVarIfEmpty { m }
+  {
+    \clist_if_empty:NTF #1 { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \ClistIfIn { m m }
+  {
+    \clist_if_in:nnTF {#1} {#2}
+      { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \ClistVarIfIn { M m }
+  {
+    \clist_if_in:NnTF #1 {#2}
+      { \Result { \cTrueBool } }  { \Result { \cFalseBool } }
+  }
+



More information about the tex-live-commits mailing list.