% -*- coding: utf-8 -*- % !TEX program = lualatex \documentclass[oneside]{book} \usepackage[a4paper,margin=2.5cm]{geometry} \newcommand*{\myversion}{2024A} \newcommand*{\mydate}{Version \myversion\ (\the\year-\mylpad\month-\mylpad\day)} \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi} \setlength{\parindent}{0pt} \setlength{\parskip}{4pt plus 1pt minus 1pt} \usepackage{codehigh} \colorlet{highback}{blue9} %\CodeHigh{lite} \CodeHigh{language=latex/latex2,style/main=highback,style/code=highback} \NewCodeHighEnv{code}{style/main=gray9,style/code=gray9} \NewCodeHighEnv{demo}{style/main=gray9,style/code=gray9,demo} \usepackage{enumitem} \NewDocumentCommand\MySubScript{m}{$_{#1}$} \ExplSyntaxOn \NewDocumentCommand\PrintVarList{m}{ \clist_set:Nn \l_tmpa_clist {#1} \clist_map_inline:Nn \l_tmpa_clist { \token_to_str:N ##1 ~ } } \NewDocumentCommand\RelaceChacters{m}{ \tl_set:Nn \lTmpaTl {#1} \regex_replace_once:nnN { \_ } { \c{MySubScript} } \lTmpaTl } \NewDocumentCommand\RelaceUnderScoreAll{m}{ \tl_set:Nn \lTmpaTl {#1} \regex_replace_all:nnN { \_ } { \c{_} } \lTmpaTl \lTmpaTl } \ExplSyntaxOff \NewDocumentEnvironment{variable}{om}{ \vspace{5pt} \begin{minipage}{\linewidth} \hrule\vspace{4pt}\obeylines% \begingroup \ttfamily\bfseries\color{azure3} \PrintVarList{#2} \endgroup \par\vspace{4pt}\hrule \end{minipage}\par\nopagebreak\vspace{4pt} }{% \vspace{5pt}% } \NewDocumentEnvironment{function}{om}{ \vspace{5pt}% }{\vspace{5pt}} \NewDocumentEnvironment{syntax}{}{% \begin{minipage}{\linewidth} \hrule\vspace{4pt}\obeylines% }{% \par\vspace{4pt}\hrule \end{minipage}\par\nopagebreak\vspace{4pt} } \NewDocumentEnvironment{texnote}{}{}{} \NewDocumentCommand\cs{O{}m}{% \texttt{\bfseries\color{purple3}\cBackslashStr\RelaceUnderScoreAll{#2}}% } \NewDocumentCommand\meta{m}{% \RelaceChacters{#1}% \textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}% } \NewDocumentCommand\Arg{m}{% \RelaceChacters{#1}% \texttt{\{}\textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}\texttt{\}}% } \NewDocumentCommand\pkg{m}{\textsf{#1}} \NewDocumentCommand\nan{}{\texttt{NaN}} \NewDocumentCommand\enquote{m}{``#1''} \let\tn=\cs \RenewDocumentCommand\emph{m}{% \underline{\textsl{#1}}% } \newenvironment{l3regex-syntax} {\begin{itemize}\def\\{\char`\\}\def\makelabel##1{\hss\llap{\ttfamily##1}}} {\end{itemize}} \usepackage{shortvrb} \NewDocumentCommand \MyMakeShortVerb {} {% \MakeShortVerb \|% \MakeShortVerb \"% } \NewDocumentCommand \MyDeleteShortVerb {} {% \DeleteShortVerb \|% \DeleteShortVerb \"% } \AtBeginDocument{\MyMakeShortVerb} \AtEndDocument{\MyDeleteShortVerb} \AddToHook{env/demohigh/before}{\MyDeleteShortVerb} \AddToHook{env/demohigh/after}{\MyMakeShortVerb} \usepackage{hologo} \providecommand*\LuaTeX{\hologo{LuaTeX}} \providecommand*\pdfTeX{\hologo{pdfTeX}} \providecommand*\XeTeX{\hologo{XeTeX}} \usepackage{amsmath} \usepackage{hyperref} \hypersetup{ colorlinks=true, urlcolor=blue3, linkcolor=blue3, } \usepackage{functional} %\Functional{scoping=false,tracing=true} \begin{document} \title{\sffamily Intuitive \textcolor{green3}{Functional} Programming Interface for LaTeX2} \author{Jianrui Lyu (tolvjr@163.com)\\\url{https://github.com/lvjr/functional}} \date{\mydate\vspace{1cm}\\\myabstract\vspace{10cm}} \newcommand\myabstract{\parbox{\linewidth}{\hrule\vspace{0.8em}\large This package provides an intuitive functional programming interface for LaTeX2, which is an alternative choice to \textsf{expl3} or LuaTeX, if you want to do programming in LaTeX. \par\vspace{0.5em} Although there are functions in LaTeX3 programming layer (\textsf{expl3}), the evaluation of them is from outside to inside. With this package, the evaluation of functions is from inside to outside, which is the same as other programming languages such as \texttt{Lua}. In this way, it is rather easy to debug code too. \par\vspace{0.5em} Note that many paragraphs in this manual are copied from the documentation of \textsf{expl3}. \par\vspace{0.8em}\hrule}} {\let\newpage\relax\vspace{-4cm}\maketitle} \tableofcontents \chapter{Overview of Features} \section{Evaluation from Inside to Outside} We will compare our first example with a similar \verb!Lua! example: \begin{minipage}{0.55\textwidth} \begin{codehigh} \IgnoreSpacesOn \prgNewFunction \mathSquare { m } { \intSet \lTmpaInt {\intEval {#1 * #1}} \prgReturn {\expValue \lTmpaInt} } \IgnoreSpacesOff \mathSquare{5} \mathSquare{\mathSquare{5}} \end{codehigh} \end{minipage}% \begin{minipage}{0.45\textwidth} \begin{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} %\IgnoreSpacesOn %\prgNewFunction \mathSquare { m }{ % \intSet \lTmpaInt { \intEval { #1 * #1 } } % \prgReturn { \expValue \lTmpaInt } %} %\IgnoreSpacesOff %\mathSquare{5} %\mathSquare{\mathSquare{5}} %\IgnoreSpacesOn %\prgNewFunction \mathCubic { m } % { % \intSet \lTmpaInt { \intEval { #1 * #1 * #1 } } % \prgReturn { \expValue \lTmpaInt } % } %\IgnoreSpacesOff %\mathCubic{2} %\mathCubic{\mathCubic{2}} Both examples calculate first the square of $5$ and produce $25$, then calculate the square of $25$ and produce $625$. In contrast to \verb!expl3!, this \verb!functional! package does evaluation of functions from inside to outside, which means composition of functions works like other programming languages such as \verb!Lua! or \verb!JavaScript!. You can define new functions with \cs{prgNewFunction} command. To make composition of functions work as expected, every function \emph{must not} insert directly any token to the input stream. Instead, a function \emph{must} pass the result (if any) to \verb!functional! package with \cs{prgReturn} command. And \verb!functional! package is responsible for 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!\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.68\textwidth} \begin{codehigh} \IgnoreSpacesOn \prgNewFunction \mathFact { m } { \intCompareTF {#1} = {0} { \prgReturn {1} }{ \prgReturn {\intEval{#1*\mathFact{\intEval{#1-1}}}} } } \IgnoreSpacesOff \mathFact{4} \end{codehigh} \end{minipage}% \begin{minipage}{0.32\textwidth} \begin{code} -- define a function -- function Fact (n) if n == 0 then return 1 else return n * Fact(n-1) end end -- use the function -- print(Fact(4)) \end{code} \end{minipage} %\IgnoreSpacesOn %\prgNewFunction \Factorial { m } { % \intCompareTF {#1} = {0} { % \prgReturn {1} % }{ % \prgReturn { \intMathMult {#1} { \Factorial { \intMathSub{#1}{1} } } } % } %} %\IgnoreSpacesOff %\Factorial{0} %\Factorial{4} \section{Group Scoping of Functions} 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. 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} \IgnoreSpacesOn \intSet \lTmpaInt {1} \intVarLog \lTmpaInt % ---- 1 \prgNewFunction \someFun { } { \intSet \lTmpaInt {2} \intVarLog \lTmpaInt % ---- 2 \intCompareTF {1} > {0} { \intSet \lTmpaInt {3} \intVarLog \lTmpaInt % ---- 3 }{ } \intVarLog \lTmpaInt % ---- 2 } \someFun \intVarLog \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!. The difference is that \verb!functional! package provides only one function for setting both local and global variables of the same type, by checking leading letters of their names. So for integer variables, you can write \verb!\intSet\lTmpaInt{1}! and \verb!\intSet\gTmpbInt{2}!. 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} \intVarLog \gTmpaInt % ---- 1 \prgNewFunction \someFun { } { \intSet \gTmpaInt {2} \intVarLog \gTmpaInt % ---- 2 \intCompareTF {1} > {0} { \intSet \gTmpaInt {3} \intVarLog \gTmpaInt % ---- 3 }{ } \intVarLog \gTmpaInt % ---- 3 } \someFun \intVarLog \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. \section{Tracing Evaluation of Functions} Since every function in \verb!functional! package will pass its return value to the package, it is quite easy to debug your code. You can turn on the tracing by setting \verb!\Functional{tracing=true}!. For example, the tracing log of the first example in this chapter will be the following: % FIXME: spaces at the first line will be removed %\begin{codehigh}[] % [I] \mathSquare{5} % [I] \intEval{5*5} % [I] \expWhole{\int_eval:n {5*5}} % [O] 25 % [I] \prgReturn{25} % [O] 25 % [O] 25 % [I] \intSet\lTmpaInt {25} % [O] % [I] \expValue\lTmpaInt % [O] 25 % [I] \prgReturn{25} % [O] 25 % [O] 25 %\end{codehigh} \begin{codehigh}[] [I] \mathSquare{5} [I] \intEval{5*5} [I] \expWhole{\int_eval:n {5*5}} [O] 25 [I] \prgReturn{25} [O] 25 [O] 25 [I] \intSet{\lTmpaInt }{25} [O] [I] \expValue{\lTmpaInt } [O] 25 [I] \prgReturn{25} [O] 25 [O] 25 [I] \mathSquare{25} [I] \intEval{25*25} [I] \expWhole{\int_eval:n {25*25}} [O] 625 [I] \prgReturn{625} [O] 625 [O] 625 [I] \intSet{\lTmpaInt }{625} [O] [I] \expValue{\lTmpaInt } [O] 625 [I] \prgReturn{625} [O] 625 [O] 625 \end{codehigh} \section{Definitions of Functions} 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 regular users. The created functions are always protected and accept \verb!\par! in their arguments. Since \verb!functional! package gets the results of functions by evaluation (including expansion and execution by \TeX), it is natural to protect all functions. \section{Variants of Arguments} 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 \module_bar:x \module_bar:f \module_bar:o \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 \exp_args:Nx \exp_args:Nf \exp_args:No \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 as functions (\cs{expName}, \cs{expWhole}, \cs{expValue}, respectively), which are easier to use for regular users. \begin{demohigh} \newcommand\test{uvw} \expName{test} \end{demohigh} \begin{demohigh} \newcommand\test{uvw} \expWhole{111\test222} \end{demohigh} \begin{demohigh} \intSet\lTmpaInt{123} \expValue\lTmpaInt \end{demohigh} The most interesting feature is that you can compose these functions. For example, you can easily get the \verb!v! variant of \verb!expl3! by simply composing \cs{expName} and \cs{expValue} functions: \begin{demohigh} \intSet\lTmpaInt{123} \expValue{\expName{lTmpaInt}} \end{demohigh} \chapter{Functional Progarmming (\texttt{Prg})} \section{Defining Functions and Conditionals} \begin{function}{\prgNewFunction} \begin{syntax} \cs{prgNewFunction} \meta{function} \Arg{argument specification} \Arg{code} \end{syntax} Creates protected \meta{function} for evaluating the \meta{code}. Within the \meta{code}, the parameters (\verb|#1|, \verb|#2|, \emph{etc.}) will be replaced by those absorbed by the function. The returned value \emph{must} be passed with \cs{prgReturn} function. The definition is global and an error results if the \meta{function} is already defined.\par The \Arg{argument specification} in a list of letters, where each letter is one of the following argument specifiers (nearly all of them are \texttt{M} or \texttt{m} for functions provided by this package):\par {\centering\begin{tabular}{ll} %\hline \texttt{M} & single-token argument, which will be manipulated first \\ \texttt{m} & multi-token argument, which will be manipulated first \\ \texttt{N} & single-token argument, which will not be manipulated first \\ \texttt{n} & multi-token argument, which will not be manipulated first \\ %\hline \end{tabular}\par} The argument manipulation for argument type \texttt{M} or \texttt{m} is: if the argument starts with a function defined with \cs{prgNewFunction}, the argument will be evaluated and replaced with the returned value. \end{function} \begin{function}{\prgSetEqFunction} \begin{syntax} \cs{prgSetEqFunction} \meta{function_1} \meta{function_2} \end{syntax} Sets \meta{function_1} as an alias of \meta{function_2}. \end{function} \begin{function}{\prgNewConditional} \begin{syntax} \cs{prgNewConditional} \meta{function} \Arg{argument specification} \Arg{code} \end{syntax} Creates protected conditional \meta{function} for evaluating the \meta{code}. The returned value of the \meta{function} \emph{must} be either |\cTrueBool| or |\cFalseBool| and be passed with \cs{prgReturn} function.. The definition is global and an error results if the \meta{function} is already defined. \par Assume the \meta{function} is |\fooIfBar|, then another three functions are also created at the same time: |\fooIfBarT|, |\fooIfBarF|, and |\fooIfBarTF|. They have extra arguments which are \Arg{true code} or/and \Arg{false code}. For example, if you write \begin{codehigh} \prgNewConditional \fooIfBar {Mm} {code with return value \cTrueBool or \cFalseBool} \end{codehigh} Then the following four functions are created: \begin{itemize} \item |\fooIfBar| \meta{arg_1} \Arg{arg_2} \item |\fooIfBarT| \meta{arg_1} \Arg{arg_2} \Arg{true code} \item |\fooIfBarF| \meta{arg_1} \Arg{arg_2} \Arg{false code} \item |\fooIfBarTF| \meta{arg_1} \Arg{arg_2} \Arg{true code} \Arg{false code} \end{itemize} \end{function} \section{Returning Values and Printing Tokens} Just like \LuaTeX, \pkg{functional} package also provides \cs{prgReturn} and \cs{prgPrint} functions. \begin{function}{\prgReturn} \begin{syntax} \cs{prgReturn} \Arg{tokens} \end{syntax} Returns \meta{tokens} as result of current function or conditional. This function is normally used in the \meta{code} of \cs{prgNewFunction} or \cs{prgNewConditional}, and it \emph{must} be the last function evaluated in the \meta{code}. If it is missing, the return value of the last function evaluated in the \meta{code} is returned. Therefore, the following two examples produce the same output: \begin{codehigh} \IgnoreSpacesOn \prgNewFunction \mathSquare { m } { \intSet \lTmpaInt {\intEval {#1 * #1}} \prgReturn {\expValue \lTmpaInt} } \IgnoreSpacesOff \mathSquare{5} \end{codehigh} \begin{codehigh} \IgnoreSpacesOn \prgNewFunction \mathSquare { m } { \intSet \lTmpaInt {\intEval {#1 * #1}} \expValue \lTmpaInt } \IgnoreSpacesOff \mathSquare{5} \end{codehigh} \pkg{Functional} package takes care of return values, and only print them to the input stream if the outer most functions are evaluated. \end{function} \begin{function}{\prgPrint} \begin{syntax} \cs{prgPrint} \Arg{tokens} \end{syntax} Prints \meta{tokens} directly to the input stream. If there is no function defined with \cs{prgNewFunction} in \meta{tokens}, you can omit \cs{prgPrint} and write only \meta{tokens}. But if there is any function defined with \cs{prgNewFunction} in \meta{tokens}, you \emph{have to} use \cs{prgPrint} function. \end{function} \section{Running Code with Anonymous Functions} \begin{function}{\prgDo} \begin{syntax} \cs{prgDo} \Arg{code} \end{syntax} Treats \meta{code} as an anonymous function without arguments and evaluates it. \end{function} \begin{function}{\prgRunOneArgCode,\prgRunTwoArgCode,\prgRunThreeArgCode,\prgRunFourArgCode} \begin{syntax} \cs{prgRunOneArgCode} \Arg{arg_1} \Arg{code} \cs{prgRunTwoArgCode} \Arg{arg_1} \Arg{arg_2} \Arg{code} \cs{prgRunThreeArgCode} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{code} \cs{prgRunFourArgCode} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{code} \end{syntax} Treats \meta{code} as an anonymous function with one to four arguments respectively, and evaluates it. In evaluating the \meta{code}, \pkg{functional} package first evaluates \meta{arg_1} to \meta{arg_4}, then replaces |#1| to |#4| in \meta{code} with the return values respectively. \end{function} \chapter{Argument Using (\texttt{Use})} \section{Evaluating Functions} \begin{function}{\evalWhole} \begin{syntax} \cs{evalWhole} \Arg{tokens} \end{syntax} Evaluates all functions (defined with \cs{prgNewFunction}) in \meta{tokens} and replaces them with their return values, then returns the resulting tokens. \begin{codehigh} \tlSet \lTmpaTl {a\intEval{2*3}b} \tlSet \lTmpbTl {\evalWhole {a\intEval{2*3}b}} \end{codehigh} In the above example, |\lTmpaTl| contains |a\intEval{2*3}b|, while |\lTmpbTl| contains |a6b|. \end{function} \begin{function}{\evalNone} \begin{syntax} \cs{evalNone} \Arg{tokens} \end{syntax} Prevents the evaluation of its argument, returning \meta{tokens} without touching them. \begin{codehigh} \tlSet \lTmpaTl {\intEval{2*3}} \tlSet \lTmpbTl {\evalNone {\intEval{2*3}}} \end{codehigh} In the above example, |\lTmpaTl| contains |6|, while |\lTmpbTl| contains |\intEval{2*3}|. \end{function} \section{Expanding Tokens} \begin{function}{\expName} \begin{syntax} \cs{expName} \Arg{control sequence name} \end{syntax} Expands the \meta{control sequence name} until only characters remain, then converts this into a control sequence and returns it. The \meta{control sequence name} must consist of character tokens %, %typically a mixture of category code $10$ (space), $11$ (letter) and $12$ (other). when exhaustively expanded.% %\begin{texnote} %Protected macros that appear in a \texttt{c}-type argument are %expanded despite being protected; \cs{exp_not:n} also has no %effect. An internal error occurs if non-characters or active %characters remain after full expansion, as the conversion to a %control sequence is not possible. %\end{texnote} \end{function} \begin{function}{\expValue} \begin{syntax} \cs{expValue} \meta{variable} \end{syntax} Recovers the content of a \meta{variable} and returns the value. An error is raised if the variable does not exist or if it is invalid. Note that it is the same as \cs{tlUse} for \meta{tl var}, or \cs{intUse} for \meta{int var}. \end{function} \begin{function}{\expWhole} \begin{syntax} \cs{expWhole} \Arg{tokens} \end{syntax} Expands the \meta{tokens} exhaustively and returns the result. \end{function} \begin{function}{\unExpand} \begin{syntax} \cs{unExpand} \Arg{tokens} \end{syntax} Prevents expansion of the \meta{tokens} inside the argument of \cs{expWhole} function. The argument of \cs{unExpand} \emph{must} be surrounded by braces. %\begin{texnote} %This is the \eTeX{} \tn{unexpanded} primitive. In an %|x|-expanding definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#1}| %is equivalent to |##1| rather than to~|#1|, namely it inserts the %two characters |#| and~|1|. In an |e|-type argument %\cs{exp_not:n}~|{#}| is equivalent to |#|, namely it inserts the %character~|#|. %\end{texnote} \end{function} \begin{function}{\onlyName} \begin{syntax} \cs{onlyName} \Arg{tokens} \end{syntax} Expands the \meta{tokens} until only characters remain, and then converts this into a control sequence. Further expansion of this control sequence is then inhibited inside the argument of \cs{expWhole} function. %\begin{texnote} %Protected macros that appear in a \texttt{c}-type argument are %expanded despite being protected; \cs{exp_not:n} also has no %effect. An internal error occurs if non-characters or active %characters remain after full expansion, as the conversion to a %control sequence is not possible. %\end{texnote} \end{function} \begin{function}{\onlyValue} \begin{syntax} \cs{onlyValue} \meta{variable} \end{syntax} Recovers the content of the \meta{variable}, then prevents expansion of this material inside the argument of \cs{expWhole} function. \end{function} \section{Using Tokens} \begin{function}{\useOne,\gobbleOne} \begin{syntax} \cs{useOne} \Arg{argument} \cs{gobbleOne} \Arg{argument} \end{syntax} The function \cs{useOne} absorbs one argument and returns it. %\begin{texnote} %The \cs{UseOne} function is equivalent to \LaTeXe{}'s \tn{@firstofone}. %\end{texnote} \cs{gobbleOne} absorbs one argument and returns nothing. %\begin{texnote} %These are equivalent to \LaTeXe{}'s \tn{@gobble}, \tn{@gobbbletwo}, %\emph{etc.} %\end{texnote} For example \begin{demohigh} \useOne{abc}\gobbleOne{ijk}\useOne{xyz} \end{demohigh} \end{function} \begin{function}{\useGobble,\gobbleUse} \begin{syntax} \cs{useGobble} \Arg{arg_1} \Arg{arg_2} \cs{gobbleUse} \Arg{arg_1} \Arg{arg_2} \end{syntax} These functions absorb two arguments. The function \cs{useGobble} discards the second argument, and returns the content of the first argument. \cs{gobbleUse} discards the first argument, and returns the content of the second argument. %\begin{texnote} %These are equivalent to \LaTeXe{}'s \tn{@firstoftwo} and %\tn{@secondoftwo}. %\end{texnote} For example \begin{demohigh} \useGobble{abc}{uvw}\gobbleUse{abc}{uvw} \end{demohigh} \end{function} \chapter{Control Structures (\texttt{Bool})} \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 {\prgReturn{True!}} {\prgReturn{False!}} \boolVarIfTF \cFalseBool {\prgReturn{True!}} {\prgReturn{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 function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaBool,\gTmpbBool,\gTmpcBool,\gTmpiBool,\gTmpjBool,\gTmpkBool} Scratch booleans 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{Boolean Expressions} As we have a boolean datatype and predicate functions returning boolean \meta{true} or \meta{false} values, it seems only fitting that we also provide a parser for \meta{boolean expressions}. A boolean expression is an expression which given input in the form of predicate functions and boolean variables, return boolean \meta{true} or \meta{false}. It supports the logical operations And, Or and Not as the well-known infix operators \verb|&&| and \verb"||" and prefix~\verb|!| with their usual precedences (namely, \verb|&&| binds more tightly than \verb"||"). In addition to this, parentheses can be used to isolate sub-expressions. For example, \begin{codehigh} \intCompare {1} = {1} && ( \intCompare {2} = {3} || \intCompare {4} < {4} || \strIfEq {abc} {def} ) && ! \intCompare {2} = {4} \end{codehigh} is a valid boolean expression. Contrarily to some other programming languages, the operators \verb|&&| and \verb"||" evaluate both operands in all cases, even when the first operand is enough to determine the result. \section{Creating and Setting Booleans} \begin{function}{\boolNew} \begin{syntax} \cs{boolNew} \meta{boolean} \end{syntax} Creates a new \meta{boolean} or raises an error if the name is already taken. The declaration is global. The \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}<{4}} \boolVarLog \lTmpaBool \end{codehigh} \begin{codehigh} \boolSet \lTmpaBool {\intCompare{3}<{4} && \strIfEq{abc}{uvw}} \boolVarLog \lTmpaBool \end{codehigh} \end{function} \begin{function}{\boolSetTrue} \begin{syntax} \cs{boolSetTrue} \meta{boolean} \end{syntax} Sets \meta{boolean} logically \texttt{true}. \end{function} \begin{function}{\boolSetFalse} \begin{syntax} \cs{boolSetFalse} \meta{boolean} \end{syntax} Sets \meta{boolean} logically \texttt{false}. \end{function} \begin{function}{\boolSetEq} \begin{syntax} \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,\boolIfExistT,\boolIfExistF,\boolIfExistTF} \begin{syntax} \cs{boolIfExist} \meta{boolean} \cs{boolIfExistT} \meta{boolean} \Arg{true code} \cs{boolIfExistF} \meta{boolean} \Arg{false code} \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 {\prgReturn{Yes}} {\prgReturn{No}} \boolIfExistTF \lFooUndefinedBool {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\boolVarIf,\boolVarIfT,\boolVarIfF,\boolVarIfTF} \begin{syntax} \cs{boolVarIf} \meta{boolean} \cs{boolVarIfT} \meta{boolean} \Arg{true code} \cs{boolVarIfF} \meta{boolean} \Arg{false code} \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 \boolVarIfTF \lTmpaBool {\prgReturn{True!}} {\prgReturn{False!}} \boolSetFalse \lTmpaBool \boolVarIfTF \lTmpaBool {\prgReturn{True!}} {\prgReturn{False!}} \end{demohigh} \end{function} \begin{function}{\boolVarNot,\boolVarNotT,\boolVarNotF,\boolVarNotTF} \begin{syntax} \cs{boolVarNot} \meta{boolean} \cs{boolVarNotT} \meta{boolean} \Arg{true code} \cs{boolVarNotF} \meta{boolean} \Arg{false code} \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}} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\boolVarAnd,\boolVarAndT,\boolVarAndF,\boolVarAndTF} \begin{syntax} \cs{boolVarAnd} \meta{boolean_1} \meta{boolean_2} \cs{boolVarAndT} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \cs{boolVarAndF} \meta{boolean_1} \meta{boolean_2} \Arg{false code} \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}} {\intIfOdd{6}} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\boolVarOr,\boolVarOrT,\boolVarOrF,\boolVarOrTF} \begin{syntax} \cs{boolVarOr} \meta{boolean_1} \meta{boolean_2} \cs{boolVarOrT} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \cs{boolVarOrF} \meta{boolean_1} \meta{boolean_2} \Arg{false code} \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}} {\intIfOdd{6}} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\boolVarXor,\boolVarXorT,\boolVarXorF,\boolVarXorTF} \begin{syntax} \cs{boolVarXor} \meta{boolean_1} \meta{boolean_2} \cs{boolVarXorT} \meta{boolean_1} \meta{boolean_2} \Arg{true code} \cs{boolVarXorF} \meta{boolean_1} \meta{boolean_2} \Arg{false code} \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}} {\intIfOdd{6}} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \section{Booleans and Logical Loops} Loops using either boolean expressions or stored boolean values. \begin{function}{\boolVarDoUntil} \begin{syntax} \cs{boolVarDoUntil} \meta{boolean} \Arg{code} \end{syntax} Places the \meta{code} in the input stream for \TeX{} to process, and then checks the logical value of the \meta{boolean}. If it is \texttt{false} then the \meta{code} is inserted into the input stream again and the process loops until the \meta{boolean} is \texttt{true}. \begin{demohigh} \IgnoreSpacesOn \boolSetFalse \lTmpaBool \intZero \lTmpaInt \clistClear \lTmpaClist \boolVarDoUntil \lTmpaBool { \intIncr \lTmpaInt \clistPutRight \lTmpaClist {\expValue\lTmpaInt} \intCompareT {\lTmpaInt} = {10} {\boolSetTrue \lTmpaBool} } \clistVarJoin \lTmpaClist {:} \IgnoreSpacesOff \end{demohigh} \end{function} \begin{function}{\boolVarDoWhile} \begin{syntax} \cs{boolVarDoWhile} \meta{boolean} \Arg{code} \end{syntax} Places the \meta{code} in the input stream for \TeX{} to process, and then checks the logical value of the \meta{boolean}. If it is \texttt{true} then the \meta{code} is inserted into the input stream again and the process loops until the \meta{boolean} is \texttt{false}. \begin{demohigh} \IgnoreSpacesOn \boolSetTrue \lTmpaBool \intZero \lTmpaInt \clistClear \lTmpaClist \boolVarDoWhile \lTmpaBool { \intIncr \lTmpaInt \clistPutRight \lTmpaClist {\expValue\lTmpaInt} \intCompareT {\lTmpaInt} = {10} {\boolSetFalse \lTmpaBool} } \clistVarJoin \lTmpaClist {:} \IgnoreSpacesOff \end{demohigh} \end{function} \begin{function}{\boolVarUntilDo} \begin{syntax} \cs{boolVarUntilDo} \meta{boolean} \Arg{code} \end{syntax} This function firsts checks the logical value of the \meta{boolean}. If it is \texttt{false} the \meta{code} is placed in the input stream and expanded. After the completion of the \meta{code} the truth of the \meta{boolean} is re-evaluated. The process then loops until the \meta{boolean} is \texttt{true}. \begin{demohigh} \IgnoreSpacesOn \boolSetFalse \lTmpaBool \intZero \lTmpaInt \clistClear \lTmpaClist \boolVarUntilDo \lTmpaBool { \intIncr \lTmpaInt \clistPutRight \lTmpaClist {\expValue\lTmpaInt} \intCompareT {\lTmpaInt} = {10} {\boolSetTrue \lTmpaBool} } \clistVarJoin \lTmpaClist {:} \IgnoreSpacesOff \end{demohigh} \end{function} \begin{function}{\boolVarWhileDo} \begin{syntax} \cs{boolVarWhileDo} \meta{boolean} \Arg{code} \end{syntax} This function firsts checks the logical value of the \meta{boolean}. If it is \texttt{true} the \meta{code} is placed in the input stream and expanded. After the completion of the \meta{code} the truth of the \meta{boolean} is re-evaluated. The process then loops until the \meta{boolean} is \texttt{false}. \begin{demohigh} \IgnoreSpacesOn \boolSetTrue \lTmpaBool \intZero \lTmpaInt \clistClear \lTmpaClist \boolVarWhileDo \lTmpaBool { \intIncr \lTmpaInt \clistPutRight \lTmpaClist {\expValue\lTmpaInt} \intCompareT {\lTmpaInt} = {10} {\boolSetFalse \lTmpaBool} } \clistVarJoin \lTmpaClist {:} \IgnoreSpacesOff \end{demohigh} \end{function} \chapter{Token Lists (\texttt{Tl})} \TeX{} works with tokens, and \LaTeX3 therefore provides a number of functions to deal with lists of tokens. Token lists may be present directly in the argument to a function: \begin{codehigh} \tlFoo {a collection of \tokens} \end{codehigh} or may be stored in a so-called \enquote{token list variable}, which have the suffix \texttt{Tl}: a token list variable can also be used as the argument to a function, for example \begin{codehigh} \tlVarFoo \lSomeTl \end{codehigh} In both cases, functions are available to test and manipulate the lists of tokens, and these have the module prefix \texttt{Tl}. In many cases, functions which can be applied to token list variables are paired with similar functions for application to explicit lists of tokens: the two \enquote{views} of a token list are therefore collected together here. A token list (explicit, or stored in a variable) can be seen either as a list of \enquote{items}, or a list of \enquote{tokens}. An item is whatever \cs{useOne} would grab as its argument: a single non-space token or a brace group, with optional leading explicit space characters (each item is thus itself a token list). A token is either a normal \texttt{N} argument, or \verb*| |, \verb|{|, or \verb|}| (assuming normal \TeX{} category codes). Thus for example \begin{codehigh} {Hello} world \end{codehigh} contains 6 items (\texttt{Hello}, \texttt{w}, \texttt{o}, \texttt{r}, \texttt{l} and \texttt{d}), but 13 tokens (\verb|{|, \texttt{H}, \texttt{e}, \texttt{l}, \texttt{l}, \texttt{o}, \verb|}|, \verb*| |, \texttt{w}, \texttt{o}, \texttt{r}, \texttt{l} and \texttt{d}). Functions which act on items are often faster than their analogue acting directly on tokens. \section{Constant and Scratch Token Lists} \begin{variable}{\cSpaceTl} 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}} {\prgReturn{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 function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaTl,\gTmpbTl,\gTmpcTl,\gTmpiTl,\gTmpjTl,\gTmpkTl} Scratch token 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 Token Lists} \begin{function}{\tlNew} \begin{syntax} \cs{tlNew} \meta{tl var} \end{syntax} Creates a new \meta{tl var} or raises an error if the name is already taken. The declaration is global. The \meta{tl~var} is initially empty. \begin{codehigh} \tlNew \lFooSomeTl \end{codehigh} \end{function} \begin{function}{\tlConst} \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}. \begin{codehigh} \tlConst \cFooSomeTl {abc} \end{codehigh} \end{function} \begin{function}{\tlUse} \begin{syntax} \cs{tlUse} \meta{tl~var} \end{syntax} Recovers the content of a \meta{tl~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{tl~var} directly without an accessor function. \begin{codehigh} \tlUse \lTmpbTl \end{codehigh} \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). \begin{demohigh} \tlToStr {12\abc34} \end{demohigh} %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). \begin{demohigh} \tlSet \lTmpaTl {12\abc34} \tlVarToStr \lTmpaTl \end{demohigh} \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. \begin{codehigh} \tlLog {123\abc456} \end{codehigh} \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. \begin{codehigh} \tlSet \lTmpaTl {123\abc456} \tlVarLog \lTmpaTl \end{codehigh} \end{function} \begin{function}{\tlShow} \begin{syntax} \cs{tlShow} \Arg{token list} \end{syntax} Displays the \meta{token list} on the terminal. \begin{codehigh} \tlShow {123\abc456} \end{codehigh} %\begin{texnote} %This is similar to the \eTeX{} primitive \tn{showtokens}, wrapped %to a fixed number of characters per line. %\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{codehigh} \tlSet \lTmpaTl {123\abc456} \tlVarShow \lTmpaTl \end{codehigh} %\begin{texnote} %This is similar to the \TeX{} primitive \tn{show}, wrapped to a %fixed number of characters per line. %\end{texnote} \end{function} \section{Setting Token List Variables} \begin{function}{\tlSet} \begin{syntax} \cs{tlSet} \meta{tl~var} \Arg{tokens} \end{syntax} Sets \meta{tl~var} to contain \meta{tokens}, removing any previous content from the variable. \begin{demohigh} \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}. \begin{demohigh} \tlSet \lTmpaTl {abc} \tlSetEq \lTmpbTl \lTmpaTl \tlUse \lTmpbTl \end{demohigh} \end{function} \begin{function}{\tlClear} \begin{syntax} \cs{tlClear} \meta{tl~var} \end{syntax} Clears all entries from the \meta{tl~var}. \begin{demohigh} \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. \begin{codehigh} \tlClearNew \lFooSomeTl \end{codehigh} \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. \begin{demohigh} \tlSet \lTmpbTl {con} \tlSet \lTmpcTl {cat} \tlConcat \lTmpaTl \lTmpbTl \lTmpcTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\tlPutLeft} \begin{syntax} \cs{tlPutLeft} \meta{tl~var} \Arg{tokens} \end{syntax} Appends \meta{tokens} to the left side of the current content of \meta{tl~var}. \begin{demohigh} \tlSet \lTmpkTl {Functional} \tlPutLeft \lTmpkTl {Hello} \tlUse \lTmpkTl \end{demohigh} \end{function} \begin{function}{\tlPutRight} \begin{syntax} \cs{tlPutRight} \meta{tl~var} \Arg{tokens} \end{syntax} Appends \meta{tokens} to the right side of the current content of \meta{tl~var}. \begin{demohigh} \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}{\tlVarReplaceOnce} \begin{syntax} \cs{tlVarReplaceOnce} \meta{tl var} \Arg{old tokens} \Arg{new tokens} \end{syntax} Replaces the first (leftmost) occurrence of \meta{old tokens} in the \meta{tl var} with \meta{new tokens}. \meta{Old tokens} cannot contain \verb|{|, \verb|}| or \verb|#| (more precisely, explicit character tokens with category code $1$ (begin-group) or $2$ (end-group), and tokens with category code $6$). \begin{demohigh} \tlSet \lTmpaTl {1{bc}2bc3} \tlVarReplaceOnce \lTmpaTl {bc} {xx} \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\tlVarReplaceAll} \begin{syntax} \cs{tlVarReplaceAll} \meta{tl var} \Arg{old tokens} \Arg{new tokens} \end{syntax} Replaces all occurrences of \meta{old tokens} in the \meta{tl var} with \meta{new tokens}. \meta{Old tokens} 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{tlVarRemoveAll} for an example). \begin{demohigh} \tlSet \lTmpaTl {1{bc}2bc3} \tlVarReplaceAll \lTmpaTl {bc} {xx} \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\tlVarRemoveOnce} \begin{syntax} \cs{tlVarRemoveOnce} \meta{tl var} \Arg{tokens} \end{syntax} Removes the first (leftmost) occurrence of \meta{tokens} from the \meta{tl var}. \meta{Tokens} cannot contain \verb|{|, \verb|}| or \verb|#| (more precisely, explicit character tokens with category code $1$ (begin-group) or $2$ (end-group), and tokens with category code $6$). \begin{demohigh} \tlSet \lTmpaTl {1{bc}2bc3} \tlVarRemoveOnce \lTmpaTl {bc} \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\tlVarRemoveAll} \begin{syntax} \cs{tlVarRemoveAll} \meta{tl var} \Arg{tokens} \end{syntax} Removes all occurrences of \meta{tokens} from the \meta{tl var}. \meta{Tokens} cannot contain \verb|{|, \verb|}| or \verb|#| (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} \tlVarRemoveAll \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{demohigh} Foo\tlTrimSpaces { 12 34 }Bar \end{demohigh} %\begin{texnote} %The result is returned within \tn{unexpanded}, which means that the token %list does not expand further when appearing in an \texttt{x}-type %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. \begin{demohigh} \tlSet \lTmpaTl { 12 34 } \tlVarTrimSpaces \lTmpaTl Foo\tlUse \lTmpaTl Bar \end{demohigh} \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}. \begin{demohigh} \tlCount {12\abc34} \end{demohigh} \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}. \begin{demohigh} \tlSet \lTmpaTl {12\abc34} \tlVarCount \lTmpaTl \end{demohigh} \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. \begin{demohigh} \tlSet \lTmpaTl {HELLO} \tlVarHead \lTmpaTl \end{demohigh} \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. \begin{demohigh} \tlSet \lTmpaTl {HELLO} \tlVarTail \lTmpaTl \end{demohigh} \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{demohigh} \tlItem {abcd} {3} \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %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{demohigh} \tlRandItem {abcdef} \tlRandItem {abcdef} \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %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|. \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \tlMapInline {one} { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \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|. \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \tlSet \lTmpkTl {one} \tlVarMapInline \lTmpkTl { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \tlMapVariable {one} \lTmpiTl { \tlPutRight \lTmpaTl {\expWhole {[\lTmpiTl]}} } \prgReturn{\tlUse\lTmpaTl} \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \tlSet \lTmpkTl {one} \tlVarMapVariable \lTmpkTl \lTmpiTl { \tlPutRight \lTmpaTl {\expWhole {[\lTmpiTl]}} } \prgReturn{\tlUse\lTmpaTl} \IgnoreSpacesOff \end{demohigh} \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 { } } %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,\tlIfExistT,\tlIfExistF,\tlIfExistTF} \begin{syntax} \cs{tlIfExist} \meta{tl var} \cs{tlIfExistT} \meta{tl var} \Arg{true code} \cs{tlIfExistF} \meta{tl var} \Arg{false code} \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. \begin{demohigh} \tlIfExistTF \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \tlIfExistTF \lFooUndefinedTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\tlIfEmpty,\tlIfEmptyT,\tlIfEmptyF,\tlIfEmptyTF} \begin{syntax} \cs{tlIfEmpty} \Arg{token list} \cs{tlIfEmptyT} \Arg{token list} \Arg{true code} \cs{tlIfEmptyF} \Arg{token list} \Arg{false code} \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} {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \tlIfEmptyTF {} {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\tlVarIfEmpty,\tlVarIfEmptyT,\tlVarIfEmptyF,\tlVarIfEmptyTF} \begin{syntax} \cs{tlVarIfEmpty} \meta{tl~var} \cs{tlVarIfEmptyT} \meta{tl~var} \Arg{true code} \cs{tlVarIfEmptyF} \meta{tl~var} \Arg{false code} \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} \tlVarIfEmptyTF \lTmpaTl {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \tlClear \lTmpaTl \tlVarIfEmptyTF \lTmpaTl {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\tlIfBlank,\tlIfBlankT,\tlIfBlankF,\tlIfBlankTF} \begin{syntax} \cs{tlIfBlank} \Arg{token list} \cs{tlIfBlankT} \Arg{token list} \Arg{true code} \cs{tlIfBlankF} \Arg{token list} \Arg{false code} \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. \begin{demohigh} \tlIfEmptyTF { } {\prgReturn{Yes}} {\prgReturn{No}} \tlIfBlankTF { } {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\tlIfEq,\tlIfEqT,\tlIfEqF,\tlIfEqTF} \begin{syntax} \cs{tlIfEq} \Arg{token list_1} \Arg{token list_2} \cs{tlIfEqT} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \cs{tlIfEqF} \Arg{token list_1} \Arg{token list_2} \Arg{false code} \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} {\prgReturn{Yes}} {\prgReturn{No}} \tlIfEqTF {abc} {xyz} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} %\begin{demohigh} %\tlSet\lTmpaTl{abc} %\tlSet\lTmpbTl{abc} %\tlSet\lTmpcTl{xyz} %\tlIfEqTF{\tlUse\lTmpaTl}{\tlUse\lTmpbTl}{\prgReturn{Yes}}{\prgReturn{No}} %\tlIfEqTF{\tlUse\lTmpaTl}{\tlUse\lTmpcTl}{\prgReturn{Yes}}{\prgReturn{No}} %\end{demohigh} \end{function} \begin{function}{\tlVarIfEq,\tlVarIfEqT,\tlVarIfEqF,\tlVarIfEqTF} \begin{syntax} \cs{tlVarIfEq} \meta{tl var_1} \meta{tl var_2} \cs{tlVarIfEqT} \meta{tl var_1} \meta{tl var_2} \Arg{true code} \cs{tlVarIfEqF} \meta{tl var_1} \meta{tl var_2} \Arg{false code} \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} \tlVarIfEqTF \lTmpaTl \lTmpbTl {\prgReturn{Yes}} {\prgReturn{No}} \tlVarIfEqTF \lTmpaTl \lTmpcTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} See also \cs{strVarIfEq} for a comparison that ignores category codes. \end{function} \begin{function}{\tlIfIn,\tlIfInT,\tlIfInF,\tlIfInTF} \begin{syntax} \cs{tlIfIn} \Arg{token list_1} \Arg{token list_2} \cs{tlIfInT} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \cs{tlIfInF} \Arg{token list_1} \Arg{token list_2} \Arg{false code} \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. \begin{demohigh} \tlIfInTF {hello world} {o} {\prgReturn{Yes}} {\prgReturn{No}} \tlIfInTF {hello world} {a} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\tlVarIfIn,\tlVarIfInT,\tlVarIfInF,\tlVarIfInTF} \begin{syntax} \cs{tlVarIfIn} \meta{tl var} \Arg{token list} \cs{tlVarIfInT} \meta{tl var} \Arg{token list} \Arg{true code} \cs{tlVarIfInF} \meta{tl var} \Arg{token list} \Arg{false code} \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$). \begin{demohigh} \tlSet \lTmpaTl {hello world} \tlVarIfInTF \lTmpaTl {o} {\prgReturn{Yes}} {\prgReturn{No}} \tlVarIfInTF \lTmpaTl {a} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\tlIfSingle,\tlIfSingleT,\tlIfSingleF,\tlIfSingleTF} \begin{syntax} \cs{tlIfSingle} \Arg{token list} \cs{tlIfSingleT} \Arg{token list} \Arg{true code} \cs{tlIfSingleF} \Arg{token list} \Arg{false code} \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}. \begin{demohigh} \tlIfSingleTF {a} {\prgReturn{Yes}} {\prgReturn{No}} \tlIfSingleTF {abc} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\tlVarIfSingle,\tlVarIfSingleT,\tlVarIfSingleF,\tlVarIfSingleTF} \begin{syntax} \cs{tlVarIfSingle} \meta{tl var} \cs{tlVarIfSingleT} \meta{tl var} \Arg{true code} \cs{tlVarIfSingleF} \meta{tl var} \Arg{false code} \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}. \begin{demohigh} \tlSet \lTmpaTl {a} \tlVarIfSingleTF \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \tlSet \lTmpaTl {abc} \tlVarIfSingleTF \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \tlSet \lTmpaTl {a} \tlSet \lTmpbTl {b} \tlSet \lTmpcTl {c} \tlSet \lTmpkTl {b} \tlVarCase \lTmpkTl { \lTmpaTl {\prgReturn {First}} \lTmpbTl {\prgReturn {Second}} \lTmpcTl {\prgReturn {Third}} } \IgnoreSpacesOff \end{demohigh} \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). \begin{demohigh} \IgnoreSpacesOn \tlSet \lTmpaTl {a} \tlSet \lTmpbTl {b} \tlSet \lTmpcTl {c} \tlSet \lTmpkTl {b} \tlVarCaseT \lTmpkTl { \lTmpaTl {\intSet \lTmpkInt {1}} \lTmpbTl {\intSet \lTmpkInt {2}} \lTmpcTl {\intSet \lTmpkInt {3}} }{ \prgReturn {\intUse \lTmpkInt} } \IgnoreSpacesOff \end{demohigh} \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). \begin{demohigh} \IgnoreSpacesOn \tlSet \lTmpaTl {a} \tlSet \lTmpbTl {b} \tlSet \lTmpcTl {c} \tlSet \lTmpkTl {b} \tlVarCaseF \lTmpkTl{ \lTmpaTl {\prgReturn {First}} \lTmpbTl {\prgReturn {Second}} \lTmpcTl {\prgReturn {Third}} }{ \prgReturn {No~Match!} } \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \tlSet \lTmpaTl {a} \tlSet \lTmpbTl {b} \tlSet \lTmpcTl {c} \tlSet \lTmpkTl {b} \tlVarCaseTF \lTmpkTl { \lTmpaTl {\intSet \lTmpkInt {1}} \lTmpbTl {\intSet \lTmpkInt {2}} \lTmpcTl {\intSet \lTmpkInt {3}} }{ \prgReturn {\intUse \lTmpkInt} }{ \prgReturn {0} } \IgnoreSpacesOff \end{demohigh} \end{function} \chapter{Strings (\texttt{Str})} \TeX{} associates each character with a category code: as such, there is no concept of a \enquote{string} as commonly understood in many other programming languages. However, there are places where we wish to manipulate token lists while in some sense \enquote{ignoring} category codes: this is done by treating token lists as strings in a \TeX{} sense. A \TeX{} string (and thus an \pkg{expl3} string) is a series of characters which have category code $12$ (\enquote{other}) with the exception of space characters which have category code $10$ (\enquote{space}). Thus at a technical level, a \TeX{} string is a token list with the appropriate category codes. In this documentation, these are simply referred to as strings. String variables are simply specialised token lists, but by convention should be named with the suffix \texttt{Str}. Such variables should contain characters with category code $12$ (other), except spaces, which have category code $10$ (blank space). All the functions in this module which accept a token list argument first convert it to a string using \cs{tlToStr} for internal processing, and do not treat a token list or the corresponding string representation differently. As a string is a subset of the more general token list, it is sometimes unclear when one should be used over the other. Use a string variable for data that isn't primarily intended for typesetting and for which a level of protection from unwanted expansion is suitable. This data type simplifies comparison of variables since there are no concerns about expansion of their contents. %The functions \cs{CsToStr}, \cs{tlToStr}, \cs{tlVarToStr} and %\cs{TokenToStr} (and variants) generate strings from the appropriate %input: these are documented in modules \pkg{Cs}, \pkg{Tl} and \pkg{Token}, %respectively. \section{Constant and Scratch Strings} \begin{variable}{\cAmpersandStr,\cAtsignStr,\cBackslashStr,\cLeftBraceStr,\cRightBraceStr, \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. \begin{codehigh} \strNew \lFooSomeStr \end{codehigh} \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. \begin{codehigh} \strConst \cFooSomeStr {12\abc34} \end{codehigh} \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. \begin{codehigh} \strUse \lTmpaStr \end{codehigh} \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. \begin{codehigh} \strLog {1234\abcd5678} \end{codehigh} \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. \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. \begin{codehigh} \strShow {1234\abcd5678} \end{codehigh} \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. \begin{codehigh} \strSet \lTmpiStr {1234\abcd5678} \strVarShow \lTmpiStr \end{codehigh} \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}. \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}. \begin{demohigh} \strSet \lTmpaStr {abc} \strSetEq \lTmpbStr \lTmpaStr \strUse \lTmpbStr \end{demohigh} \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. \begin{codehigh} \strClearNew \lFooSomeStr \strUse \lFooSomeStr \end{codehigh} \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. \begin{demohigh} \strSet \lTmpbStr {con} \strSet \lTmpcStr {cat} \strConcat \lTmpaStr \lTmpbStr \lTmpcStr \strUse \lTmpaStr \end{demohigh} \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. \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. \begin{demohigh} \strSet \lTmpkStr {Functional} \strPutRight \lTmpkStr {World} \strUse \lTmpkStr \end{demohigh} \end{function} \section{Modifying String Variables} \begin{function}{\strVarReplaceOnce} \begin{syntax} \cs{strVarReplaceOnce} \meta{str var} \Arg{old} \Arg{new} \end{syntax} Converts the \meta{old} and \meta{new} token lists to strings, then replaces the first (leftmost) occurrence of \meta{old string} in the \meta{str var} with \meta{new string}. \begin{demohigh} \strSet \lTmpaStr {a{bc}bcd} \strVarReplaceOnce \lTmpaStr {bc} {xx} \strUse \lTmpaStr \end{demohigh} \end{function} \begin{function}{\strVarReplaceAll} \begin{syntax} \cs{strVarReplaceAll} \meta{str var} \Arg{old} \Arg{new} \end{syntax} Converts the \meta{old} and \meta{new} token lists to strings, then replaces all occurrences of \meta{old string} in the \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. \begin{demohigh} \strSet \lTmpaStr {a{bc}bcd} \strVarReplaceAll \lTmpaStr {bc} {xx} \strUse \lTmpaStr \end{demohigh} \end{function} \begin{function}{\strVarRemoveOnce} \begin{syntax} \cs{strVarRemoveOnce} \meta{str var} \Arg{token list} \end{syntax} Converts the \meta{token list} to a \meta{string} then removes the first (leftmost) occurrence of \meta{string} from the \meta{str var}. \begin{demohigh} \strSet \lTmpaStr {a{bc}bcd} \strVarRemoveOnce \lTmpaStr {bc} \strUse \lTmpaStr \end{demohigh} \end{function} \begin{function}{\strVarRemoveAll} \begin{syntax} \cs{strVarRemoveAll} \meta{str var} \Arg{token list} \end{syntax} Converts the \meta{token list} to a \meta{string} then removes all occurrences of \meta{string} from the \meta{str var}. As this function operates from left to right, the pattern \meta{string} may remain after the removal, for instance, \begin{demohigh} \strSet \lTmpaStr {abbccd} \strVarRemoveAll \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. \begin{demohigh} \strCount {12\abc34} \end{demohigh} \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. \begin{demohigh} \strSet \lTmpaStr {12\abc34} \strVarCount \lTmpaStr \end{demohigh} \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. \begin{demohigh} \strHead {HELLO} \end{demohigh} \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. \begin{demohigh} \strSet \lTmpaStr {HELLO} \strVarHead \lTmpaStr \end{demohigh} \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. \begin{demohigh} \strTail {HELLO} \end{demohigh} \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. \begin{demohigh} \strSet \lTmpaStr {HELLO} \strVarTail \lTmpaStr \end{demohigh} \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.} \begin{demohigh} \strItem {abcd} {3} \end{demohigh} \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.} \begin{demohigh} \strSet \lTmpaStr {abcd} \strVarItem \lTmpaStr {3} \end{demohigh} \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|. \begin{demohigh} \IgnoreSpacesOn \strClear \lTmpaStr \strMapInline {one} { \strPutRight \lTmpaStr {[#1]} } \strUse \lTmpaStr \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \strClear \lTmpaStr \strMapVariable {one} \lTmpiStr { \strPutRight \lTmpaStr {\expWhole {[\lTmpiStr]}} } \strUse \lTmpaStr \IgnoreSpacesOff \end{demohigh} \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 { } } %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,\strIfExistT,\strIfExistF,\strIfExistTF} \begin{syntax} \cs{strIfExist} \meta{str var} \cs{strIfExistT} \meta{str var} \Arg{true code} \cs{strIfExistF} \meta{str var} \Arg{false code} \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. \begin{demohigh} \strIfExistTF \lTmpaStr {\prgReturn{Yes}} {\prgReturn{No}} \strIfExistTF \lFooUndefinedStr {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\strVarIfEmpty,\strVarIfEmptyT,\strVarIfEmptyF,\strVarIfEmptyTF} \begin{syntax} \cs{strVarIfEmpty} \meta{str var} \cs{strVarIfEmptyT} \meta{str var} \Arg{true code} \cs{strVarIfEmptyF} \meta{str var} \Arg{false code} \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). \begin{demohigh} \strSet \lTmpaStr {abc} \strVarIfEmptyTF \lTmpaStr {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \strClear \lTmpaStr \strVarIfEmptyTF \lTmpaStr {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\strIfEq,\strIfEqT,\strIfEqF,\strIfEqTF} \begin{syntax} \cs{strIfEq} \Arg{tl_1} \Arg{tl_2} \cs{strIfEqT} \Arg{tl_1} \Arg{tl_2} \Arg{true code} \cs{strIfEqF} \Arg{tl_1} \Arg{tl_2} \Arg{false code} \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} {\prgReturn{Yes}} {\prgReturn{No}} \strIfEqTF {abc} {xyz} {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} %\begin{demohigh} %\strSet\lTmpaStr{abc} %\strSet\lTmpbStr{abc} %\strSet\lTmpcStr{xyz} %\strIfEqTF{\lTmpaStr}{\lTmpbStr}{\prgReturn{Yes}}{\prgReturn{No}} %\strIfEqTF{\lTmpaStr}{\lTmpcStr}{\prgReturn{Yes}}{\prgReturn{No}} %\strIfEqTF{\strUse\lTmpaStr}{\strUse\lTmpbStr}{\prgReturn{Yes}}{\prgReturn{No}} %\strIfEqTF{\strUse\lTmpaStr}{\strUse\lTmpcStr}{\prgReturn{Yes}}{\prgReturn{No}} %\end{demohigh} \end{function} \begin{function}{\strVarIfEq,\strVarIfEqT,\strVarIfEqF,\strVarIfEqTF} \begin{syntax} \cs{strVarIfEq} \meta{str var_1} \meta{str var_2} \cs{strVarIfEqT} \meta{str var_1} \meta{str var_2} \Arg{true code} \cs{strVarIfEqF} \meta{str var_1} \meta{str var_2} \Arg{false code} \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 {\prgReturn{Yes}} {\prgReturn{No}} \strVarIfEqTF \lTmpaStr \lTmpcStr {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\strIfIn,\strIfInT,\strIfInF,\strIfInTF} \begin{syntax} \cs{strIfIn} \Arg{tl_1} \Arg{tl_2} \cs{strIfInT} \Arg{tl_1} \Arg{tl_2} \Arg{true code} \cs{strIfInF} \Arg{tl_1} \Arg{tl_2} \Arg{false code} \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}. \begin{demohigh} \strIfInTF {hello world} {o} {\prgReturn{Yes}}{\prgReturn{No}} \strIfInTF {hello world} {a} {\prgReturn{Yes}}{\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\strVarIfIn,\strVarIfInT,\strVarIfInF,\strVarIfInTF} \begin{syntax} \cs{strVarIfIn} \meta{str var} \Arg{token list} \cs{strVarIfInT} \meta{str var} \Arg{token list} \Arg{true code} \cs{strVarIfInF} \meta{str var} \Arg{token list} \Arg{false code} \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}. \begin{demohigh} \strSet \lTmpaStr {hello world} \strVarIfInTF \lTmpaStr {o} {\prgReturn{Yes}}{\prgReturn{No}} \strVarIfInTF \lTmpaStr {a} {\prgReturn{Yes}}{\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\strCompare,\strCompareT,\strCompareF,\strCompareTF} \begin{syntax} \cs{strCompare} \Arg{tl_1} \meta{relation} \Arg{tl_2} \cs{strCompareT} \Arg{tl_1} \meta{relation} \Arg{tl_2} \Arg{true code} \cs{strCompareF} \Arg{tl_1} \meta{relation} \Arg{tl_2} \Arg{false code} \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} {\prgReturn{Yes}} {\prgReturn{No}} \strCompareTF {ab} < {aa} {\prgReturn{Yes}} {\prgReturn{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} \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. \begin{demohigh} \IgnoreSpacesOn \strCase {bbb} { {aaa} {\prgReturn{First}} {bbb} {\prgReturn{Second}} {ccb} {\prgReturn{Third}} } \IgnoreSpacesOff \end{demohigh} \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). \begin{demohigh} \IgnoreSpacesOn \strCaseT {bbb} { {aaa} {\tlSet\lTmpkTl{First}} {bbb} {\tlSet\lTmpkTl{Second}} {ccb} {\tlSet\lTmpkTl{Third}} }{ \prgReturn{\tlUse\lTmpkTl} } \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \strCaseF {bbb} { {aaa} {\prgReturn{First}} {bbb} {\prgReturn{Second}} {ccb} {\prgReturn{Third}} }{ \prgReturn{No~Match!} } \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \strCaseTF {bbb} { {aaa} {\tlSet\lTmpkTl{First}} {bbb} {\tlSet\lTmpkTl{Second}} {ccb} {\tlSet\lTmpkTl{Third}} }{ \prgReturn{\tlUse\lTmpkTl} }{ \prgReturn{No~Match!} } \IgnoreSpacesOff \end{demohigh} \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 function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaInt,\gTmpbInt,\gTmpcInt,\gTmpiInt,\gTmpjInt,\gTmpkInt} Scratch integer 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{The Syntax of Integer Expressions} An \meta{integer expression} should consist, after evaluation of functions defined with \cs{PrgNewFunction} and expansion, of \texttt{+}, \texttt{-}, \texttt{*}, \texttt{/}, \texttt{(}, \texttt{)} and of course integer operands. The result is calculated by applying standard mathematical rules with the following peculiarities: \begin{itemize} \item \texttt{/} denotes division rounded to the closest integer with ties rounded away from zero; \item there is an error and the overall expression evaluates to zero whenever the absolute value of any intermediate result exceeds $2^{31}-1$, except in the case of scaling operations $a$\texttt{*}$b$\texttt{/}$c$, for which $a$\texttt{*}$b$ may be arbitrarily large (but the operands $a$, $b$, $c$ are still constrained to an absolute value at most $2^{31}-1$); \item parentheses may not appear after unary \texttt{+} or \texttt{-}, namely placing \texttt{+(} or \texttt{-(} at the start of an expression or after \texttt{+}, \texttt{-}, \texttt{*}, \texttt{/} or~\texttt{(} leads to an error. \end{itemize} Each integer operand can be either an integer variable (with no need for \cs{intUse}) or an integer denotation. For example both of the following give the same result because \cs{lFooSomeTl} expands to the integer denotation~$5$ while the integer variable \cs{lFooSomeInt} takes the value~$4$. \begin{demohigh} \intEval {5 + 4 * 3 - (3 + 4 * 5)} \end{demohigh} \begin{demohigh} \tlNew \lFooSomeTl \tlSet \lFooSomeTl {5} \intNew \lFooSomeInt \intSet \lFooSomeInt {4} \intEval {\lFooSomeTl + \lFooSomeInt * 3 - (3 + 4 * 5)} \end{demohigh} %\begin{texnote} %As all \TeX{} integers, integer operands can also be: %\tn{value}\Arg{\LaTeXe{} counter}; dimension or skip variables, %converted to integers in~\texttt{sp}; the character code of some %character given as \texttt{`}\meta{char} or %\texttt{`\textbackslash}\meta{char}; octal numbers given as %\texttt{'} followed by digits from \texttt{0} to \texttt{7}; or %hexadecimal numbers given as \verb|"| followed by digits and upper case %letters from \texttt{A} to~\texttt{F}. %\end{texnote} \section{Using Integer Expressions} \begin{function}{\intEval} \begin{syntax} \cs{intEval} \Arg{integer expression} \end{syntax} Evaluates the \meta{integer expression} and returns the result: for positive results an explicit sequence of decimal digits not starting with~\texttt{0}, for negative results \texttt{-}~followed by such a sequence, and \texttt{0}~for zero. For example \begin{demohigh} \intEval {(1+4)*(2-3)/5} \end{demohigh} \begin{demohigh} \intEval {\strCount{12\TeX34} - \tlCount{12\TeX34}} \end{demohigh} \end{function} \begin{function}{\intMathAdd} \begin{syntax} \cs{intMathAdd} \Arg{integer expression_1} \Arg{integer expression_2} \end{syntax} Adds \Arg{integer expression_1} and \Arg{integer expression_2}, and returns the result. For example \begin{demohigh} \intMathAdd {7} {3} \end{demohigh} \end{function} \begin{function}{\intMathSub} \begin{syntax} \cs{intMathSub} \Arg{integer expression_1} \Arg{integer expression_2} \end{syntax} Subtracts \Arg{integer expression_2} from \Arg{integer expression_1}, and returns the result. For example \begin{demohigh} \intMathSub {7} {3} \end{demohigh} \end{function} \begin{function}{\intMathMult} \begin{syntax} \cs{intMathMult} \Arg{integer expression_1} \Arg{integer expression_2} \end{syntax} Multiplies \Arg{integer expression_1} by \Arg{integer expression_2}, and returns the result. For example \begin{demohigh} \intMathMult {7} {3} \end{demohigh} \end{function} \begin{function}{\intMathDiv} \begin{syntax} \cs{intMathDiv} \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 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 {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} \end{syntax} Creates a new \meta{integer} or raises an error if the name is already taken. The declaration is global. The \meta{integer} is 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. \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} \end{syntax} Sets \meta{integer} to the value of \meta{integer expression}, which must evaluate to an integer (as described for \cs{intEval}). For example \begin{demohigh} \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} \end{syntax} Sets \meta{integer} to $0$. For example \begin{demohigh} \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} \end{syntax} Increases the value stored in \meta{integer} by $1$. For example \begin{demohigh} \intSet \lTmpaInt {5} \intIncr \lTmpaInt \intUse \lTmpaInt \end{demohigh} \end{function} \begin{function}{\intDecr} \begin{syntax} \cs{intDecr} \meta{integer} \end{syntax} Decreases the value stored in \meta{integer} by $1$. For example \begin{demohigh} \intSet \lTmpaInt {5} \intDecr \lTmpaInt \intUse \lTmpaInt \end{demohigh} \end{function} \begin{function}{\intAdd} \begin{syntax} \cs{intAdd} \meta{integer} \Arg{integer expression} \end{syntax} 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 \end{demohigh} \end{function} \begin{function}{\intSub} \begin{syntax} \cs{intSub} \meta{integer} \Arg{integer expression} \end{syntax} 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 \end{demohigh} \end{function} \section{Integer Step Functions} \begin{function}{\intReplicate} \begin{syntax} \cs{intReplicate} \Arg{integer expression} \Arg{tokens} \end{syntax} Evaluates the \meta{integer expression} (which should be zero or positive) and returns the resulting number of copies of the \meta{tokens}. \begin{demohigh} \intReplicate {4} {Hello} \end{demohigh} \end{function} %\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|). \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \intStepInline {1} {3} {30} { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \end{function} \begin{function}{\intStepOneInline} \begin{syntax} \cs{intStepOneInline} \Arg{initial value} \Arg{final value} \Arg{code} \end{syntax} This function first evaluates the \meta{initial value} 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 a fixed step of $1$ 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|). \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \intStepOneInline {1} {10} { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \end{function} \begin{function}{\intStepVariable} \begin{syntax} \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. 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 the \meta{code} should make use of the \meta{tl~var}. %For example %\begin{demohigh} %\IgnoreSpacesOn %\tlClear\lTmpaTl %\intStepVariable{1}{3}{30}\lTmpiTl{ % \tlPutRight\lTmpaTl{\expValue\lTmpiTl} % \tlPutRight\lTmpaTl{~} %} %\prgReturn{\expValue\lTmpaTl} %\IgnoreSpacesOff %\end{demohigh} \end{function} \begin{function}{\intStepOneVariable} \begin{syntax} \cs{intStepOneVariable} \Arg{initial value} \Arg{final value} \meta{tl var} \Arg{code} \end{syntax} This function first evaluates the \meta{initial value} 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 a fixed stop of $1$ between each \meta{value}), the \meta{code} is evaluated, with the \meta{tl~var} defined as the current \meta{value}. Thus the \meta{code} should make use of the \meta{tl~var}. \end{function} \section{Integer Conditionals} \begin{function}{\intIfExist,\intIfExistT,\intIfExistF,\intIfExistTF} \begin{syntax} \cs{intIfExist} \meta{integer} \cs{intIfExistT} \meta{integer} \Arg{true code} \cs{intIfExistF} \meta{integer} \Arg{false code} \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,\intIfOddT,\intIfOddF,\intIfOddTF} \begin{syntax} \cs{intIfOdd} \Arg{integer expression} \cs{intIfOddT} \Arg{integer expression} \Arg{true code} \cs{intIfOddF} \Arg{integer expression} \Arg{false code} \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,\intIfEvenT,\intIfEvenF,\intIfEvenTF} \begin{syntax} \cs{intIfEven} \Arg{integer expression} \cs{intIfEvenT} \Arg{integer expression} \Arg{true code} \cs{intIfEvenF} \Arg{integer expression} \Arg{false code} \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,\intCompareT,\intCompareF,\intCompareTF} \begin{syntax} \cs{intCompare} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2} \cs{intCompareT} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2} \Arg{true code} \cs{intCompareF} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2} \Arg{false code} \cs{intCompareTF} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2} \Arg{true code} \Arg{false code} \end{syntax} This function first evaluates each of the \meta{integer expressions} as described for \cs{intEval}. The two results are then compared using the \meta{relation}:\par {\centering\begin{tabular}{ll} Equal & \texttt{=} \\ Greater than & \texttt{>} \\ Less than & \texttt{<} \\ \end{tabular}\par} For example \begin{demohigh} \intCompareTF {2} > {1} {\prgReturn{Greater}} {\prgReturn{Less}} \intCompareTF {2} > {3} {\prgReturn{Greater}} {\prgReturn{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{The Syntax of Floating Point Expressions} A decimal floating point number is one which is stored as a significand and a separate exponent. The module implements expandably a wide set of arithmetic, trigonometric, and other operations on decimal floating point numbers, to be used within floating point expressions. Floating point expressions support the following operations with their usual precedence. \begin{itemize} \item Basic arithmetic: addition $x+y$, subtraction $x-y$, multiplication $x*y$, division $x/y$, square root $\sqrt{x}$, and parentheses. \item Comparison operators: $x\mathop{\mathtt{<}}y$, $x\mathop{\mathtt{<=}}y$, $x\mathop{\mathtt{>?}}y$, $x\mathop{\mathtt{!=}}y$ \emph{etc.} \item Boolean logic: sign $\operatorname{sign} x$, negation $\mathop{!}x$, conjunction $x\mathop{\&\&}y$, disjunction $x\mathop{\vert\vert}y$, ternary operator $x\mathop{?}y\mathop{:}z$. \item Exponentials: $\exp x$, $\ln x$, $x^y$, $\operatorname{logb} x$. \item Integer factorial: $\operatorname{fact} x$. \item Trigonometry: $\sin x$, $\cos x$, $\tan x$, $\cot x$, $\sec x$, $\csc x$ expecting their arguments in radians, and $\operatorname{sind} x$, $\operatorname{cosd} x$, $\operatorname{tand} x$, $\operatorname{cotd} x$, $\operatorname{secd} x$, $\operatorname{cscd} x$ expecting their arguments in degrees. \item Inverse trigonometric functions: $\operatorname{asin} x$, $\operatorname{acos} x$, $\operatorname{atan} x$, $\operatorname{acot} x$, $\operatorname{asec} x$, $\operatorname{acsc} x$ giving a result in radians, and $\operatorname{asind} x$, $\operatorname{acosd} x$, $\operatorname{atand} x$, $\operatorname{acotd} x$, $\operatorname{asecd} x$, $\operatorname{acscd} x$ giving a result in degrees. %\item [\emph{(not yet)}] Hyperbolic functions and their inverse %functions: $\sinh x$, $\cosh x$, $\tanh x$, $\coth x$, %$\operatorname{sech} x$, $\operatorname{csch}$, and %$\operatorname{asinh} x$, $\operatorname{acosh} x$, %$\operatorname{atanh} x$, $\operatorname{acoth} x$, %$\operatorname{asech} x$, $\operatorname{acsch} x$. \item Extrema: $\max(x_{1},x_{2},\ldots)$, $\min(x_{1},x_{2},\ldots)$, $\operatorname{abs}(x)$. \item Rounding functions, controlled by two optional values, $n$ (number of places, $0$ by default) and $t$ (behavior on a tie, $\nan$ by default): \begin{itemize} \item $\operatorname{trunc}(x,n)$ rounds towards zero, \item $\operatorname{floor}(x,n)$ rounds towards $-\infty$, \item $\operatorname{ceil}(x,n)$ rounds towards $+\infty$, \item $\operatorname{round}(x,n,t)$ rounds to the closest value, with ties rounded to an even value by default, towards zero if $t=0$, towards $+\infty$ if $t>0$ and towards $-\infty$ if $t<0$. \end{itemize} %And \emph{(not yet)} modulo, and \enquote{quantize}. \item Random numbers: $\mathop{rand}()$, $\mathop{randint}(m,n)$. \item Constants: \texttt{pi}, \texttt{deg} (one degree in radians). \item Dimensions, automatically expressed in points, \emph{e.g.}, \texttt{pc} is $12$. \item Automatic conversion (no need for \cs{intUse}, etc) of integer, dimension, and skip variables to floating point numbers, expressing dimensions in points and ignoring the stretch and shrink components of skips. \item Tuples: $(x_1,\ldots{},x_n)$ that can be stored in variables, added together, multiplied or divided by a floating point number, and nested. \end{itemize} Floating point numbers can be given either explicitly (in a form such as \verb|1.234e-34|, or \verb|-.0001|), or as a stored floating point variable, which is automatically replaced by its current value. A \enquote{floating point} is a floating point number or a tuple thereof. %See section \ref{sec:l3fp:fp-floats} for a description of what a floating point is, %section \ref{sec:l3fp:fp-precedence} for details about how an expression is %parsed, and section \ref{sec:l3fp:fp-operations} to know what the various %operations do. Some operations may raise exceptions (error messages), %described in section \ref{sec:l3fp:fp-exceptions}. An example of use could be the following. \begin{demohigh} \LaTeX{} can now compute: $ \frac{\sin(3.5)}{2} + 2\cdot 10^{-3} = \fpEval {sin(3.5)/2 + 2e-3} $. \end{demohigh} The operation \texttt{round} can be used to limit the result's precision. Adding $+0$ avoids the possibly undesirable output \verb|-0|, replacing it by \verb|+0|. %However, the \pkg{l3fp} module is mostly meant %as an underlying tool for higher-level commands. For example, one %could provide a function to typeset nicely the result of floating %point computations. %\begin{verbatim} %\documentclass{article} %\usepackage{xparse, siunitx} %\ExplSyntaxOn %\NewDocumentCommand { \calcnum } { m } %{ \num { \fp_to_scientific:n {#1} } } %\ExplSyntaxOff %\begin{document} %\calcnum { 2 pi * sin ( 2.3 ^ 5 ) } %\end{document} %\end{verbatim} %See the documentation of \pkg{siunitx} for various options of %\cs{num}. \section{Using 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|). \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \fpStepInline {1} {0.1} {1.5} { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \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{\expValue\lTmpiTl} % \tlPutRight\lTmpaTl{~} %} %\prgReturn{\expValue\lTmpaTl} %\IgnoreSpacesOff %\end{demohigh} \end{function} \section{Float Point Conditionals} \begin{function}{\fpIfExist,\fpIfExistT,\fpIfExistF,\fpIfExistTF} \begin{syntax} \cs{fpIfExist} \meta{fp var} \cs{fpIfExistT} \meta{fp var} \Arg{true code} \cs{fpIfExistF} \meta{fp var} \Arg{false code} \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 {\prgReturn{Yes}} {\prgReturn{No}} \fpIfExistTF \lMyUndefinedFp {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\fpCompare,\fpCompareT,\fpCompareF,\fpCompareTF} \begin{syntax} \cs{fpCompare} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \cs{fpCompareT} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \Arg{true code} \cs{fpCompareF} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \Arg{false code} \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} {\prgReturn{Greater}} {\prgReturn{Less}} \fpCompareTF {1} > {1.0001} {\prgReturn{Greater}} {\prgReturn{Less}} \end{demohigh} Two floating points $x$ and $y$ may obey four mutually exclusive relations: $xy$, 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}{\prgReturn{Is~a~Nan}}{\prgReturn{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|). \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \dimStepInline {1pt} {0.1pt} {1.5pt} { \tlPutRight \lTmpaTl {[#1]} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \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{\expValue\lTmpiTl} % \tlPutRight\lTmpaTl{~} %} %\prgReturn{\expValue\lTmpaTl} %\IgnoreSpacesOff %\end{demohigh} \end{function} \section{Dimension Conditionals} \begin{function}{\dimIfExist,\dimIfExistT,\dimIfExistF,\dimIfExistTF} \begin{syntax} \cs{dimIfExist} \meta{dimension} \cs{dimIfExistT} \meta{dimension} \Arg{true code} \cs{dimIfExistF} \meta{dimension} \Arg{false code} \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 {\prgReturn{Yes}} {\prgReturn{No}} \dimIfExistTF \lFooUndefinedDim {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\dimCompare,\dimCompareT,\dimCompareF,\dimCompareTF} \begin{syntax} \cs{dimCompare} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \cs{dimCompareT} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{true code} \cs{dimCompareF} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{false code} \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} {\prgReturn{Greater}} {\prgReturn{Less}} \dimCompareTF {1pt} > {1.0001pt} {\prgReturn{Greater}} {\prgReturn{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} {\prgReturn{Small}} {4pt+6pt} {\prgReturn{Medium}} {-10pt} {\prgReturn{Negative}} }{ \prgReturn {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} {\prgReturn{Small}} % {4pt+6pt} {\prgReturn{Medium}} % {-10pt} {\prgReturn{Negative}} %}{ % \prgReturn{[Some Match]} %}{ % \prgReturn{[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. \begin{codehigh} \clistNew \lFooSomeClist \end{codehigh} \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}. \begin{codehigh} \clistConst \cFooSomeClist {one,two,three} \end{codehigh} \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. \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. \begin{demohigh} \clistSet \lTmpaClist { a , b } \clistVarJoinExtended \lTmpaClist { and } {, } {, and } \end{demohigh} \begin{demohigh} \clistSet \lTmpaClist { a , b , , c , {de} , f } \clistVarJoinExtended \lTmpaClist { and } {, } {, and } \end{demohigh} %\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{demohigh} \clistJoinExtended { a , b } { and } {, } {, and } \end{demohigh} \begin{demohigh} \clistJoinExtended { a , b , , c , {de} , f } { and } {, } {, and } \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{items} %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. \begin{codehigh} \clistLog {one,two,three} \end{codehigh} \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. \begin{codehigh} \clistSet \lTmpaClist {one,two,three} \clistVarLog \lTmpaClist \end{codehigh} \end{function} \begin{function}{\clistShow} \begin{syntax} \cs{clistShow} \Arg{tokens} \end{syntax} Displays the entries in the comma list in the terminal. \begin{codehigh} \clistShow {one,two,three} \end{codehigh} \end{function} \begin{function}{\clistVarShow} \begin{syntax} \cs{clistVarShow} \meta{comma list} \end{syntax} Displays the entries in the \meta{comma list} in the terminal. \begin{codehigh} \clistSet \lTmpaClist {one,two,three} \clistVarShow \lTmpaClist \end{codehigh} \end{function} \section{Setting Comma Lists} \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|}|. \begin{demohigh} \clistSet \lTmpaClist {one,two,three} \clistVarJoin \lTmpaClist { and } \end{demohigh} \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. \begin{demohigh} \clistSet \lTmpaClist {one,two,three,four} \clistSetEq \lTmpbClist \lTmpaClist \clistVarJoin \lTmpbClist { and } \end{demohigh} \end{function} \begin{function}{\clistSetFromSeq} \begin{syntax} \cs{clistSetFromSeq} \meta{comma list} \meta{sequence} \end{syntax} Converts the data in the \meta{sequence} into a \meta{comma list}: the original \meta{sequence} is unchanged. Items which contain either spaces or commas are surrounded by braces. \begin{demohigh} \seqPutRight \lTmpaSeq {one} \seqPutRight \lTmpaSeq {two} \clistSetFromSeq \lTmpaClist \lTmpaSeq \clistVarJoin \lTmpaClist { and } \end{demohigh} \end{function} \begin{function}{\clistClear} \begin{syntax} \cs{clistClear} \meta{comma list} \end{syntax} Clears all items from the \meta{comma list}. \begin{codehigh} \clistSet \lTmpaClist {one,two,three,four} \clistClear \lTmpaClist \end{codehigh} \end{function} \begin{function}{\clistClearNew} \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. \begin{demohigh} \clistClearNew \lFooSomeClist \clistSet \lFooSomeClist {one,two,three} \clistVarJoin \lFooSomeClist { and } \end{demohigh} \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. \begin{demohigh} \clistSet \lTmpbClist {one,two} \clistSet \lTmpcClist {three,four} \clistConcat \lTmpaClist \lTmpbClist \lTmpcClist \clistVarJoin \lTmpaClist { + } \end{demohigh} \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|}|. \begin{demohigh} \clistSet \lTmpaClist {one,two} \clistPutLeft \lTmpaClist {zero} \clistVarJoin \lTmpaClist { and } \end{demohigh} \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|}|. \begin{demohigh} \clistSet \lTmpaClist {one,two} \clistPutRight \lTmpaClist {three} \clistVarJoin \lTmpaClist { and } \end{demohigh} \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}{\clistVarRemoveDuplicates} \begin{syntax} \cs{clistVarRemoveDuplicates} \meta{comma list} \end{syntax} Removes duplicate items from the \meta{comma list}, leaving the left most copy of each item in the \meta{comma list}. The \meta{item} comparison takes place on a token basis, as for \cs{tlIfEqTF}. \begin{demohigh} \clistSet \lTmpaClist {one,two,one,two,three} \clistVarRemoveDuplicates \lTmpaClist \clistVarJoin \lTmpaClist {,} \end{demohigh} %\begin{texnote} %This function iterates through every item in the \meta{comma list} and %does a comparison with the \meta{items} already checked. It is therefore %relatively slow with large comma lists. %Furthermore, it may fail if any of the items in the %\meta{comma list} contains \verb|{|, \verb|}|, or \verb|#| %(assuming the usual \TeX{} category codes apply). %\end{texnote} \end{function} \begin{function}{\clistVarRemoveAll} \begin{syntax} \cs{clistVarRemoveAll} \meta{comma list} \Arg{item} \end{syntax} Removes every occurrence of \meta{item} from the \meta{comma list}. The \meta{item} comparison takes place on a token basis, as for \cs{tlIfEqTF}. \begin{demohigh} \clistSet \lTmpaClist {one,two,one,two,three} \clistVarRemoveAll \lTmpaClist {two} \clistVarJoin \lTmpaClist {,} \end{demohigh} %\begin{texnote} %The function may fail if the \meta{item} contains \verb|{|, \verb|}|, or \verb|#| %(assuming the usual \TeX{} category codes apply). %\end{texnote} \end{function} \begin{function}{\clistVarReverse} \begin{syntax} \cs{clistVarReverse} \meta{comma list} \end{syntax} Reverses the order of items stored in the \meta{comma list}. \begin{demohigh} \clistSet \lTmpaClist {one,two,one,two,three} \clistVarReverse \lTmpaClist \clistVarJoin \lTmpaClist {,} \end{demohigh} \end{function} %\begin{function}{\clistVarSort} %\begin{syntax} %\cs{clistVarSort} \meta{clist var} \Arg{comparison code} %\end{syntax} %Sorts the items in the \meta{clist var} according to the %\meta{comparison code}, and assigns the result to %\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. \begin{demohigh} \clistSet \lTmpaClist {one,two,three,four} \clistVarCount \lTmpaClist \end{demohigh} \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{demohigh} \tlSet \lTmpaTl {\clistItem {one,two,three,four} {3}} \tlUse \lTmpaTl \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %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{demohigh} \clistSet \lTmpaClist {one,two,three,four} \tlSet \lTmpaTl {\clistVarItem \lTmpaClist {3}} \tlUse \lTmpaTl \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %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{demohigh} \tlSet \lTmpaTl {\clistRandItem {one,two,three,four,five,six}} \tlUse \lTmpaTl \tlSet \lTmpaTl {\clistRandItem {one,two,three,four,five,six}} \tlUse \lTmpaTl \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %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} \begin{syntax} \cs{clistGet} \meta{comma list} \meta{token list variable} \end{syntax} Stores the left-most item from the \meta{comma list} in the \meta{token list variable} without removing it from the \meta{comma list}. The \meta{token list variable} is assigned locally. If the \meta{comma list} is empty the \meta{token list variable} is set to the marker value \cs{qNoValue}. \begin{demohigh} \clistSet \lTmpaClist {two,three,four} \clistGet \lTmpaClist \lTmpaTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\clistGetT,\clistGetF,\clistGetTF} \begin{syntax} \cs{clistGetT} \meta{comma list} \meta{token list variable} \meta{true code} \cs{clistGetF} \meta{comma list} \meta{token list variable} \meta{false code} \cs{clistGetTF} \meta{comma list} \meta{token list variable} \meta{true code} \meta{false code} \end{syntax} If the \meta{comma list} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{comma list} is non-empty, stores the left-most item from the \meta{comma list} in the \meta{token list variable} without removing it from the \meta{comma list}. The \meta{token list variable} is assigned locally. \begin{demohigh} \clistSet \lTmpaClist {two,three,four} \clistGetTF \lTmpaClist \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\clistPop} \begin{syntax} \cs{clistPop} \meta{comma list} \meta{token list variable} \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 \meta{token list variable} is set to the marker value \cs{qNoValue}. \begin{demohigh} \clistSet \lTmpaClist {two,three,four} \clistPop \lTmpaClist \lTmpaTl \clistVarJoin \lTmpaClist {,} \end{demohigh} \end{function} \begin{function}{\clistPopT,\clistPopF,\clistPopTF} \begin{syntax} \cs{clistPopT} \meta{comma list} \meta{token list variable} \Arg{true code} \cs{clistPopF} \meta{comma list} \meta{token list variable} \Arg{false code} \cs{clistPopTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{comma list} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{comma list} is non-empty, pops the top item from the \meta{comma list} in the \meta{token list variable}, \emph{i.e.} removes the item from the \meta{comma list}. The \meta{token list variable} is assigned locally. \begin{demohigh} \clistSet \lTmpaClist {two,three,four} \clistPopTF \lTmpaClist \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \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. \begin{demohigh} \clistSet \lTmpaClist {two,three,four} \clistPush \lTmpaClist {zero,one} \clistVarJoin \lTmpaClist {|} \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \tlClear \lTmpaTl \clistMapInline {one,two,three} { \tlPutRight \lTmpaTl {(#1)} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \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. \begin{demohigh} \IgnoreSpacesOn \clistMapVariable {one,two,three} \lTmpiTl { \tlPutRight \gTmpaTl {\expWhole {(\lTmpiTl)}} } \tlUse \gTmpaTl \IgnoreSpacesOff \end{demohigh} \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 { } } %{ %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,\clistIfExistT,\clistIfExistF,\clistIfExistTF} \begin{syntax} \cs{clistIfExist} \meta{comma list} \cs{clistIfExistT} \meta{comma list} \Arg{true code} \cs{clistIfExistF} \meta{comma list} \Arg{false code} \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. \begin{demohigh} \clistIfExistTF \lTmpaClist {\prgReturn{Yes}} {\prgReturn{No}} \clistIfExistTF \lFooUndefinedClist {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\clistIfEmpty,\clistIfEmptyT,\clistIfEmptyF,\clistIfEmptyTF} \begin{syntax} \cs{clistIfEmpty} \Arg{comma list} \cs{clistIfEmptyT} \Arg{comma list} \Arg{true code} \cs{clistIfEmptyF} \Arg{comma list} \Arg{false code} \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. \begin{demohigh} \clistIfEmptyTF {one,two} {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \clistIfEmptyTF { , } {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\clistVarIfEmpty,\clistVarIfEmptyT,\clistVarIfEmptyF,\clistVarIfEmptyTF} \begin{syntax} \cs{clistVarIfEmpty} \meta{comma list} \cs{clistVarIfEmptyT} \meta{comma list} \Arg{true code} \cs{clistVarIfEmptyF} \meta{comma list} \Arg{false code} \cs{clistVarIfEmptyTF} \meta{comma list} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{comma list} is empty (containing no items). \begin{demohigh} \clistSet \lTmpaClist {one,two} \clistVarIfEmptyTF \lTmpaClist {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \clistClear \lTmpaClist \clistVarIfEmptyTF \lTmpaClist {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\clistIfIn,\clistIfInT,\clistIfInF,\clistIfInTF} \begin{syntax} \cs{clistIfIn} \Arg{comma list} \Arg{item} \cs{clistIfInT} \Arg{comma list} \Arg{item} \Arg{true code} \cs{clistIfInF} \Arg{comma list} \Arg{item} \Arg{false code} \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} {\prgReturn{Yes}} {\prgReturn{No}} \clistIfInTF { a , {b} , {b} , c } {d} {\prgReturn{Yes}} {\prgReturn{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,\clistVarIfInT,\clistVarIfInF,\clistVarIfInTF} \begin{syntax} \cs{clistVarIfIn} \meta{comma list} \Arg{item} \cs{clistVarIfInT} \meta{comma list} \Arg{item} \Arg{true code} \cs{clistVarIfInF} \meta{comma list} \Arg{item} \Arg{false code} \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{demohigh} \clistSet \lTmpaClist {one,two} \clistVarIfInTF \lTmpaClist {one} {\prgReturn{Yes}} {\prgReturn{No}} \clistVarIfInTF \lTmpaClist {three} {\prgReturn{Yes}} {\prgReturn{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} \chapter{Sequences and Stacks (\texttt{Seq})} \section{Constant and Scratch Sequences} \begin{variable}{\cEmptySeq} Constant that is always empty. \end{variable} \begin{variable}{\lTmpaSeq,\lTmpbSeq,\lTmpcSeq,\lTmpiSeq,\lTmpjSeq,\lTmpkSeq} Scratch sequences for local assignment. These are never used by the \verb!functional! package, and so are safe for use with any function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaSeq,\gTmpbSeq,\gTmpcSeq,\gTmpiSeq,\gTmpjSeq,\gTmpkSeq} Scratch sequences for global assignment. These are never used by the \verb!functional! package, and so are safe for use with any function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \section{Creating and Using Sequences} \begin{function}{\seqNew} \begin{syntax} \cs{seqNew} \meta{sequence} \end{syntax} Creates a new \meta{sequence} or raises an error if the name is already taken. The declaration is global. The \meta{sequence} initially contains no items. \begin{codehigh} \seqNew \lFooSomeSeq \end{codehigh} \end{function} \begin{function}{\seqConstFromClist} \begin{syntax} \cs{seqConstFromClist} \meta{seq var} \Arg{comma-list} \end{syntax} Creates a new constant \meta{seq var} or raises an error if the name is already taken. The \meta{seq var} is set globally to contain the items in the \meta{comma list}. \begin{codehigh} \seqConstFromClist \cFooSomeSeq {one,two,three} \end{codehigh} \end{function} \begin{function}{\seqVarJoin} \begin{syntax} \cs{seqVarJoin} \meta{seq var} \Arg{separator} \end{syntax} Returns the contents of the \meta{seq var}, with the \meta{separator} between the items. If the sequence has a single item, it is returned with no \meta{separator}, and an empty sequence returns nothing. An error is raised if the variable does not exist or if it is invalid. \begin{demohigh} \seqSetSplit \lTmpaSeq {|} {a|b|c|{de}|f} \seqVarJoin \lTmpaSeq { and } \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{items} %do not expand further when appearing in an \texttt{x}-type %or \texttt{e}-type argument expansion. %\end{texnote} \end{function} \begin{function}{\seqVarJoinExtended} \begin{syntax} \cs{seqVarJoinExtended} \meta{seq var} \Arg{separator between two} \Arg{separator between more than two} \Arg{separator between final two} \end{syntax} Returns the contents of the \meta{seq var}, with the appropriate \meta{separator} between the items. Namely, if the sequence has more than two items, the \meta{separator between more than two} is placed between each pair of items except the last, for which the \meta{separator between final two} is used. If the sequence has exactly two items, then they are joined with the \meta{separator between two} and returned. If the sequence has a single item, it is returned, and an empty sequence returns nothing. An error is raised if the variable does not exist or if it is invalid. \begin{demohigh} \seqSetSplit \lTmpaSeq {|} {a|b|c|{de}|f} \seqVarJoinExtended \lTmpaSeq { and } {, } {, and } \end{demohigh} The first separator argument is not used in this case because the sequence has more than $2$ items. %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{items} %do not expand further when appearing in an \texttt{x}-type %or \texttt{e}-type argument expansion. %\end{texnote} \end{function} \section{Viewing Sequences} \begin{function}{\seqVarLog} \begin{syntax} \cs{seqVarLog} \meta{sequence} \end{syntax} Writes the entries in the \meta{sequence} in the log file. \begin{codehigh} \seqVarLog \lFooSomeSeq \end{codehigh} \end{function} \begin{function}{\seqVarShow} \begin{syntax} \cs{seqVarShow} \meta{sequence} \end{syntax} Displays the entries in the \meta{sequence} in the terminal. \begin{codehigh} \seqVarShow \lFooSomeSeq \end{codehigh} \end{function} \section{Setting Sequences} \begin{function}{\seqSetFromClist} \begin{syntax} \cs{seqSetFromClist} \meta{sequence} \meta{comma-list} \end{syntax} Converts the data in the \meta{comma list} into a \meta{sequence}: the original \meta{comma list} is unchanged. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,three} \seqVarJoin \lTmpaSeq { and } \end{demohigh} \end{function} \begin{function}{\seqSetSplit} \begin{syntax} \cs{seqSetSplit} \meta{sequence} \Arg{delimiter} \Arg{token list} \end{syntax} Splits the \meta{token list} into \meta{items} separated by \meta{delimiter}, and assigns the result to the \meta{sequence}. Spaces on both sides of each \meta{item} are ignored, then one set of outer braces is removed (if any); this space trimming behaviour is identical to that of \pkg{Clist} functions. Empty \meta{items} are preserved by \cs{seqSetSplit}, and can be removed afterwards using \cs{seqVarRemoveAll} \meta{sequence} \verb|{}|. The \meta{delimiter} may not contain \verb|{|, \verb|}| or \verb|#| (assuming \TeX{}'s normal category code r\'egime). If the \meta{delimiter} is empty, the \meta{token list} is split into \meta{items} as a \meta{token list}. %See also \cs{seqSetSplitKeepSpaces}, which omits space stripping. \begin{demohigh} \seqSetSplit \lTmpaSeq {,} {1,2,3} \seqVarJoin \lTmpaSeq { and } \end{demohigh} \end{function} \begin{function}{\seqSetEq} \begin{syntax} \cs{seqSetEq} \meta{sequence_1} \meta{sequence_2} \end{syntax} Sets the content of \meta{sequence_1} equal to that of \meta{sequence_2}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,three,four} \seqSetEq \lTmpbSeq \lTmpaSeq \seqVarJoin \lTmpbSeq { and } \end{demohigh} \end{function} \begin{function}{\seqClear} \begin{syntax} \cs{seqClear} \meta{sequence} \end{syntax} Clears all items from the \meta{sequence}. \begin{codehigh} \seqClear \lTmpaSeq \end{codehigh} \end{function} \begin{function}{\seqClearNew} \begin{syntax} \cs{seqClearNew} \meta{sequence} \end{syntax} Ensures that the \meta{sequence} exists globally by applying \cs{seqNew} if necessary, then applies \cs{seqClear} to leave the \meta{sequence} empty. \begin{demohigh} \seqClearNew \lFooSomeSeq \seqSetFromClist \lFooSomeSeq {one,two,three} \seqVarJoin \lFooSomeSeq { and } \end{demohigh} \end{function} \begin{function}{\seqConcat} \begin{syntax} \cs{seqConcat} \meta{sequence_1} \meta{sequence_2} \meta{sequence_3} \end{syntax} Concatenates the content of \meta{sequence_2} and \meta{sequence_3} together and saves the result in \meta{sequence_1}. The items in \meta{sequence_2} are placed at the left side of the new sequence. \begin{demohigh} \seqSetFromClist \lTmpbSeq {one,two} \seqSetFromClist \lTmpcSeq {three,four} \seqConcat \lTmpaSeq \lTmpbSeq \lTmpcSeq \seqVarJoin \lTmpaSeq {, } \end{demohigh} \end{function} %\begin{function}{\seqSetSplitKeepSpaces} %\begin{syntax} %\cs{seqSetSplitKeepSpaces} \meta{sequence} \Arg{delimiter} \Arg{token list} %\end{syntax} %Splits the \meta{token list} into \meta{items} separated %by \meta{delimiter}, and assigns the result to the \meta{sequence}. %One set of outer braces is removed (if any) but any surrounding spaces %are retained: any braces \emph{inside} one or more spaces are %therefore kept. Empty \meta{items} are preserved by %\cs{seqSetSplitKeepSpaces}, and can be removed afterwards using %\cs{seqVarRemoveAll} \meta{sequence} \verb|{}|. %The \meta{delimiter} may not contain \verb|{|, \verb|}| or \verb|#| %(assuming \TeX{}'s normal category code r\'egime). %If the \meta{delimiter} is empty, the \meta{token list} is split %into \meta{items} as a \meta{token list}. %%See also \cs{seqSetSplit}, which removes spaces around the delimiters. %\end{function} \begin{function}{\seqPutLeft} \begin{syntax} \cs{seqPutLeft} \meta{sequence} \Arg{item} \end{syntax} Appends the \meta{item} to the left of the \meta{sequence}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two} \seqPutLeft \lTmpaSeq {zero} \seqVarJoin \lTmpaSeq { and } \end{demohigh} \end{function} \begin{function}{\seqPutRight} \begin{syntax} \cs{seqPutRight} \meta{sequence} \Arg{item} \end{syntax} Appends the \meta{item} to the right of the \meta{sequence}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two} \seqPutRight \lTmpaSeq {three} \seqVarJoin \lTmpaSeq { and } \end{demohigh} \end{function} \section{Modifying Sequences} While sequences are normally used as ordered lists, it may be necessary to modify the content. The functions here may be used to update sequences, while retaining the order of the unaffected entries. \begin{function}{\seqVarRemoveDuplicates} \begin{syntax} \cs{seqVarRemoveDuplicates} \meta{sequence} \end{syntax} Removes duplicate items from the \meta{sequence}, leaving the left most copy of each item in the \meta{sequence}. The \meta{item} comparison takes place on a token basis, as for \cs{tlIfEqTF}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,one,two,three} \seqVarRemoveDuplicates \lTmpaSeq \seqVarJoin \lTmpaSeq {,} \end{demohigh} %\begin{texnote} %This function iterates through every item in the \meta{sequence} and %does a comparison with the \meta{items} already checked. It is therefore %relatively slow with large sequences. %\end{texnote} \end{function} \begin{function}{\seqVarRemoveAll} \begin{syntax} \cs{seqVarRemoveAll} \meta{sequence} \Arg{item} \end{syntax} Removes every occurrence of \meta{item} from the \meta{sequence}. The \meta{item} comparison takes place on a token basis, as for \cs{tlIfEqTF}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,one,two,three} \seqVarRemoveAll \lTmpaSeq {two} \seqVarJoin \lTmpaSeq {,} \end{demohigh} \end{function} \begin{function}{\seqVarReverse} \begin{syntax} \cs{seqVarReverse} \meta{sequence} \end{syntax} Reverses the order of the items stored in the \meta{sequence}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,one,two,three} \seqVarReverse \lTmpaSeq \seqVarJoin \lTmpaSeq {,} \end{demohigh} \end{function} %\begin{function}{\seqVarSort} %\begin{syntax} %\cs{seqVarSort} \meta{sequence} \Arg{comparison code} %\end{syntax} %Sorts the items in the \meta{sequence} according to the %\meta{comparison code}, and assigns the result to %\meta{sequence}. The details of sorting comparison are %described in Section \ref{sec:l3sort:mech}. %\end{function} %\begin{function}{\seqVarShuffle} %\begin{syntax} %\cs{seqVarShuffle} \meta{seq var} %\end{syntax} %Sets the \meta{seq var} to the result of placing the items of the %\meta{seq var} in a random order. Each item is (roughly) as likely %to end up in any given position. %\begin{texnote} %For sequences with more than $13$ items or so, only a small %proportion of all possible permutations can be reached, because %the random seed \cs{sys_rand_seed:} only has $28$-bits. The use %of \tn{toks} internally means that sequences with more than %$32767$ or $65535$ items (depending on the engine) cannot be %shuffled. %\end{texnote} %\end{function} \section{Working with the Contents of Sequences} \begin{function}{\seqVarCount} \begin{syntax} \cs{seqVarCount} \meta{sequence} \end{syntax} Returns the number of items in the \meta{sequence} as an \meta{integer denotation}. The total number of items in a \meta{sequence} includes those which are empty and duplicates, \emph{i.e.} every item in a \meta{sequence} is unique. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,three,four} \seqVarCount \lTmpaSeq \end{demohigh} \end{function} \begin{function}{\seqVarItem} \begin{syntax} \cs{seqVarItem} \meta{sequence} \Arg{integer expression} \end{syntax} Indexing items in the \meta{sequence} from $1$ at the top (left), this function evaluates the \meta{integer expression} and returns the appropriate item from the sequence. If the \meta{integer expression} is negative, indexing occurs from the bottom (right) of the sequence. If the \meta{integer expression} is larger than the number of items in the \meta{sequence} (as calculated by \cs{seqVarCount}) then the function returns nothing. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,three,four} \tlSet \lTmpaTl {\seqVarItem \lTmpaSeq {3}} \tlUse \lTmpaTl \end{demohigh} %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %does not expand further when appearing in an \texttt{x}-type %or \texttt{e}-type argument expansion. %\end{texnote} \end{function} \begin{function}{\seqVarRandItem} \begin{syntax} \cs{seqVarRandItem} \meta{seq var} \end{syntax} Selects a pseudo-random item of the \meta{sequence}. If the \meta{sequence} is empty the result is empty. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two,three,four,five,six} \tlSet \lTmpaTl {\seqVarRandItem \lTmpaSeq} \tlUse \lTmpaTl \tlSet \lTmpaTl {\seqVarRandItem \lTmpaSeq} \tlUse \lTmpaTl \end{demohigh} %This is not available in older versions of \XeTeX{}. %\begin{texnote} %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{item} %does not expand further when appearing in an \texttt{x}-type %or \texttt{e}-type argument expansion. %\end{texnote} \end{function} \section{Sequences as Stacks} Sequences can be used as stacks, where data is pushed to and popped from the top of the sequence. (The left of a sequence is the top, for performance reasons.) The stack functions for sequences are not intended to be mixed with the general ordered data functions detailed in the previous section: a sequence should either be used as an ordered data type or as a stack, but not in both ways. \begin{function}{\seqGet} \begin{syntax} \cs{seqGet} \meta{sequence} \meta{token list variable} \end{syntax} Reads the top item from a \meta{sequence} into the \meta{token list variable} without removing it from the \meta{sequence}. The \meta{token list variable} is assigned locally. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGet \lTmpaSeq \lTmpaTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\seqGetT,\seqGetF,\seqGetTF} \begin{syntax} \cs{seqGetT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqGetF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqGetTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, stores the top item from a \meta{sequence} in the \meta{token list variable} without removing it from the \meta{sequence}. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGetTF \lTmpaSeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqPop} \begin{syntax} \cs{seqPop} \meta{sequence} \meta{token list variable} \end{syntax} Pops the top item from a \meta{sequence} into the \meta{token list variable}. the \meta{token list variable} is assigned locally. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqPop \lTmpaSeq \lTmpaTl \seqVarJoin \lTmpaSeq {,} \end{demohigh} \end{function} \begin{function}{\seqPopT,\seqPopF,\seqPopTF} \begin{syntax} \cs{seqPopT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqPopF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqPopTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, pops the top item from the \meta{sequence} in the \meta{token list variable}, \emph{i.e.} removes the item from the \meta{sequence}. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqPopTF \cEmptySeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqPush} \begin{syntax} \cs{seqPush} \meta{sequence} \Arg{item} \end{syntax} Adds the \Arg{item} to the top of the \meta{sequence}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqPush \lTmpaSeq {one} \seqVarJoin \lTmpaSeq {|} \end{demohigh} You can only push one item to the \meta{sequence} with \cs{seqPush}, which is different from \cs{ClistPush}. \end{function} \section{Recovering Items from Sequences} Items can be recovered from either the left or the right of sequences. For implementation reasons, the actions at the left of the sequence are faster than those acting on the right. These functions all assign the recovered material locally. \begin{function}{\seqGetLeft} \begin{syntax} \cs{seqGetLeft} \meta{sequence} \meta{token list variable} \end{syntax} Stores the left-most item from a \meta{sequence} in the \meta{token list variable} without removing it from the \meta{sequence}. The \meta{token list variable} is assigned locally. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGetLeft \lTmpaSeq \lTmpaTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\seqGetLeftT,\seqGetLeftF,\seqGetLeftTF} \begin{syntax} \cs{seqGetLeftT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqGetLeftF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqGetLeftTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, stores the left-most item from the \meta{sequence} in the \meta{token list variable} without removing it from the \meta{sequence}, then leaves the \meta{true code} in the input stream. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGetLeftTF \lTmpaSeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqGetRight} \begin{syntax} \cs{seqGetRight} \meta{sequence} \meta{token list variable} \end{syntax} Stores the right-most item from a \meta{sequence} in the \meta{token list variable} without removing it from the \meta{sequence}. The \meta{token list variable} is assigned locally. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGetRight \lTmpaSeq \lTmpaTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\seqGetRightT,\seqGetRightF,\seqGetRightTF} \begin{syntax} \cs{seqGetRightT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqGetRightF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqGetRightTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, stores the right-most item from the \meta{sequence} in the \meta{token list variable} without removing it from the \meta{sequence}, then leaves the \meta{true code} in the input stream. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqGetRightTF \lTmpaSeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqPopLeft} \begin{syntax} \cs{seqPopLeft} \meta{sequence} \meta{token list variable} \end{syntax} Pops the left-most item from a \meta{sequence} into the \meta{token list variable}, \emph{i.e.} removes the item from the sequence and stores it in the \meta{token list variable}. The assignment of the \meta{token list variable} is local. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqPopLeft \lTmpaSeq \lTmpaTl \seqVarJoin \lTmpaSeq {,} \end{demohigh} \end{function} \begin{function}{\seqPopLeftT,\seqPopLeftF,\seqPopLeftTF} \begin{syntax} \cs{seqPopLeftT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqPopLeftF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqPopLeftTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, pops the left-most item from the \meta{sequence} in the \meta{token list variable}, \emph{i.e.} removes the item from the \meta{sequence}, then leaves the \meta{true code} in the input stream. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqPopLeftTF \cEmptySeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqPopRight} \begin{syntax} \cs{seqPopRight} \meta{sequence} \meta{token list variable} \end{syntax} Pops the right-most item from a \meta{sequence} into the \meta{token list variable}, \emph{i.e.} removes the item from the sequence and stores it in the \meta{token list variable}. The assignment of the \meta{token list variable} is local. If \meta{sequence} is empty the \meta{token list variable} is set to the special marker \cs{qNoValue}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {two,three,four} \seqPopRight \lTmpaSeq \lTmpaTl \seqVarJoin \lTmpaSeq {,} \end{demohigh} \end{function} \begin{function}{\seqPopRightT,\seqPopRightF,\seqPopRightTF} \begin{syntax} \cs{seqPopRightT} \meta{sequence} \meta{token list variable} \Arg{true code} \cs{seqPopRightF} \meta{sequence} \meta{token list variable} \Arg{false code} \cs{seqPopRightTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{sequence} is empty, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{sequence} is non-empty, pops the right-most item from the \meta{sequence} in the \meta{token list variable}, \emph{i.e.} removes the item from the \meta{sequence}, then leaves the \meta{true code} in the input stream. The \meta{token list variable} is assigned locally. \begin{demohigh} \seqPopRightTF \cEmptySeq \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \section{Mapping over Sequences} %All mappings are done at the current group level, \emph{i.e.} any %local assignments made by the \meta{function} or \meta{code} discussed %below remain in effect after the loop. %\begin{function}{\seqVarMapFunction} %\begin{syntax} %\cs{seqVarMapFunction} \meta{sequence} \meta{function} %\end{syntax} %Applies \meta{function} to every \meta{item} stored in the %\meta{sequence}. The \meta{function} will receive one argument for %each iteration. The \meta{items} are returned from left to right. %To pass further arguments to the \meta{function}, see \cs{seqVarMapTokens}. %The function \cs{seqVarMapInline} is faster than %\cs{seqVarMapFunction} for sequences with more than about $10$ items. %\end{function} \begin{function}{\seqVarMapInline} \begin{syntax} \cs{seqVarMapInline} \meta{sequence} \Arg{inline function} \end{syntax} Applies \meta{inline function} to every \meta{item} stored within the \meta{sequence}. The \meta{inline function} should consist of code which will receive the \meta{item} as \verb|#1|. The \meta{items} are returned from left to right. \begin{demohigh} \IgnoreSpacesOn \seqSetFromClist \lTmpkSeq {one,two,three} \tlClear \lTmpaTl \seqVarMapInline \lTmpkSeq { \tlPutRight \lTmpaTl {(#1)} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \end{function} %\begin{function}{\seqVarMapTokens} %\begin{syntax} %\cs{seqVarMapTokens} \meta{sequence} \Arg{code} %\end{syntax} %Analogue of \cs{seqVarMapFunction} which maps several tokens %instead of a single function. The \meta{code} receives each item in %the \meta{sequence} as a trailing brace group. For instance, %\begin{verbatim} %\seqVarMapTokens \lMySeq { \prgReplicate { 2 } } %\end{verbatim} %expands to twice each item in the \meta{sequence}: for each item in %\verb|\l_my_seq| the function \cs{PrgReplicate} receives \verb|2| and %\meta{item} as its two arguments. The function %\cs{seqVarMapInline} is typically faster but it is not expandable. %\end{function} \begin{function}{\seqVarMapVariable} \begin{syntax} \cs{seqVarMapVariable} \meta{sequence} \meta{variable} \Arg{code} \end{syntax} Stores each \meta{item} of the \meta{sequence} in turn in the (token list) \meta{variable} and applies the \meta{code}. The \meta{code} will usually make use of the \meta{variable}, but this is not enforced. The assignments to the \meta{variable} are local. Its value after the loop is the last \meta{item} in the \meta{sequence}, or its original value if the \meta{sequence} is empty. The \meta{items} are returned from left to right. \begin{demohigh} \IgnoreSpacesOn \intZero \lTmpaInt \seqSetFromClist \lTmpaSeq {1,3,7} \seqVarMapVariable \lTmpaSeq \lTmpiTl { \intAdd \lTmpaInt {\lTmpiTl*\lTmpiTl} } \intUse \lTmpaInt \IgnoreSpacesOff \end{demohigh} \end{function} %\begin{function}{\seqVarMapIndexedFunction} %\begin{syntax} %\cs{seqVarMapIndexedFunction} \meta{seq var} \meta{function} %\end{syntax} %Applies \meta{function} to every entry in the \meta{sequence %variable}. The \meta{function} should have signature |:nn|. It %receives two arguments for each iteration: the \meta{index} (namely %\verb|1| for the first entry, then \verb|2| and so on) and the \meta{item}. %\end{function} %\begin{function}{\seqVarMapIndexedInline} %\begin{syntax} %\cs{seqVarMapIndexedInline} \meta{seq var} \Arg{inline function} %\end{syntax} %Applies \meta{inline function} to every entry in the \meta{sequence %variable}. The \meta{inline function} should consist of code which %receives the \meta{index} (namely \verb|1| for the first entry, then \verb|2| %and so on) as \verb|#1| and the \meta{item} as \verb|#2|. %\end{function} %\begin{function}{\seqMapBreak} %\begin{syntax} %\cs{seqMapBreak} %\end{syntax} %Used to terminate a seq map function before all %entries in the \meta{sequence} have been processed. This %normally takes place within a conditional statement, for example %\begin{verbatim} %\seq_map_inline:Nn \l_my_seq %{ %\str_if_eq:nnTF { #1 } { bingo } %{ \seq_map_break: } %{ %Do something useful %} %} %\end{verbatim} %Use outside of a seq map scenario leads to low %level \TeX{} errors. %\begin{texnote} %When the mapping is broken, additional tokens may be inserted %before further items are taken %from the input stream. This depends on the design of the mapping %function. %\end{texnote} %\end{function} %\begin{function}{\seqMapBreakDo} %\begin{syntax} %\cs{seqMapBreakDo} \Arg{code} %\end{syntax} %Used to terminate a seq map function before all %entries in the \meta{sequence} have been processed, inserting %the \meta{code} after the mapping has ended. This %normally takes place within a conditional statement, for example %\begin{verbatim} %\seq_map_inline:Nn \l_my_seq %{ %\str_if_eq:nnTF { #1 } { bingo } %{ \seq_map_break:n { } } %{ %Do something useful %} %} %\end{verbatim} %Use outside of a seq map scenario leads to low %level \TeX{} errors. %\begin{texnote} %When the mapping is broken, additional tokens may be inserted %before the \meta{code} is %inserted into the input stream. %This depends on the design of the mapping function. %\end{texnote} %\end{function} %\begin{function} %{\seq_set_map:NNn, \seq_gset_map:NNn} %\begin{syntax} %\cs{seq_set_map:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function} %\end{syntax} %Applies \meta{inline function} to every \meta{item} stored %within the \meta{sequence_2}. The \meta{inline function} should %consist of code which will receive the \meta{item} as \verb|#1|. %The sequence resulting applying \meta{inline function} to each %\meta{item} is assigned to \meta{sequence_1}. %\begin{texnote} %Contrarily to other mapping functions, \cs{seq_map_break:} cannot %be used in this function, and would lead to low-level \TeX{} errors. %\end{texnote} %\end{function} %\begin{function}[added = 2020-07-16] %{\seq_set_map_x:NNn, \seq_gset_map_x:NNn} %\begin{syntax} %\cs{seq_set_map_x:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function} %\end{syntax} %Applies \meta{inline function} to every \meta{item} stored %within the \meta{sequence_2}. The \meta{inline function} should %consist of code which will receive the \meta{item} as \verb|#1|. %The sequence resulting from \texttt{x}-expanding %\meta{inline function} applied to each \meta{item} %is assigned to \meta{sequence_1}. As such, the code %in \meta{inline function} should be expandable. %\begin{texnote} %Contrarily to other mapping functions, \cs{seq_map_break:} cannot %be used in this function, and would lead to low-level \TeX{} errors. %\end{texnote} %\end{function} \section{Sequence Conditionals} \begin{function}{\seqIfExist,\seqIfExistT,\seqIfExistF,\seqIfExistTF} \begin{syntax} \cs{seqIfExist} \meta{sequence} \cs{seqIfExistT} \meta{sequence} \Arg{true code} \cs{seqIfExistF} \meta{sequence} \Arg{false code} \cs{seqIfExistTF} \meta{sequence} \Arg{true code} \Arg{false code} \end{syntax} Tests whether the \meta{sequence} is currently defined. This does not check that the \meta{sequence} really is a sequence variable. \begin{demohigh} \seqIfExistTF \lTmpaSeq {\prgReturn{Yes}} {\prgReturn{No}} \seqIfExistTF \lFooUndefinedSeq {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\seqVarIfEmpty,\seqVarIfEmptyT,\seqVarIfEmptyF,\seqVarIfEmptyTF} \begin{syntax} \cs{seqVarIfEmpty} \meta{sequence} \cs{seqVarIfEmptyT} \meta{sequence} \Arg{true code} \cs{seqVarIfEmptyF} \meta{sequence} \Arg{false code} \cs{seqVarIfEmptyTF} \meta{sequence} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{sequence} is empty (containing no items). \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two} \seqVarIfEmptyTF \lTmpaSeq {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \seqClear \lTmpaSeq \seqVarIfEmptyTF \lTmpaSeq {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\seqVarIfIn,\seqVarIfInT,\seqVarIfInF,\seqVarIfInTF} \begin{syntax} \cs{seqVarIfIn} \meta{sequence} \Arg{item} \cs{seqVarIfInT} \meta{sequence} \Arg{item} \Arg{true code} \cs{seqVarIfInF} \meta{sequence} \Arg{item} \Arg{false code} \cs{seqVarIfInTF} \meta{sequence} \Arg{item} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{item} is present in the \meta{sequence}. \begin{demohigh} \seqSetFromClist \lTmpaSeq {one,two} \seqVarIfInTF \lTmpaSeq {one} {\prgReturn{Yes}} {\prgReturn{Not}} \seqVarIfInTF \lTmpaSeq {three} {\prgReturn{Yes}} {\prgReturn{Not}} \end{demohigh} \end{function} \chapter{Property Lists (\texttt{Prop})} \LaTeX3 implements a \enquote{property list} data type, which contain an unordered list of entries each of which consists of a \meta{key} and an associated \meta{value}. The \meta{key} and \meta{value} may both be any \meta{balanced text}, the \meta{key} is processed using \cs{tlToStr}, meaning that category codes are ignored. It is possible to map functions to property lists such that the function is applied to every key--value pair within the list. Each entry in a property list must have a unique \meta{key}: if an entry is added to a property list which already contains the \meta{key} then the new entry overwrites the existing one. The \meta{keys} are compared on a string basis, using the same method as \cs{strIfEq}. %Property lists are intended for storing key-based information for use within %code. This is in contrast to key--value lists, which are a form of %\emph{input} parsed by the \pkg{l3keys} module. \section{Constant and Scratch Sequences} \begin{variable}{\cEmptyProp} Constant that is always empty. \end{variable} \begin{variable}{\lTmpaProp,\lTmpbProp,\lTmpcProp,\lTmpiProp,\lTmpjProp,\lTmpkProp} Scratch property lists for local assignment. These are never used by the \verb!functional! package, and so are safe for use with any function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaProp,\gTmpbProp,\gTmpcProp,\gTmpiProp,\gTmpjProp,\gTmpkProp} Scratch property lists for global assignment. These are never used by the \verb!functional! package, and so are safe for use with any function. However, they may be overwritten by other code and so should only be used for short-term storage. \end{variable} \section{Creating and Using Property Lists} \begin{function}{\propNew} \begin{syntax} \cs{propNew} \meta{property list} \end{syntax} Creates a new \meta{property list} or raises an error if the name is already taken. The declaration is global. The \meta{property list} initially contains no entries. \begin{codehigh} \propNew \lFooSomeProp \end{codehigh} \end{function} \begin{function}{\propConstFromKeyval} \begin{syntax} \cs{propConstFromKeyval} \meta{prop var} ~ \{ ~ ~ \meta{key1} \verb|=| \meta{value1} \verb|,| ~ ~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$ ~ \} \end{syntax} Creates a new constant \meta{prop var} or raises an error if the name is already taken. The \meta{prop var} is set globally to contain key--value pairs given in the second argument, processed in the way described for \cs{propSetFromKeyval}. If duplicate keys appear only the last of the values is kept. This function correctly detects the \verb|=| and \verb|,| signs provided they have the standard category code $12$ or they are active. \begin{codehigh} \propConstFromKeyval \cFooSomeProp {key1=one,key2=two,key3=three} \end{codehigh} %Notice that in contrast to most keyval lists (\emph{e.g.} those in %\pkg{l3keys}), each key here \emph{must} be followed with an \texttt{=} sign. \end{function} \begin{function}{\propToKeyval} \begin{syntax} \cs{propToKeyval} \meta{property list} \end{syntax} Returns the \meta{property list} in a key--value notation. Keep in mind that a \meta{property list} is \emph{unordered}, while key--value interfaces don't necessarily are, so this can't be used for arbitrary interfaces. %\begin{texnote} %The result is returned within the \tn{unexpanded} primitive %(\cs{exp_not:n}), which means that the key--value list does not expand %further when appearing in an \texttt{x}-type or \texttt{e}-type argument expansion. %It also needs exactly two steps of expansion. %\end{texnote} \begin{codehigh} \propToKeyval \lTmpaProp \end{codehigh} \end{function} \section{Viewing Property Lists} \begin{function}{\propVarLog} \begin{syntax} \cs{propVarLog} \meta{property list} \end{syntax} Writes the entries in the \meta{property list} in the log file. \begin{codehigh} \propVarLog \lTmpaProp \end{codehigh} \end{function} \begin{function}{\propVarShow} \begin{syntax} \cs{propVarShow} \meta{property list} \end{syntax} Displays the entries in the \meta{property list} in the terminal. \begin{codehigh} \propVarShow \lTmpaProp \end{codehigh} \end{function} \section{Setting Property Lists} \begin{function}{\propSetFromKeyval} \begin{syntax} \cs{propSetFromKeyval} \meta{prop var} \{ ~ \meta{key1} \verb|=| \meta{value1} \verb|,| ~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$ \} \end{syntax} Sets \meta{prop var} to contain key--value pairs given in the second argument. If duplicate keys appear only the last of the values is kept. Spaces are trimmed around every \meta{key} and every \meta{value}, and if the result of trimming spaces consists of a single brace group then a set of outer braces is removed. This enables both the \meta{key} and the \meta{value} to contain spaces, commas or equal signs. The \meta{key} is then processed by \cs{tlToStr}. This function correctly detects the \verb|=| and \verb|,| signs provided they have the standard category code $12$ or they are active. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \end{codehigh} %Notice that in contrast to most keyval lists (\emph{e.g.} those in %\pkg{l3keys}), each key here \emph{must} be followed with an \texttt{=} sign. \end{function} \begin{function}{\propSetEq} \begin{syntax} \cs{propSetEq} \meta{property list_1} \meta{property list_2} \end{syntax} Sets the content of \meta{property list_1} equal to that of \meta{property list_2}. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propSetEq \lTmpbProp \lTmpaProp \propVarLog \lTmpbProp \end{codehigh} \end{function} \begin{function}{\propClear} \begin{syntax} \cs{propClear} \meta{property list} \end{syntax} Clears all entries from the \meta{property list}. \begin{codehigh} \propClear \lTmpaProp \end{codehigh} \end{function} \begin{function}{\propClearNew} \begin{syntax} \cs{propClearNew} \meta{property list} \end{syntax} Ensures that the \meta{property list} exists globally by applying \cs{propNew} if necessary, then applies \cs{propClear} to leave the list empty. \begin{codehigh} \propClearNew \lFooSomeProp \end{codehigh} \end{function} \begin{function}{\propConcat} \begin{syntax} \cs{propConcat} \meta{prop var_1} \meta{prop var_2} \meta{prop var_3} \end{syntax} Combines the key--value pairs of \meta{prop var_2} and \meta{prop var_3}, and saves the result in \meta{prop var_1}. If a key appears in both \meta{prop var_2} and \meta{prop var_3} then the last value, namely the value in \meta{prop var_3} is kept. \begin{codehigh} \propSetFromKeyval \lTmpbProp {key1=one,key2=two} \propSetFromKeyval \lTmpcProp {key3=three,key4=four} \propConcat \lTmpaProp \lTmpbProp \lTmpcProp \propVarLog \lTmpaProp \end{codehigh} \end{function} \begin{function}{\propPut} \begin{syntax} \cs{propPut} \meta{property list} \Arg{key} \Arg{value} \end{syntax} Adds an entry to the \meta{property list} which may be accessed using the \meta{key} and which has \meta{value}. If the \meta{key} is already present in the \meta{property list}, the existing entry is overwritten by the new \meta{value}. Both the \meta{key} and \meta{value} may contain any \meta{balanced text}. The \meta{key} is stored after processing with \cs{tlToStr}, meaning that category codes are ignored. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propPut \lTmpaProp {key1} {newone} \propVarLog \lTmpaProp \end{codehigh} \end{function} \begin{function}{\propPutIfNew} \begin{syntax} \cs{propPutIfNew} \meta{property list} \Arg{key} \Arg{value} \end{syntax} If the \meta{key} is present in the \meta{property list} then no action is taken. Otherwise, a new entry is added as described for \cs{propPut}. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propPutIfNew \lTmpaProp {key1} {newone} \propVarLog \lTmpaProp \end{codehigh} \end{function} \begin{function}{\propPutFromKeyval} \begin{syntax} \cs{propPutFromKeyval} \meta{prop var} \{ ~ \meta{key1} \verb|=| \meta{value1} \verb|,| ~ \meta{key2} \verb|=| \meta{value2} \verb|,| $\cdots$ \} \end{syntax} Updates the \meta{prop var} by adding entries for each key--value pair given in the second argument. The addition is done through \cs{propPut}, hence if the \meta{prop var} already contains some of the keys, the corresponding values are discarded and replaced by those given in the key--value list. If duplicate keys appear in the key--value list then only the last of the values is kept. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propPutFromKeyval \lTmpaProp {key1=newone,key3=three} \propVarLog \lTmpaProp \end{codehigh} %The function is equivalent to storing the key--value pairs in a %temporary property variable using \cs{propSetFromKeyval}, then %combining \meta{prop var} with the temporary variable using %\cs{propConcat}. In particular, the \meta{keys} and %\meta{values} are space-trimmed and unbraced as described in %\cs{propSetFromKeyval}. This function correctly detects %the \verb|=| and \verb|,| signs provided they %have the standard category code $12$ or they are active. \end{function} \begin{function}{\propVarRemove} \begin{syntax} \cs{propVarRemove} \meta{property list} \Arg{key} \end{syntax} Removes the entry listed under \meta{key} from the \meta{property list}. If the \meta{key} is not found in the \meta{property list} no change occurs, \emph{i.e} there is no need to test for the existence of a key before deleting it. \begin{codehigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propVarRemove \lTmpaProp {key2} \propVarLog \lTmpaProp \end{codehigh} \end{function} \section{Recovering Values from Property Lists} \begin{function}{\propVarCount} \begin{syntax} \cs{propVarCount} \meta{property list} \end{syntax} Returns the number of key--value pairs in the \meta{property list} as an \meta{integer denotation}. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propVarCount \lTmpaProp \end{demohigh} \end{function} \begin{function}{\propVarItem} \begin{syntax} \cs{propVarItem} \meta{property list} \Arg{key} \end{syntax} Returns the \meta{value} corresponding to the \meta{key} in the \meta{property list}. If the \meta{key} is missing, nothing is returned. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \tlSet \lTmpaTl {\propVarItem \lTmpaProp {key2}} \tlUse \lTmpaTl \end{demohigh} %\begin{texnote} %This function is slower than the non-expandable analogue %\cs{prop_get:NnN}. %The result is returned within the \tn{unexpanded} %primitive (\cs{exp_not:n}), which means that the \meta{value} %does not expand further when appearing in an \texttt{x}-type %or \texttt{e}-type argument expansion. %\end{texnote} \end{function} \begin{function}{\propGet} \begin{syntax} \cs{propGet} \meta{property list} \Arg{key} \meta{token list variable} \end{syntax} Recovers the \meta{value} stored with \meta{key} from the \meta{property list}, and places this in the \meta{token list variable}. If the \meta{key} is not found in the \meta{property list} then the \meta{token list variable} is set to the special marker \cs{qNoValue}. The assignment of the \meta{token list variable} is local. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propGet \lTmpaProp {key2} \lTmpaTl \tlUse \lTmpaTl \end{demohigh} \end{function} \begin{function}{\propGetT,\propGetF,\propGetTF} \begin{syntax} \cs{propGetT} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \cs{propGetF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{false code} \cs{propGetTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{key} is not present in the \meta{property list}, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{key} is present in the \meta{property list}, stores the corresponding \meta{value} in the \meta{token list variable} without removing it from the \meta{property list}, then leaves the \meta{true code} in the input stream. The \meta{token list variable} is assigned locally. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propGetTF \lTmpaProp {key2} \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\propPop} \begin{syntax} \cs{propPop} \meta{property list} \Arg{key} \meta{token list variable} \end{syntax} Recovers the \meta{value} stored with \meta{key} from the \meta{property list}, and places this in the \meta{token list variable}. If the \meta{key} is not found in the \meta{property list} then the \meta{token list variable} is set to the special marker \cs{qNoValue}. The \meta{key} and \meta{value} are then deleted from the property list. The assignment of the \meta{token list variable} is local. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propPop \lTmpaProp {key2} \lTmpaTl Pop: \tlUse \lTmpaTl. Count: \propVarCount \lTmpaProp. \end{demohigh} \end{function} \begin{function}{\propPopT,\propPopF,\propPopTF} \begin{syntax} \cs{propPopT} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \cs{propPopF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{false code} \cs{propPopTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code} \end{syntax} If the \meta{key} is not present in the \meta{property list}, leaves the \meta{false code} in the input stream. The value of the \meta{token list variable} is not defined in this case and should not be relied upon. If the \meta{key} is present in the \meta{property list}, pops the corresponding \meta{value} in the \meta{token list variable}, \emph{i.e.} removes the item from The \meta{token list variable} is assigned locally. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two,key3=three} \propPopTF \lTmpaProp {key2} \lTmpaTl {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \section{Mapping over property lists} %All mappings are done at the current group level, \emph{i.e.} any %local assignments made by the \meta{function} or \meta{code} discussed %below remain in effect after the loop. %\begin{function}{\propVarMapFunction} %\begin{syntax} %\cs{propVarMapFunction} \meta{property list} \meta{function} %\end{syntax} %Applies \meta{function} to every \meta{entry} stored in the %\meta{property list}. The \meta{function} receives two arguments for %each iteration: the \meta{key} and associated \meta{value}. %The order in which \meta{entries} are returned is not defined and %should not be relied upon. %To pass further arguments to the \meta{function}, see %\cs{prop_map_tokens:Nn}. %\end{function} \begin{function}{\propVarMapInline} \begin{syntax} \cs{propVarMapInline} \meta{property list} \Arg{inline function} \end{syntax} Applies \meta{inline function} to every \meta{entry} stored within the \meta{property list}. The \meta{inline function} should consist of code which receives the \meta{key} as \verb|#1| and the \meta{value} as \verb|#2|. The order in which \meta{entries} are returned is not defined and should not be relied upon. \begin{demohigh} \IgnoreSpacesOn \propSetFromKeyval \lTmpkProp {key1=one,key2=two,key3=three} \tlClear \lTmpaTl \propVarMapInline \lTmpkProp { \tlPutRight \lTmpaTl {(#1=#2)} } \tlUse \lTmpaTl \IgnoreSpacesOff \end{demohigh} \end{function} %\begin{function}{\propVarMapTokens} %\begin{syntax} %\cs{propVarMapTokens} \meta{property list} \Arg{code} %\end{syntax} %Analogue of \cs{propVarMapFunction} which maps several tokens %instead of a single function. The \meta{code} receives each %key--value pair in the \meta{property list} as two trailing brace %groups. For instance, %\begin{verbatim} %\propVarMapTokens \lMyProp { \strIfEqT { mykey } } %\end{verbatim} %expands to the value corresponding to \texttt{mykey}: for each %pair in \verb|\lMyProp| the function \cs{strIfEqT} receives %\texttt{mykey}, the \meta{key} and the \meta{value} as its three %arguments. For that specific task, \cs{propVarItem} is faster. %\end{function} %\begin{function}{\propMapBreak} %\begin{syntax} %\cs{propMapBreak} %\end{syntax} %Used to terminate a prop map function before all %entries in the \meta{property list} have been processed. This %normally takes place within a conditional statement, for example %\begin{verbatim} %\prop_map_inline:Nn \l_my_prop %{ %\str_if_eq:nnTF { #1 } { bingo } %{ \prop_map_break: } %{ %Do something useful %} %} %\end{verbatim} %Use outside of a prop map scenario leads to low %level \TeX{} errors. %\begin{texnote} %When the mapping is broken, additional tokens may be inserted %before further items are taken %from the input stream. This depends on the design of the mapping %function. %\end{texnote} %\end{function} %\begin{function}{\propMapBreakDo} %\begin{syntax} %\cs{propMapBreakDo} \Arg{code} %\end{syntax} %Used to terminate a prop map function before all %entries in the \meta{property list} have been processed, inserting %the \meta{code} after the mapping has ended. This %normally takes place within a conditional statement, for example %\begin{verbatim} %\prop_map_inline:Nn \l_my_prop %{ %\str_if_eq:nnTF { #1 } { bingo } %{ \prop_map_break:n { } } %{ %Do something useful %} %} %\end{verbatim} %Use outside of a prop map scenario leads to low %level \TeX{} errors. %\begin{texnote} %When the mapping is broken, additional tokens may be inserted %before the \meta{code} is %inserted into the input stream. %This depends on the design of the mapping function. %\end{texnote} %\end{function} \section{Property List Conditionals} \begin{function}{\propIfExist,\propIfExistT,\propIfExistF,\propIfExistTF} \begin{syntax} \cs{propIfExist} \meta{property list} \cs{propIfExistT} \meta{property list} \Arg{true code} \cs{propIfExistF} \meta{property list} \Arg{false code} \cs{propIfExistTF} \meta{property list} \Arg{true code} \Arg{false code} \end{syntax} Tests whether the \meta{property list} is currently defined. This does not check that the \meta{property list} really is a property list variable. \begin{demohigh} \propIfExistTF \lTmpaProp {\prgReturn{Yes}} {\prgReturn{No}} \propIfExistTF \lFooUndefinedProp {\prgReturn{Yes}} {\prgReturn{No}} \end{demohigh} \end{function} \begin{function}{\propVarIfEmpty,\propVarIfEmptyT,\propVarIfEmptyF,\propVarIfEmptyTF} \begin{syntax} \cs{propVarIfEmpty} \meta{property list} \cs{propVarIfEmptyT} \meta{property list} \Arg{true code} \cs{propVarIfEmptyF} \meta{property list} \Arg{false code} \cs{propVarIfEmptyTF} \meta{property list} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{property list} is empty (containing no entries). \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propVarIfEmptyTF \lTmpaProp {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \propClear \lTmpaProp \propVarIfEmptyTF \lTmpaProp {\prgReturn{Empty}} {\prgReturn{NonEmpty}} \end{demohigh} \end{function} \begin{function}{\propVarIfIn,\propVarIfInT,\propVarIfInF,\propVarIfInTF} \begin{syntax} \cs{propVarIfIn} \meta{property list} \Arg{key} \cs{propVarIfInT} \meta{property list} \Arg{key} \Arg{true code} \cs{propVarIfInF} \meta{property list} \Arg{key} \Arg{false code} \cs{propVarIfInTF} \meta{property list} \Arg{key} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{key} is present in the \meta{property list}, making the comparison using the method described by \cs{strIfEqTF}. \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propVarIfInTF \lTmpaProp {key1} {\prgReturn{Yes}} {\prgReturn{Not}} \propVarIfInTF \lTmpaProp {key3} {\prgReturn{Yes}} {\prgReturn{Not}} \end{demohigh} %\begin{texnote} %This function iterates through every key--value pair in the %\meta{property list} and is therefore slower than using \cs{propGetTF}. %\end{texnote} \end{function} \chapter{Regular Expressions (\texttt{Regex})} This module provides regular expression testing, extraction of submatches, splitting, and replacement, all acting on token lists. The syntax of regular expressions is mostly a subset of the \textsc{pcre} syntax (and very close to \textsc{posix}), with some additions due to the fact that \TeX{} manipulates tokens rather than characters. For performance reasons, only a limited set of features are implemented. Notably, back-references are not supported. Let us give a few examples. The following example replace the first occurrence of \enquote{\texttt{at}} with \enquote{\texttt{is}} in the token list variable \cs{lTmpaTl}. \begin{demohigh} \tlSet \lTmpaTl {That cat.} \regexReplaceOnce {at} {is} \lTmpaTl \tlUse \lTmpaTl \end{demohigh} A more complicated example is a pattern to emphasize each word and add a comma after it: \begin{demohigh} \tlSet \lTmpaTl {That cat.} \regexReplaceAll {\w+} {\c{underline} \cB\{ \0 \cE\} ,} \lTmpaTl \tlUse \lTmpaTl \end{demohigh} The |\w| sequence represents any \enquote{word} character, and |+| indicates that the |\w| sequence should be repeated as many times as possible (at least once), hence matching a word in the input token list. In the replacement text, |\0| denotes the full match (here, a word). The command |\underline| is inserted using |\c{underline}|, and its argument |\0| is put between braces |\cB\{| and |\cE\}|. If a regular expression is to be used several times, it can be compiled once, and stored in a regex variable using \cs{regexSet}. For example, \begin{codehigh} \regexNew \lFooRegex \regexSet \lFooRegex {\c{begin} \cB. (\c[^BE].*) \cE.} \end{codehigh} stores in \cs{lFooRegex} a regular expression which matches the starting marker for an environment: \cs[no-index]{begin}, followed by a begin-group token (|\cB.|), then any number of tokens which are neither begin-group nor end-group character tokens (|\c[^BE].*|), ending with an end-group token (|\cE.|). As explained later, the parentheses \enquote{capture} the result of |\c[^BE].*|, giving us access to the name of the environment when doing replacements. \section{Regular Expression Variables} If a regular expression is to be used several times, it is better to compile it once rather than doing it each time the regular expression is used. The compiled regular expression is stored in a variable. All of this module's functions can be given their regular expression argument either as an explicit string or as a compiled regular expression. \begin{variable}{\lTmpaRegex,\lTmpbRegex,\lTmpcRegex,\lTmpiRegex,\lTmpjRegex,\lTmpkRegex} Scratch regex variables for local assignment. These are never used by \verb!function! package, and so are safe for use with any function. However, they may be overwritten by other non-kernel code and so should only be used for short-term storage. \end{variable} \begin{variable}{\gTmpaRegex,\gTmpbRegex,\gTmpcRegex,\gTmpiRegex,\gTmpjRegex,\gTmpkRegex} Scratch regex variables for global assignment. These are never used by \verb!function! package, and so are safe for use with any function. However, they may be overwritten by other non-kernel code and so should only be used for short-term storage. \end{variable} \begin{function}{\regexNew} \begin{syntax} \cs{regexNew} \meta{regex var} \end{syntax} Creates a new \meta{regex var} or raises an error if the name is already taken. The declaration is global. The \meta{regex var} is initially such that it never matches. \end{function} \begin{function}{\regexSet} \begin{syntax} \cs{regexSet} \meta{regex var} \Arg{regex} \end{syntax} Stores a compiled version of the \meta{regular expression} in the \meta{regex var}. For instance, this function can be used as \begin{codehigh} \regexNew \lMyRegex \regexSet \lMyRegex {my\ (simple\ )? reg(ex|ular\ expression)} \end{codehigh} \end{function} \begin{function}{\regexConst} \begin{syntax} \cs{regexConst} \meta{regex var} \Arg{regex} \end{syntax} Creates a new constant \meta{regex var} or raises an error if the name is already taken. The value of the \meta{regex var} is set globally to the compiled version of the \meta{regular expression}. \end{function} \begin{function}{\regexLog,\regexVarLog,\regexShow,\regexVarShow} \begin{syntax} \cs{regexLog} \Arg{regex} \cs{regexVarLog} \meta{regex var} \cs{regexShow} \Arg{regex} \cs{regexVarShow} \meta{regex var} \end{syntax} Displays in the terminal or writes in the log file (respectively) how \pkg{l3regex} interprets the \meta{regex}. For instance, \cs{regexShow} \verb+{\A X|Y}+ shows \begin{codehigh} +-branch anchor at start (\A) char code 88 (X) +-branch char code 89 (Y) \end{codehigh} indicating that the anchor |\A| only applies to the first branch: the second branch is not anchored to the beginning of the match. \end{function} \section{Regular Expression Matching} \begin{function}{\regexMatch,\regexMatchT,\regexMatchF,\regexMatchTF} \begin{syntax} \cs{regexMatch} \Arg{regex} \Arg{token list} \cs{regexMatchT} \Arg{regex} \Arg{token list} \Arg{true code} \cs{regexMatchF} \Arg{regex} \Arg{token list} \Arg{false code} \cs{regexMatchTF} \Arg{regex} \Arg{token list} \Arg{true code} \Arg{false code} \end{syntax} Tests whether the \meta{regular expression} matches any part of the \meta{token list}. For instance, \begin{demohigh} \regexMatchTF {b [cde]*} {abecdcx} {\prgPrint{True}} {\prgPrint{False}} \regexMatchTF {[b-dq-w]} {example} {\prgPrint{True}} {\prgPrint{False}} \end{demohigh} \end{function} \begin{function}{\regexVarMatch,\regexVarMatchT,\regexVarMatchF,\regexVarMatchTF} \begin{syntax} \cs{regexVarMatch} \meta{regex var} \Arg{token list} \cs{regexVarMatchT} \meta{regex var} \Arg{token list} \Arg{true code} \cs{regexVarMatchF} \meta{regex var} \Arg{token list} \Arg{false code} \cs{regexVarMatchTF} \meta{regex var} \Arg{token list} \Arg{true code} \Arg{false code} \end{syntax} Tests whether the \meta{regex var} matches any part of the \meta{token list}. \end{function} \begin{function}{\regexCount,\regexVarCount} \begin{syntax} \cs{regexCount} \Arg{regex} \Arg{token list} \meta{int var} \cs{regexVarCount} \meta{regex var} \Arg{token list} \meta{int var} \end{syntax} Sets \meta{int var} within the current \TeX{} group level equal to the number of times \meta{regular expression} appears in \meta{token list}. The search starts by finding the left-most longest match, respecting greedy and lazy (non-greedy) operators. Then the search starts again from the character following the last character of the previous match, until reaching the end of the token list. Infinite loops are prevented in the case where the regular expression can match an empty token list: then we count one match between each pair of characters. For instance, \begin{demohigh} \intNew \lFooInt \regexCount {(b+|c)} {abbababcbb} \lFooInt \intUse \lFooInt \end{demohigh} \end{function} \begin{function}{\regexMatchCase} \begin{syntax} \cs{regexMatchCase} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{code case_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{code case_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{code case_n} ~ ~ |}| \Arg{token list} \end{syntax} Determines which of the \meta{regular expressions} matches at the earliest point in the \meta{token list}, and leaves the corresponding \meta{code_i}. If several \meta{regex} match starting at the same point, then the first one in the list is selected and the others are discarded. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \par In detail, for each starting position in the \meta{token list}, each of the \meta{regex} is searched in turn. If one of them matches then the corresponding \meta{code} is used and everything else is discarded, while if none of the \meta{regex} match at a given position then the next starting position is attempted. If none of the \meta{regex} match anywhere in the \meta{token list} then nothing is left in the input stream. Note that this differs from nested \cs{regexMatch} statements since all \meta{regex} are attempted at each position rather than attempting to match \meta{regex_1} at every position before moving on to \meta{regex_2}. \end{function} \begin{function}{\regexMatchCaseT} \begin{syntax} \cs{regexMatchCaseT} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{code case_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{code case_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{code case_n} ~ ~ |}| \Arg{token list} ~ ~ \Arg{true code} \end{syntax} Determines which of the \meta{regular expressions} matches at the earliest point in the \meta{token list}, and leaves the corresponding \meta{code_i} followed by the \meta{true code} in the input stream. If several \meta{regex} match starting at the same point, then the first one in the list is selected and the others are discarded. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \begin{function}{\regexMatchCaseF} \begin{syntax} \cs{regexMatchCaseF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{code case_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{code case_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{code case_n} ~ ~ |}| \Arg{token list} ~ ~ \Arg{false code} \end{syntax} Determines which of the \meta{regular expressions} matches at the earliest point in the \meta{token list}, and leaves the corresponding \meta{code_i}. If several \meta{regex} match starting at the same point, then the first one in the list is selected and the others are discarded. If none of the \meta{regex} match, the \meta{false code} is left in the input stream. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \begin{function}{\regexMatchCaseTF} \begin{syntax} \cs{regexMatchCaseTF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{code case_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{code case_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{code case_n} ~ ~ |}| \Arg{token list} ~ ~ \Arg{true code} \Arg{false code} \end{syntax} Determines which of the \meta{regular expressions} matches at the earliest point in the \meta{token list}, and leaves the corresponding \meta{code_i} followed by the \meta{true code} in the input stream. If several \meta{regex} match starting at the same point, then the first one in the list is selected and the others are discarded. If none of the \meta{regex} match, the \meta{false code} is left in the input stream. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \section{Regular Expression Submatch Extraction} \begin{function}{\regexExtractOnce,\regexExtractOnceT,\regexExtractOnceF,\regexExtractOnceTF} \begin{syntax} \cs{regexExtractOnce} \Arg{regex} \Arg{token list} \meta{seq var} \cs{regexExtractOnceT} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexExtractOnceF} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexExtractOnceTF} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Finds the first match of the \meta{regular expression} in the \meta{token list}. If it exists, the match is stored as the first item of the \meta{seq var}, and further items are the contents of capturing groups, in the order of their opening parenthesis. The \meta{seq var} is assigned locally. If there is no match, the \meta{seq var} is cleared. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. \par For instance, assume that you type \begin{codehigh} \regexExtractOnce {\A(La)?TeX(!*)\Z} {LaTeX!!!} \lTmpaSeq \end{codehigh} Then the regular expression (anchored at the start with |\A| and at the end with |\Z|) must match the whole token list. The first capturing group, |(La)?|, matches |La|, and the second capturing group, |(!*)|, matches |!!!|. Thus, \cs{lTmpaSeq} contains as a result the items |{LaTeX!!!}|, |{La}|, and |{!!!}|. Note that the $n$-th item of \cs{lTmpaSeq}, as obtained using \cs{seqVarItem}, correspond to the submatch numbered $(n-1)$ in functions such as \cs{regexReplaceOnce}. \end{function} \begin{function}{\regexVarExtractOnce,\regexVarExtractOnceT,\regexVarExtractOnceF,\regexVarExtractOnceTF} \begin{syntax} \cs{regexVarExtractOnce} \meta{regex var} \Arg{token list} \meta{seq var} \cs{regexVarExtractOnceT} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexVarExtractOnceF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexVarExtractOnceTF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Finds the first match of the \meta{regex var} in the \meta{token list}. If it exists, the match is stored as the first item of the \meta{seq var}, and further items are the contents of capturing groups, in the order of their opening parenthesis. The \meta{seq var} is assigned locally. If there is no match, the \meta{seq var} is cleared. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. \end{function} \begin{function}{\regexExtractAll,\regexExtractAllT,\regexExtractAllF,\regexExtractAllTF} \begin{syntax} \cs{regexExtractAll} \Arg{regex} \Arg{token list} \meta{seq var} \cs{regexExtractAllT} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexExtractAllF} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexExtractAllTF} \Arg{regex} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Finds all matches of the \meta{regular expression} in the \meta{token list}, and stores all the submatch information in a single sequence (concatenating the results of multiple \cs{regexExtractOnce} calls). The \meta{seq var} is assigned locally. If there is no match, the \meta{seq var} is cleared. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. For instance, assume that you type \begin{codehigh} \regexExtractAll {\w+} {Hello, world!} \lTmpaSeq \end{codehigh} Then the regular expression matches twice, the resulting sequence contains the two items |{Hello}| and |{world}|. \end{function} \begin{function}{\regexVarExtractAll,\regexVarExtractAllT,\regexVarExtractAllF,\regexVarExtractAllTF} \begin{syntax} \cs{regexVarExtractAll} \meta{regex var} \Arg{token list} \meta{seq var} \cs{regexVarExtractAllT} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexVarExtractAllF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexVarExtractAllTF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Finds all matches of the \meta{regex var} in the \meta{token list}, and stores all the submatch information in a single sequence (concatenating the results of multiple \cs{regexVarExtractOnce} calls). The \meta{seq var} is assigned locally. If there is no match, the \meta{seq var} is cleared. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. \end{function} \begin{function}{\regexSplit,\regexSplitT,\regexSplitF,\regexSplitTF} \begin{syntax} \cs{regexSplit} \Arg{regular expression} \Arg{token list} \meta{seq var} \cs{regexSplitT} \Arg{regular expression} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexSplitF} \Arg{regular expression} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexSplitTF} \Arg{regular expression} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Splits the \meta{token list} into a sequence of parts, delimited by matches of the \meta{regular expression}. If the \meta{regular expression} has capturing groups, then the token lists that they match are stored as items of the sequence as well. The assignment to \meta{seq var} is local. If no match is found the resulting \meta{seq var} has the \meta{token list} as its sole item. If the \meta{regular expression} matches the empty token list, then the \meta{token list} is split into single tokens. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. For example, after \begin{codehigh} \seqNew \lPathSeq \regexSplit {/} {the/path/for/this/file.tex} \lPathSeq \end{codehigh} the sequence |\lPathSeq| contains the items |{the}|, |{path}|, |{for}|, |{this}|, and |{file.tex}|. \end{function} \begin{function}{\regexVarSplit,\regexVarSplitT,\regexVarSplitF,\regexVarSplitTF} \begin{syntax} \cs{regexVarSplit} \meta{regex var} \Arg{token list} \meta{seq var} \cs{regexVarSplitT} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \cs{regexVarSplitF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{false code} \cs{regexVarSplitTF} \meta{regex var} \Arg{token list} \meta{seq var} \Arg{true code} \Arg{false code} \end{syntax} Splits the \meta{token list} into a sequence of parts, delimited by matches of the \meta{regular expression}. If the \meta{regex var} has capturing groups, then the token lists that they match are stored as items of the sequence as well. The assignment to \meta{seq var} is local. If no match is found the resulting \meta{seq var} has the \meta{token list} as its sole item. If the \meta{regular expression} matches the empty token list, then the \meta{token list} is split into single tokens. The testing versions insert the \meta{true code} into the input stream if a match was found, and the \meta{false code} otherwise. \end{function} \section{Regular Expression Replacement} \begin{function}{\regexReplaceOnce,\regexReplaceOnceT,\regexReplaceOnceT,\regexReplaceOnceTF} \begin{syntax} \cs{regexReplaceOnce} \Arg{regular expression} \Arg{replacement} \meta{tl var} \cs{regexReplaceOnceT} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{true code} \cs{regexReplaceOnceF} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{false code} \cs{regexReplaceOnceTF} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{true code} \Arg{false code} \end{syntax} Searches for the \meta{regular expression} in the contents of the \meta{tl var} and replaces the first match with the \meta{replacement}. In the \meta{replacement}, |\0| represents the full match, |\1| represent the contents of the first capturing group, |\2| of the second, \emph{etc.} The result is assigned locally to \meta{tl var}. \end{function} \begin{function}{\regexReplaceOnce,\regexReplaceOnceT,\regexReplaceOnceT,\regexReplaceOnceTF} \begin{syntax} \cs{regexVarReplaceOnce} \meta{regex var} \Arg{replacement} \meta{tl var} \cs{regexVarReplaceOnceT} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{true code} \cs{regexVarReplaceOnceF} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{false code} \cs{regexVarReplaceOnceTF} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{true code} \Arg{false code} \end{syntax} Searches for the \meta{regex var} in the contents of the \meta{tl var} and replaces the first match with the \meta{replacement}. In the \meta{replacement}, |\0| represents the full match, |\1| represent the contents of the first capturing group, |\2| of the second, \emph{etc.} The result is assigned locally to \meta{tl var}. \end{function} \begin{function}{\regexReplaceAll,\regexReplaceAllT,\regexReplaceAllF,\regexReplaceAllTF} \begin{syntax} \cs{regexReplaceAll} \Arg{regular expression} \Arg{replacement} \meta{tl var} \cs{regexReplaceAllT} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{true code} \cs{regexReplaceAllF} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{false code} \cs{regexReplaceAllTF} \Arg{regular expression} \Arg{replacement} \meta{tl var} \Arg{true code} \Arg{false code} \end{syntax} Replaces all occurrences of the \meta{regex var} in the contents of the \meta{tl var} by the \meta{replacement}, where |\0| represents the full match, |\1| represent the contents of the first capturing group, |\2| of the second, \emph{etc.} Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl~var}. \end{function} \begin{function}{\regexVarReplaceAll,\regexVarReplaceAllT,\regexVarReplaceAllF,\regexVarReplaceAllTF} \begin{syntax} \cs{regexVarReplaceAll} \meta{regex var} \Arg{replacement} \meta{tl var} \cs{regexVarReplaceAllT} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{true code} \cs{regexVarReplaceAllF} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{false code} \cs{regexVarReplaceAllTF} \meta{regex var} \Arg{replacement} \meta{tl var} \Arg{true code} \Arg{false code} \end{syntax} Replaces all occurrences of the \meta{regular expression} in the contents of the \meta{tl var} by the \meta{replacement}, where |\0| represents the full match, |\1| represent the contents of the first capturing group, |\2| of the second, \emph{etc.} Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl var}. \end{function} \begin{function}{\regexReplaceCaseOnce} \begin{syntax} \cs{regexReplaceCaseOnce} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} \end{syntax} Replaces the earliest match of the regular expression "(?|"\meta{regex_1}"|"\dots"|"\meta{regex_n}")" in the \meta{token list variable} by the \meta{replacement} corresponding to which \meta{regex_i} matched. If none of the \meta{regex} match, then the \meta{tl var} is not modified. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \par In detail, for each starting position in the \meta{token list}, each of the \meta{regex} is searched in turn. If one of them matches then it is replaced by the corresponding \meta{replacement} as described for \cs{regexReplaceOnce}. This is equivalent to checking with \cs{regexMatchCase} which \meta{regex} matches, then performing the replacement with \cs{regexReplaceOnce}. \end{function} \begin{function}{\regexReplaceCaseOnceT} \begin{syntax} \cs{regexReplaceCaseOnceT} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{true code} \end{syntax} Replaces the earliest match of the regular expression "(?|"\meta{regex_1}"|"\dots"|"\meta{regex_n}")" in the \meta{token list variable} by the \meta{replacement} corresponding to which \meta{regex_i} matched, then leaves the \meta{true code} in the input stream. If none of the \meta{regex} match, then the \meta{tl var} is not modified. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \begin{function}{\regexReplaceCaseOnceF} \begin{syntax} \cs{regexReplaceCaseOnceF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{false code} \end{syntax} Replaces the earliest match of the regular expression "(?|"\meta{regex_1}"|"\dots"|"\meta{regex_n}")" in the \meta{token list variable} by the \meta{replacement} corresponding to which \meta{regex_i} matched. If none of the \meta{regex} match, then the \meta{tl var} is not modified, and the \meta{false code} is left in the input stream. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \begin{function}{\regexReplaceCaseOnceTF} \begin{syntax} \cs{regexReplaceCaseOnceTF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{true code} \Arg{false code} \end{syntax} Replaces the earliest match of the regular expression "(?|"\meta{regex_1}"|"\dots"|"\meta{regex_n}")" in the \meta{token list variable} by the \meta{replacement} corresponding to which \meta{regex_i} matched, then leaves the \meta{true code} in the input stream. If none of the \meta{regex} match, then the \meta{tl var} is not modified, and the \meta{false code} is left in the input stream. Each \meta{regex} can either be given as a regex variable or as an explicit regular expression. \end{function} \begin{function}{\regexReplaceCaseAll} \begin{syntax} \cs{regexReplaceCaseAll} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} \end{syntax} Replaces all occurrences of all \meta{regex} in the \meta{token~list} by the corresponding \meta{replacement}. Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl var}. \par In detail, for each starting position in the \meta{token list}, each of the \meta{regex} is searched in turn. If one of them matches then it is replaced by the corresponding \meta{replacement}, and the search resumes at the position that follows this match (and replacement). For instance %% FIXME %\begin{codehigh} %\tlSet \lTmpaTl {Hello, world!} %\regexReplaceCaseAll % { % {[A-Za-z]+} {``\0''} % {\b} {---} % {.} {[\0]} % } \lTmpaTl %\end{codehigh} \begin{codehigh} \tlSet \lTmpaTl {Hello, world!} \regexReplaceCaseAll { {[A-Za-z]+} {``\0''} {\b} {---} {.} {[\0]} } \lTmpaTl \end{codehigh} results in \cs{lTmpaTl} having the contents \verb*|``Hello''---[,][ ]``world''---[!]|. Note in particular that the word-boundary assertion |\b| did not match at the start of words because the case |[A-Za-z]+| matched at these positions. To change this, one could simply swap the order of the two cases in the argument of \cs{regexReplaceCaseAll}. \end{function} \begin{function}{\regexReplaceCaseAllT} \begin{syntax} \cs{regexReplaceCaseAllT} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{true code} \end{syntax} Replaces all occurrences of all \meta{regex} in the \meta{token~list} by the corresponding \meta{replacement}. Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl var}, and the \meta{true code} is left in the input stream if any replacement was made. \end{function} \begin{function}{\regexReplaceCaseAllF} \begin{syntax} \cs{regexReplaceCaseAllF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{false code} \end{syntax} Replaces all occurrences of all \meta{regex} in the \meta{token~list} by the corresponding \meta{replacement}. Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl var}, and the \meta{false code} is left in the input stream if not any replacement was made. \end{function} \begin{function}{\regexReplaceCaseAllTF} \begin{syntax} \cs{regexReplaceCaseAllTF} ~ ~ |{| ~ ~ ~ ~ \Arg{regex_1} \Arg{replacement_1} ~ ~ ~ ~ \Arg{regex_2} \Arg{replacement_2} ~ ~ ~ ~ \ldots ~ ~ ~ ~ \Arg{regex_n} \Arg{replacement_n} ~ ~ |}| \meta{tl var} ~ ~ \Arg{true code} \Arg{false code} \end{syntax} Replaces all occurrences of all \meta{regex} in the \meta{token list} by the corresponding \meta{replacement}. Every match is treated independently, and matches cannot overlap. The result is assigned locally to \meta{tl var}, and the \meta{true code} or \meta{false code} is left in the input stream depending on whether any replacement was made or not. \end{function} \section{Syntax of Regular Expressions} \subsection{Regular Expression Examples} We start with a few examples, and encourage the reader to apply \cs{regexShow} to these regular expressions. \begin{itemize} \item |Cat| matches the word \enquote{Cat} capitalized in this way, but also matches the beginning of the word \enquote{Cattle}: use |\bCat\b| to match a complete word only. \item |[abc]| matches one letter among \enquote{a}, \enquote{b}, \enquote{c}; the pattern \verb"(a|b|c)" matches the same three possible letters (but see the discussion of submatches below). \item |[A-Za-z]*| matches any number (due to the quantifier \verb"*") of Latin letters (not accented). \item |\c{[A-Za-z]*}| matches a control sequence made of Latin letters. \item |\_[^\_]*\_| matches an underscore, any number of characters other than underscore, and another underscore; it is equivalent to |\_.*?\_| where |.| matches arbitrary characters and the lazy quantifier |*?| means to match as few characters as possible, thus avoiding matching underscores. \item |[\+\-]?\d+| matches an explicit integer with at most one sign. \item \verb*"[\+\-\ ]*\d+\ *" matches an explicit integer with any number of $+$ and $-$ signs, with spaces allowed except within the mantissa, and surrounded by spaces. \item \verb*"[\+\-\ ]*(\d+|\d*\.\d+)\ *" matches an explicit integer or decimal number; using \verb*"[.,]" instead of \verb*"\." would allow the comma as a decimal marker. \item \verb*"[\+\-\ ]*(\d+|\d*\.\d+)\ *((?i)pt|in|[cem]m|ex|[bs]p|[dn]d|[pcn]c)\ *" \allowbreak matches an explicit dimension with any unit that \TeX{} knows, where \verb*"(?i)" means to treat lowercase and uppercase letters identically. \item \verb*"[\+\-\ ]*((?i)nan|inf|(\d+|\d*\.\d+)(\ *e[\+\-\ ]*\d+)?)\ *" matches an explicit floating point number or the special values \verb*"nan" and \verb*"inf" (with signs and spaces allowed). \item \verb*"[\+\-\ ]*(\d+|\cC.)\ *" matches an explicit integer or control sequence (without checking whether it is an integer variable). \item |\G.*?\K| at the beginning of a regular expression matches and discards (due to |\K|) everything between the end of the previous match (|\G|) and what is matched by the rest of the regular expression; this is useful in \cs{regexReplaceAll} when the goal is to extract matches or submatches in a finer way than with \cs{regexExtractAll}. \end{itemize} While it is impossible for a regular expression to match only integer expressions, \newline\verb*"[\+\-\(]*\d+\)*([\+\-*/][\+\-\(]*\d+\)*)*" matches among other things all valid integer expressions (made only with explicit integers). One should follow it with further testing. \subsection{Characters in Regular Expressions} Most characters match exactly themselves, with an arbitrary category code. Some characters are special and must be escaped with a backslash (\emph{e.g.}, |\*| matches a star character). Some escape sequences of the form backslash--letter also have a special meaning (for instance |\d| matches any digit). As a rule, \begin{itemize} \item every alphanumeric character (\texttt{A}--\texttt{Z}, \texttt{a}--\texttt{z}, \texttt{0}--\texttt{9}) matches exactly itself, and should not be escaped, because |\A|, |\B|, \ldots{} have special meanings; \item non-alphanumeric printable ASCII characters can (and should) always be escaped: many of them have special meanings (\emph{e.g.}, use |\(|, |\)|, |\?|, |\.|, |\^|); \item spaces should always be escaped (even in character classes); \item any other character may be escaped or not, without any effect: both versions match exactly that character. \end{itemize} Note that these rules play nicely with the fact that many non-alphanumeric characters are difficult to input into \TeX{} under normal category codes. For instance, |\\abc\%| matches the characters |\abc%| (with arbitrary category codes), but does not match the control sequence |\abc| followed by a percent character. Matching control sequences can be done using the |\c|\Arg{regex} syntax (see below). Any special character which appears at a place where its special behaviour cannot apply matches itself instead (for instance, a quantifier appearing at the beginning of a string), after raising a warning. Characters. \begin{l3regex-syntax} \item[\\x\{hh\ldots{}\}] Character with hex code \texttt{hh\ldots{}} \item[\\xhh] Character with hex code \texttt{hh}. \item[\\a] Alarm (hex 07). \item[\\e] Escape (hex 1B). \item[\\f] Form-feed (hex 0C). \item[\\n] New line (hex 0A). \item[\\r] Carriage return (hex 0D). \item[\\t] Horizontal tab (hex 09). \end{l3regex-syntax} \subsection{Characters Classes} Character types. \begin{l3regex-syntax} \item[.] A single period matches any token. \item[\\d] Any decimal digit. \item[\\h] Any horizontal space character, equivalent to |[\ \^^I]|: space and tab. \item[\\s] Any space character, equivalent to |[\ \^^I\^^J\^^L\^^M]|. \item[\\v] Any vertical space character, equivalent to |[\^^J\^^K\^^L\^^M]|. Note that |\^^K| is a vertical space, but not a space, for compatibility with Perl. \item[\\w] Any word character, \emph{i.e.}, alphanumerics and underscore, equivalent to the explicit class |[A-Za-z0-9\_]|. \item[\\D] Any token not matched by |\d|. \item[\\H] Any token not matched by |\h|. \item[\\N] Any token other than the |\n| character (hex 0A). \item[\\S] Any token not matched by |\s|. \item[\\V] Any token not matched by |\v|. \item[\\W] Any token not matched by |\w|. \end{l3regex-syntax} Of those, |.|, |\D|, |\H|, |\N|, |\S|, |\V|, and |\W| match arbitrary control sequences. Character classes match exactly one token in the subject. \begin{l3regex-syntax} \item[{[\ldots{}]}] Positive character class. Matches any of the specified tokens. \item[{[\char`\^\ldots{}]}] Negative character class. Matches any token other than the specified characters. \item[{x-y}] Within a character class, this denotes a range (can be used with escaped characters). \item[{[:\meta{name}:]}] Within a character class (one more set of brackets), this denotes the \textsc{posix} character class \meta{name}, which can be \texttt{alnum}, \texttt{alpha}, \texttt{ascii}, \texttt{blank}, \texttt{cntrl}, \texttt{digit}, \texttt{graph}, \texttt{lower}, \texttt{print}, \texttt{punct}, \texttt{space}, \texttt{upper}, \texttt{word}, or \texttt{xdigit}. \item[{[:\char`\^\meta{name}:]}] Negative \textsc{posix} character class. \end{l3regex-syntax} For instance, |[a-oq-z\cC.]| matches any lowercase latin letter except |p|, as well as control sequences (see below for a description of |\c|). In character classes, only |[|, |^|, |-|, |]|, |\| and spaces are special, and should be escaped. Other non-alphanumeric characters can still be escaped without harm. Any escape sequence which matches a single character (|\d|, |\D|, \emph{etc.}) is supported in character classes. If the first character is |^|, then the meaning of the character class is inverted; |^| appearing anywhere else in the range is not special. If the first character (possibly following a leading |^|) is |]| then it does not need to be escaped since ending the range there would make it empty. Ranges of characters can be expressed using |-|, for instance, |[\D 0-5]| and |[^6-9]| are equivalent. \subsection{Structure: Alternatives, Groups, Repetitions} Quantifiers (repetition). \begin{l3regex-syntax} \item[?] $0$ or $1$, greedy. \item[??] $0$ or $1$, lazy. \item[*] $0$ or more, greedy. \item[*?] $0$ or more, lazy. \item[+] $1$ or more, greedy. \item[+?] $1$ or more, lazy. \item[\{$n$\}] Exactly $n$. \item[\{$n,$\}] $n$ or more, greedy. \item[\{$n,$\}?] $n$ or more, lazy. \item[\{$n,m$\}] At least $n$, no more than $m$, greedy. \item[\{$n,m$\}?] At least $n$, no more than $m$, lazy. \end{l3regex-syntax} For greedy quantifiers the regex code will first investigate matches that involve as many repetitions as possible, while for lazy quantifiers it investigates matches with as few repetitions as possible first. Alternation and capturing groups. \begin{l3regex-syntax} \item[A\char`|B\char`|C] Either one of \texttt{A}, \texttt{B}, or \texttt{C}, investigating \texttt{A} first. \item[(\ldots{})] Capturing group. \item[(?:\ldots{})] Non-capturing group. \item[(?\char`|\ldots{})] Non-capturing group which resets the group number for capturing groups in each alternative. The following group is numbered with the first unused group number. \end{l3regex-syntax} Capturing groups are a means of extracting information about the match. Parenthesized groups are labelled in the order of their opening parenthesis, starting at $1$. The contents of those groups corresponding to the \enquote{best} match (leftmost longest) can be extracted and stored in a sequence of token lists using for instance \cs{regexExtractOnceTF}. The |\K| escape sequence resets the beginning of the match to the current position in the token list. This only affects what is reported as the full match. For instance, \begin{codehigh} \regexExtractAll {a \K .} {a123aaxyz} \lFooSeq \end{codehigh} results in \cs{lFooSeq} containing the items |{1}| and |{a}|: the true matches are |{a1}| and |{aa}|, but they are trimmed by the use of |\K|. The |\K| command does not affect capturing groups: for instance, \begin{codehigh} \regexExtractOnce {(. \K c)+ \d} {acbc3} \lFooSeq \end{codehigh} results in \cs{lFooSeq} containing the items |{c3}| and |{bc}|: the true match is |{acbc3}|, with first submatch |{bc}|, but |\K| resets the beginning of the match to the last position where it appears. \subsection{Matching Exact Tokens} The |\c| escape sequence allows to test the category code of tokens, and match control sequences. Each character category is represented by a single uppercase letter: \begin{itemize} \item |C| for control sequences; \item |B| for begin-group tokens; \item |E| for end-group tokens; \item |M| for math shift; \item |T| for alignment tab tokens; \item |P| for macro parameter tokens; \item |U| for superscript tokens (up); \item |D| for subscript tokens (down); \item |S| for spaces; \item |L| for letters; \item |O| for others; and \item |A| for active characters. \end{itemize} The |\c| escape sequence is used as follows. \begin{l3regex-syntax} \item[\\c\Arg{regex}] A control sequence whose csname matches the \meta{regex}, anchored at the beginning and end, so that |\c{begin}| matches exactly \cs[no-index]{begin}, and nothing else. \item[\\cX] Applies to the next object, which can be a character, escape character sequence such as |\x{0A}|, character class, or group, and forces this object to only match tokens with category |X| (any of |CBEMTPUDSLOA|. For instance, |\cL[A-Z\d]| matches uppercase letters and digits of category code letter, |\cC.| matches any control sequence, and |\cO(abc)| matches |abc| where each character has category other.\footnote{This last example also captures \enquote{\texttt{abc}} as a regex group; to avoid this use a non-capturing group \texttt{\textbackslash cO(?:abc)}.} \item[{\\c[XYZ]}] Applies to the next object, and forces it to only match tokens with category |X|, |Y|, or |Z| (each being any of |CBEMTPUDSLOA|). For instance, |\c[LSO](..)| matches two tokens of category letter, space, or other. \item[{\\c[\char`\^XYZ]}] Applies to the next object and prevents it from matching any token with category |X|, |Y|, or |Z| (each being any of |CBEMTPUDSLOA|). For instance, |\c[^O]\d| matches digits which have any category different from other. \end{l3regex-syntax} The category code tests can be used inside classes; for instance, |[\cO\d \c[LO][A-F]]| matches what \TeX{} considers as hexadecimal digits, namely digits with category other, or uppercase letters from |A| to |F| with category either letter or other. Within a group affected by a category code test, the outer test can be overridden by a nested test: for instance, |\cL(ab\cO\*cd)| matches |ab*cd| where all characters are of category letter, except |*| which has category other. The |\u| escape sequence allows to insert the contents of a token list directly into a regular expression or a replacement, avoiding the need to escape special characters. Namely, |\u|\Arg{var name} matches the exact contents (both character codes and category codes) of the variable \cs[no-index]{\meta{var name}}. %, %which are obtained by applying \cs{exp_not:v} \Arg{var name} at the %time the regular expression is compiled. Within a |\c{...}| control sequence matching, the |\u| escape sequence only expands its argument once. %, in effect performing \cs{tl_to_str:v}. Quantifiers are supported. The |\ur| escape sequence allows to insert the contents of a |regex| variable into a larger regular expression. For instance, |A\ur{lTmpaRegex}D| matches the tokens |A| and |D| separated by something that matches the regular expression \cs{lTmpaRegex}. This behaves as if a non-capturing group were surrounding \cs{lTmpaRegex}, and any group contained in \cs{lTmpaRegex} is converted to a non-capturing group. Quantifiers are supported. For instance, if \cs{lTmpaRegex} has value \verb"B|C", then |A\ur{l_tmpa_regex}D| is equivalent to \verb"A(?:B|C)D" (matching |ABD| or |ACD|) and not to \verb"AB|CD" (matching |AB| or |CD|). To get the latter effect, it is simplest to use \TeX{}'s expansion machinery directly: if \cs{lTmpaTl} contains \verb"B|C" then the following two lines show the same result: \begin{codehigh} \regexShow {A \u{lTmpaTl} D} \regexShow {A B | C D} \end{codehigh} \subsection{Miscellaneous} Anchors and simple assertions. \begin{l3regex-syntax} \item[\\b] Word boundary: either the previous token is matched by |\w| and the next by |\W|, or the opposite. For this purpose, the ends of the token list are considered as |\W|. \item[\\B] Not a word boundary: between two |\w| tokens or two |\W| tokens (including the boundary). \item[\char`^ \textrm{or} \\A] Start of the subject token list. \item[\char`$\textrm{,} \\Z \textrm{or} \\z] %^^A $ End of the subject token list. \item[\\G] Start of the current match. This is only different from |^| in the case of multiple matches: for instance |\regexCount {\G a} {aaba} \lTmpaInt| yields $2$, but replacing |\G| by |^| would result in \cs{lTmpaInt} holding the value $1$. \end{l3regex-syntax} The option |(?i)| makes the match case insensitive (identifying \texttt{A}--\texttt{Z} with \texttt{a}--\texttt{z}; no Unicode support yet). This applies until the end of the group in which it appears, and can be reverted using |(?-i)|. For instance, in \verb"(?i)(a(?-i)b|c)d", the letters |a| and |d| are affected by the |i| option. Characters within ranges and classes are affected individually: |(?i)[Y-\\]| is equivalent to |[YZ\[\\yz]|, and |(?i)[^aeiou]| matches any character which is not a vowel. Neither character properties, nor |\c{...}| nor |\u{...}| are affected by the |i| option. %^^A \] \section{Syntax of the Replacement Text} Most of the features described in regular expressions do not make sense within the replacement text. Backslash introduces various special constructions, described further below: \begin{itemize} \item |\0| is the whole match; \item |\1| is the submatch that was matched by the first (capturing) group |(...)|; similarly for |\2|, \ldots{}, |\9| and |\g{|\meta{number}|}|; \item \verb*|\ | inserts a space (spaces are ignored when not escaped); \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t|, |\xhh|, |\x{hhh}| correspond to single characters as in regular expressions; \item |\c|\Arg{cs name} inserts a control sequence; \item |\c|\meta{category}\meta{character} (see below); \item |\u|\Arg{tl var name} inserts the contents of the \meta{tl var} (see below). \end{itemize} Characters other than backslash and space are simply inserted in the result (but since the replacement text is first converted to a string, one should also escape characters that are special for \TeX{}, for instance use |\#|). Non-alphanumeric characters can always be safely escaped with a backslash. For instance, \begin{demohigh} \tlSet \lTmpaTl {Hello, world!} \regexReplaceAll {([er]?l|o) .} {(\0--\1)} \lTmpaTl \tlUse \lTmpaTl \end{demohigh} The submatches are numbered according to the order in which the opening parenthesis of capturing groups appear in the regular expression to match. The $n$-th submatch is empty if there are fewer than $n$ capturing groups or for capturing groups that appear in alternatives that were not used for the match. In case a capturing group matches several times during a match (due to quantifiers) only the last match is used in the replacement text. Submatches always keep the same category codes as in the original token list. By default, the category code of characters inserted by the replacement are determined by the prevailing category code regime at the time where the replacement is made, with two exceptions: \begin{itemize} \item space characters (with character code $32$) inserted with \verb*|\ | or |\x20| or |\x{20}| have category code $10$ regardless of the prevailing category code regime; \item if the category code would be $0$ (escape), $5$ (newline), $9$ (ignore), $14$ (comment) or $15$ (invalid), it is replaced by $12$ (other) instead. \end{itemize} The escape sequence |\c| allows to insert characters with arbitrary category codes, as well as control sequences. \begin{l3regex-syntax} \item[\\cX(\ldots{})] Produces the characters \enquote{\ldots{}} with category |X|, which must be one of |CBEMTPUDSLOA| as in regular expressions. Parentheses are optional for a single character (which can be an escape sequence). When nested, the innermost category code applies, for instance |\cL(Hello\cS\ world)!| gives this text with standard category codes. \item[\\c\Arg{text}] Produces the control sequence with csname \meta{text}. The \meta{text} may contain references to the submatches |\0|, |\1|, and so on, as in the example for |\u| below. \end{l3regex-syntax} The escape sequence |\u|\Arg{var name} allows to insert the contents of the variable with name \meta{var name} directly into the replacement, giving an easier control of category codes. When nested in |\c{|\ldots{}|}| and |\u{|\ldots{}|}| constructions, the |\u| and |\c| escape sequences %perform \cs{tl_to_str:v}, namely extract the value of the control sequence and turn it into a string. Matches can also be used within the arguments of |\c| and |\u|. For instance, \begin{demohigh} \tlSet \lMyOneTl {first} \tlSet \lMyTwoTl {\underline{second}} \tlSet \lTmpaTl {One,Two,One,One} \regexReplaceAll {[^,]+} {\u{lMy\0Tl}} \lTmpaTl \tlUse \lTmpaTl \end{demohigh} Regex replacement is also a convenient way to produce token lists with arbitrary category codes. For instance \begin{codehigh} \tlClear \lTmpaTl \regexReplaceAll { } {\cU\% \cA\~} \lTmpaTl \end{codehigh} results in \cs{lTmpaTl} containing the percent character with category code $7$ (superscript) and an active tilde character. \chapter{Token Manipulation (\texttt{Token})} \begin{function}{\charLowercase,\charUppercase,\charTitlecase,\charFoldcase} \begin{syntax} \cs{charLowercase} \meta{char} \cs{charUppercase} \meta{char} \cs{charTitlecase} \meta{char} \cs{charFoldcase} \meta{char} \end{syntax} Converts the \meta{char} to the equivalent case-changed character as detailed by the function name (see %\cs{strFoldcase} and \cs{textTitlecase} for details of these terms). The case mapping is carried out with no context-dependence (\emph{cf.} \cs{textUppercase}, \emph{etc.}) These functions generate characters with the category code of the \meta{char} (i.e. only the character code changes). \end{function} \begin{function}{\charStrLowercase,\charStrUppercase,\charStrTitlecase,\charStrFoldcase} \begin{syntax} \cs{charStrLowercase} \meta{char} \cs{charStrUppercase} \meta{char} \cs{charStrTitlecase} \meta{char} \cs{charStrFoldcase} \meta{char} \end{syntax} Converts the \meta{char} to the equivalent case-changed character as detailed by the function name (see %\cs{strFoldcase} and \cs{textTitlecase} for details of these terms). The case mapping is carried out with no context-dependence (\emph{cf.} \cs{textUppercase}, \emph{etc.}) These functions generate \enquote{other} (category code $12$) characters. \end{function} \begin{function}{\charSetLccode} \begin{syntax} \cs{charSetLccode} \Arg{intexpr_1} \Arg{intexpr_2} \end{syntax} Sets up the behaviour of the \meta{character} when found inside \cs{textLowercase}, such that \meta{character_1} will be converted into \meta{character_2}. The two \meta{characters} may be specified using an \meta{integer expression} for the character code concerned. This may include the \TeX{} \verb|`|\meta{character} method for converting a single character into its character code: \begin{codehigh} \charSetLccode {`\A} {`\a} % Standard behaviour \charSetLccode {`\A} {`\A + 32} \charSetLccode {65} {97} \end{codehigh} The setting applies within the current \TeX{} group. \end{function} \begin{function}{\charSetUccode} \begin{syntax} \cs{charSetUccode} \Arg{intexpr_1} \Arg{intexpr_2} \end{syntax} Sets up the behaviour of the \meta{character} when found inside \cs{textUppercase}, such that \meta{character_1} will be converted into \meta{character_2}. The two \meta{characters} may be specified using an \meta{integer expression} for the character code concerned. This may include the \TeX{} \verb|`|\meta{character} method for converting a single character into its character code: \begin{codehigh} \charSetUccode {`\a} {`\A} % Standard behaviour \charSetUccode {`\a} {`\a - 32} \charSetUccode {97} {65} \end{codehigh} The setting applies within the current \TeX{} group. \end{function} \begin{function}{\charValueLccode} \begin{syntax} \cs{charValueLccode} \Arg{integer expression} \end{syntax} Returns the current lower case code of the \meta{character} with character code given by the \meta{integer expression}. \end{function} \begin{function}{\charValueUccode} \begin{syntax} \cs{charValueUccode} \Arg{integer expression} \end{syntax} Returns the current upper case code of the \meta{character} with character code given by the \meta{integer expression}. \end{function} %\begin{function}{\charShowValueLccode} %\begin{syntax} %\cs{charShowValueLccode} \Arg{integer expression} %\end{syntax} %Displays the current lower case code of the \meta{character} with %character code given by the \meta{integer expression} on the %terminal. %\end{function} % %\begin{function}{\charShowValueUccode} %\begin{syntax} %\cs{charShowValueUccode} \Arg{integer expression} %\end{syntax} %Displays the current upper case code of the \meta{character} with %character code given by the \meta{integer expression} on the %terminal. %\end{function} \chapter{Text Processing (\texttt{Text})} This module deals with manipulation of (formatted) text; such material is comprised of a restricted set of token list content. The functions provided here concern conversion of textual content for example in case changing, %generation of bookmarks and extraction to tags. Begin-group and end-group tokens in the \meta{text} are normalized and become \verb|{| and \verb|}|, respectively. \section{Case Changing} These case changing functions are designed to work with Unicode input only. As such, UTF-8 input is assumed for \emph{all} engines. When used with XeTeX or LuaTeX a full range of Unicode transformations are enabled. Specifically, the standard mappings here follow those defined by the \href{http://www.unicode.org} {Unicode Consortium} in \texttt{UnicodeData.txt} and \texttt{SpecialCasing.txt}. In the case of $8$-bit engines, mappings are provided for characters which can be represented in output typeset using the \verb|T1|, \verb|T2| and \verb|LGR| font encodings. Thus for example \texttt{ä} can be case-changed using pdfTeX. For pTeX only the ASCII range is covered as the engine treats input outside of this range as east Asian. %Importantly, notice that these functions are intended for working with %user \emph{text for typesetting}. For case changing programmatic data see %the \pkg{Str} module and discussion there of \cs{strLowercase}, %\cs{strUppercase} and \cs{strFoldcase}. \begin{function}{\textExpand} \begin{syntax} \cs{textExpand} \Arg{text} \end{syntax} Takes user input \meta{text} and expands the content. Protected commands (typically formatting) are left in place, and no processing takes place of math mode material. %(as delimited by pairs given in \cs{l_text_math_delims_tl} %or as the argument to commands listed in \cs{l_text_math_arg_tl}). Commands which are neither engine- nor \LaTeX{} protected are expanded exhaustively. %Any commands listed in \cs{l_text_expand_exclude_tl}, %\cs{l_text_accents_tl} and \cs{l_text_letterlike_tl} are excluded from expansion. \end{function} \begin{function}{\textLowercase,\textUppercase,\textTitlecase,\textTitlecaseFirst} \begin{syntax} \cs{textLowercase} \Arg{tokens} \cs{textUppercase} \Arg{tokens} \cs{textTitlecase} \Arg{tokens} \cs{textTitlecaseFirst} \Arg{tokens} \end{syntax} Takes user input \meta{text} first applies \cs{textExpand}, then transforms the case of character tokens as specified by the function name. The category code of letters are not changed by this process (at least where they can be represented by the engine as a single token: $8$-bit engines may require active characters). \par Upper- and lowercase have the obvious meanings. Titlecasing may be regarded informally as converting the first character of the \meta{tokens} to uppercase and the rest to lowercase. However, the process is more complex than this as there are some situations where a single lowercase character maps to a special form, for example \texttt{ij} in Dutch which becomes \texttt{IJ}. \par For titlecasing, note that there are two functions available. The function \cs{textTitlecase} applies (broadly) uppercasing to the first letter of the input, then lowercasing to the remainder. In contrast, \cs{textTitlecaseFirst} \emph{only} carries out the uppercasing operation, and leaves the balance of the input unchanged. %Determining whether non-letter characters at the start of text should switch %from upper- to lowercasing is controllable. %When \cs{l_text_titlecase_check_letter_bool} is \texttt{true}, %characters which are not letters (category code $11$) are %left unchanged and \enquote{skipped}: the first \emph{letter} is uppercased. %(With $8$-bit engines, this is extended to active characters which form %part of a multi-byte letter codepoint.) When %\cs{l_text_titlecase_check_letter_bool} is \texttt{false}, the first %character is uppercased, and the rest lowercased, irrespective of the nature %of the character. \par Case changing does not take place within math mode material. For example: \begin{demohigh} \textUppercase {Text $y=mx+c$ with {Braces}} \end{demohigh} \begin{demohigh} \textLowercase {Text $Y=mX+c$ with {Braces}} \end{demohigh} %The arguments of commands listed in \cs{l_text_case_exclude_arg_tl} %are excluded from case changing; the latter are entirely non-textual %content (such as labels). \end{function} \begin{function}{\textLangLowercase,\textLangUppercase,\textLangTitlecase,\textLangTitlecaseFirst} \begin{syntax} \cs{textLangLowercase} \Arg{language} \Arg{tokens} \cs{textLangUppercase} \Arg{language} \Arg{tokens} \cs{textLangTitlecase} \Arg{language} \Arg{tokens} \cs{textLangTitlecaseFirst} \Arg{language} \Arg{tokens} \end{syntax} Takes user input \meta{text} first applies \cs{textExpand}, then transforms the case of character tokens as specified by the function name. The category code of letters are not changed by this process (at least where they can be represented by the engine as a single token: $8$-bit engines may require active characters). \par These conversions are language-sensitive, and follow Unicode Consortium guidelines. Currently, the languages recognised for special handling are as follows. \begin{itemize} \item Azeri and Turkish (\texttt{az} and \texttt{tr}). The case pairs I/i-dotless and I-dot/i are activated for these languages. The combining dot mark is removed when lowercasing I-dot and introduced when upper casing i-dotless. \item German (\texttt{de-alt}). An alternative mapping for German in which the lowercase \emph{Eszett} maps to a \emph{gro\ss{}es Eszett}. Since there is a \verb|T1| slot for the \emph{gro\ss{}es Eszett} in \verb|T1|, this tailoring \emph{is} available with pdfTeX as well as in the Unicode \TeX{} engines. \item Greek (\texttt{el}). Removes accents from Greek letters when uppercasing; titlecasing leaves accents in place. (At present this is implemented only for Unicode engines.) \item Lithuanian (\texttt{lt}). The lowercase letters i and j should retain a dot above when the accents grave, acute or tilde are present. This is implemented for lowercasing of the relevant uppercase letters both when input as single Unicode codepoints and when using combining accents. The combining dot is removed when uppercasing in these cases. Note that \emph{only} the accents used in Lithuanian are covered: the behaviour of other accents are not modified. \item Dutch (\texttt{nl}). Capitalisation of \texttt{ij} at the beginning of titlecased input produces \texttt{IJ} rather than \texttt{Ij}. The output retains two separate letters, thus this transformation \emph{is} available using pdfTeX. \end{itemize} \end{function} \chapter{Files (\texttt{File})} This module provides functions for working with external files. %Some of these functions apply to an entire file, and have prefix \cs{file}, %while others are used to work with files on a line by line basis and have %prefix \cs{Ior} (reading) or \cs{Iow} (writing). It is important to remember that when reading external files \TeX{} attempts to locate them using both the operating system path and entries in the \TeX{} file database (most \TeX{} systems use such a database). Thus the \enquote{current path} for \TeX{} is somewhat broader than that for other programs. For functions which expect a \meta{file name} argument, this argument may contain both literal items and expandable content, which should on full expansion be the desired file name. %Active characters (as declared in \cs{l_char_active_seq}) are \emph{not} %expanded, allowing the direct use of these in file names. Quote tokens (\verb|"|) are not permitted in file names as they are reserved for internal use by some \TeX{} primitives. Spaces are trimmed at the beginning and end of the file name: this reflects the fact that some file systems do not allow or interact unpredictably with spaces in these positions. When no extension is given, this will trim spaces from the start of the name only. \section{File Operation Functions} \begin{function}{\fileInput} \begin{syntax} \cs{fileInput} \Arg{file name} \end{syntax} Searches for \meta{file name} in the path as detailed for \cs{fileIfExistTF}, and if found reads in the file and returns the contents. All files read are recorded for information and the file name stack is updated by this function. An error is raised if the file is not found. \end{function} \begin{function}{\fileIfExistInput,\fileIfExistInputF} \begin{syntax} \cs{fileIfExistInput} \Arg{file name} \cs{fileIfExistInputF} \Arg{file name} \Arg{false code} \end{syntax} Searches for \meta{file name} using the current \TeX{} search path. %and the additional paths included in \cs{l_file_search_path_seq}. If found then reads in the file and returns the contents as described for \cs{fileInput}, otherwise inserts the \meta{false code}. Note that these functions do not raise an error if the file is not found, in contrast to \cs{fileInput}. \end{function} \begin{function}{\fileGet,\fileGetT,\fileGetF,\fileGetTF} \begin{syntax} \cs{fileGet} \Arg{filename} \Arg{setup} \meta{tl} \cs{fileGetT} \Arg{filename} \Arg{setup} \meta{tl} \Arg{true code} \cs{fileGetF} \Arg{filename} \Arg{setup} \meta{tl} \Arg{false code} \cs{fileGetTF} \Arg{filename} \Arg{setup} \meta{tl} \Arg{true code} \Arg{false code} \end{syntax} Defines \meta{tl} to the contents of \meta{filename}. Category codes may need to be set appropriately via the \meta{setup} argument. The non-branching version sets the \meta{tl} to \cs{qNoValue} if the file is not found. The branching version runs the \meta{true code} after the assignment to \meta{tl} if the file is found, and \meta{false code} otherwise. \end{function} \begin{function}{\fileIfExist,\fileIfExistT,\fileIfExistF,\fileIfExistTF} \begin{syntax} \cs{fileIfExist} \Arg{file name} \cs{fileIfExistT} \Arg{file name} \Arg{true code} \cs{fileIfExistF} \Arg{file name} \Arg{false code} \cs{fileIfExistTF} \Arg{file name} \Arg{true code} \Arg{false code} \end{syntax} Searches for \meta{file name} using the current \TeX{} search path. %and the additional paths controlled by \cs{l_file_search_path_seq}. \end{function} %\begin{function}{\fileInputStop} %\begin{syntax} %\cs{fileInputStop} %\end{syntax} %Ends the reading of a file started by \cs{file_input:n} or similar before %the end of the file is reached. Where the file reading is being terminated %due to an error, \cs{msg_critical:nn(nn)} %should be preferred. %\begin{texnote} %This function must be used on a line on its own: \TeX{} reads files %line-by-line and so any additional tokens in the \enquote{current} line %will still be read. %\par %This is also true if the function is hidden inside another function %(which will be the normal case), i.e., all tokens on the same line %in the source file are still processed. Putting it on a line by itself %in the definition doesn't help as it is the line where it is used that %counts! %\end{texnote} %\end{function} \chapter{Quarks (\texttt{Quark})} %One special type of constants in \LaTeX3 is \enquote{quarks}. %By convention all constants of type quark start out with \verb|\q|. Quarks are control sequences (and in fact, token lists) that expand to themselves and should therefore \emph{never} be executed directly in the code. This would result in an endless loop! Quarks can be used as error return values for functions that receive erroneous input. For example, in the function \cs{propGet} to retrieve a value stored in some key of a property list, if the key does not exist then the return value is the quark \cs{qNoValue}. As mentioned above, such quarks are extremely fragile and it is imperative when using such functions that code is carefully written to check for pathological cases to avoid leakage of a quark into an uncontrolled environment. \section{Constant Quarks} \begin{variable}{\qNoValue} A canonical value for a missing value, when one is requested from a data structure. This is therefore used as a \enquote{return} value by functions such as \cs{propGet} if there is no data to return. \end{variable} \section{Quark Conditionals} \begin{function}{\quarkVarIfNoValue,\quarkVarIfNoValueT,\quarkVarIfNoValueF,\quarkVarIfNoValueTF} \begin{syntax} \cs{quarkVarIfNoValue} \meta{token} \cs{quarkVarIfNoValueT} \meta{token} \Arg{true code} \cs{quarkVarIfNoValueF} \meta{token} \Arg{false code} \cs{quarkVarIfNoValueTF} \meta{token} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \meta{token} is equal to \cs{qNoValue}. \begin{demohigh} \clistGet \cEmptyClist \lTmpaTl \quarkVarIfNoValueTF \lTmpaTl {\prgReturn{NoValue}} {\prgReturn{SomeValue}} \end{demohigh} \begin{demohigh} \seqPop \cEmptySeq \lTmpaTl \quarkVarIfNoValueTF \lTmpaTl {\prgReturn{NoValue}} {\prgReturn{SomeValue}} \end{demohigh} \begin{demohigh} \propSetFromKeyval \lTmpaProp {key1=one,key2=two} \propGet \lTmpaProp {key3} \lTmpaTl \quarkVarIfNoValueTF \lTmpaTl {\prgReturn{NoValue}} {\prgReturn{SomeValue}} \end{demohigh} \end{function} %\begin{function}{\quarkIfNoValue,\quarkIfNoValueTF} %\begin{syntax} %\cs{quarkIfNoValue} \Arg{token list} %\cs{quarkIfNoValueTF} \Arg{token list} \Arg{true code} \Arg{false code} %\end{syntax} %Tests if the \meta{token list} contains only \cs{qNoValue} %(distinct from \meta{token list} being empty or containing %\cs{qNoValue} plus one or more other tokens). %\end{function} \chapter{Legacy Concepts (\texttt{Legacy})} There are a small number of \TeX{} or \LaTeXe{} concepts which are not used in \pkg{functional} code but which need to be manipulated when working as a \LaTeXe{} package. To allow these to be integrated cleanly into \pkg{functional} code, a set of legacy interfaces are provided here. \begin{function}{\legacyIf,\legacyIfT,\legacyIfF,\legacyIfTF} \begin{syntax} \cs{legacyIf} \Arg{name} \cs{legacyIfT} \Arg{name} \Arg{true code} \cs{legacyIfF} \Arg{name} \Arg{false code} \cs{legacyIfTF} \Arg{name} \Arg{true code} \Arg{false code} \end{syntax} Tests if the \LaTeXe{}/plain \TeX{} conditional (generated by \tn{newif}) if \texttt{true} or \texttt{false} and branches \hbox{accordingly}. The \meta{name} of the conditional should \emph{omit} the leading \texttt{if}. \begin{demohigh} \newif \ifFooBar \legacyIfTF {FooBar} {\prgReturn{True!}} {\prgReturn{False!}} \end{demohigh} \end{function} \begin{function}{\legacyIfSetTrue,\legacyIfSetFalse} \begin{syntax} \cs{legacyIfSetTrue} \Arg{name} \cs{legacyIfSetFalse} \Arg{name} \end{syntax} Sets the \LaTeXe{}/plain \TeX{} conditional \verb|\if|\meta{name} (generated by \tn{newif}) to be \texttt{true} or \texttt{false}. \begin{demohigh} \newif \ifFooBar \legacyIfSetTrue {FooBar} \legacyIfTF {FooBar} {\prgReturn{True!}} {\prgReturn{False!}} \end{demohigh} \end{function} \begin{function}{\legacyIfSet} \begin{syntax} \cs{legacyIfSet} \Arg{name} \Arg{boolexpr} \end{syntax} Sets the \LaTeXe{}/plain \TeX{} conditional \verb|\if|\meta{name} (generated by \tn{newif}) to the result of evaluating the \meta{boolean expression}. \begin{demohigh} \newif \ifFooBar \legacyIfSet {FooBar} {\cFalseBool} \legacyIfTF {FooBar} {\prgReturn{True!}} {\prgReturn{False!}} \end{demohigh} \end{function} \chapter{The Source Code} %\CodeHigh{lite} \dochighinput[language=latex/latex3]{functional.sty} \end{document}