texlive[62648] branches/branch2021.final/Master: functional (branch)

commits+karl at tug.org commits+karl at tug.org
Sat Mar 12 00:36:46 CET 2022


Revision: 62648
          http://tug.org/svn/texlive?view=revision&revision=62648
Author:   karl
Date:     2022-03-12 00:36:45 +0100 (Sat, 12 Mar 2022)
Log Message:
-----------
functional (branch)

Modified Paths:
--------------
    branches/branch2021.final/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc

Added Paths:
-----------
    branches/branch2021.final/Master/texmf-dist/doc/latex/functional/
    branches/branch2021.final/Master/texmf-dist/doc/latex/functional/README.txt
    branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf
    branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.tex
    branches/branch2021.final/Master/texmf-dist/tex/latex/functional/
    branches/branch2021.final/Master/texmf-dist/tex/latex/functional/functional.sty
    branches/branch2021.final/Master/tlpkg/tlpsrc/functional.tlpsrc

Added: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/README.txt
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/latex/functional/README.txt	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/latex/functional/README.txt	2022-03-11 23:36:45 UTC (rev 62648)
@@ -0,0 +1,5 @@
+Functional: LaTeX2 functional interfaces to LaTeX3 programming layer
+Copyright : 2022 (c) Jianrui Lyu <tolvjr at 163.com>
+Repository: https://github.com/lvjr/functional
+Repository: https://bitbucket.org/lvjr/functional
+License   : The LaTeX Project Public License 1.3c


Property changes on: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf
===================================================================
(Binary files differ)

Index: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf	2022-03-11 23:36:20 UTC (rev 62647)
+++ branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf	2022-03-11 23:36:45 UTC (rev 62648)

Property changes on: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.tex
===================================================================
--- branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.tex	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.tex	2022-03-11 23:36:45 UTC (rev 62648)
@@ -0,0 +1,994 @@
+%  -*- coding: utf-8 -*-
+
+\documentclass[oneside]{book}
+\usepackage[a4paper,margin=2.5cm]{geometry}
+
+\newcommand*{\myversion}{2022A}
+\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}
+
+\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
+}
+\ExplSyntaxOff
+
+\NewDocumentEnvironment{variable}{m}{
+  \vspace{5pt}
+  \begin{minipage}{\linewidth}
+  \hrule\vspace{4pt}\obeylines%
+  \begingroup
+  \ttfamily\bfseries\color{azure3}
+  \PrintVarList{#1}
+  \endgroup
+  \par\vspace{4pt}\hrule
+  \end{minipage}\par\nopagebreak\vspace{4pt}
+}{%
+  \vspace{5pt}%
+}
+
+\NewDocumentEnvironment{function}{m}{
+  \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{m}{%
+  \texttt{\bfseries\color{purple3}\expandafter\string\csname#1\endcsname}%
+}
+\NewDocumentCommand\meta{m}{%
+  \RelaceChacters{#1}%
+  \textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}%
+}
+\NewDocumentCommand\Arg{m}{%
+  \RelaceChacters{#1}%
+  \texttt{\{}\textsl{$\langle$\ignorespaces\lTmpaTl\unskip$\rangle$}\texttt{\}}%
+}
+
+\let\tn=\cs
+
+\RenewDocumentCommand\emph{m}{%
+  \underline{\textsl{#1}}%
+}
+
+\usepackage{hyperref}
+\hypersetup{
+  colorlinks=true,
+  urlcolor=blue3,
+  linkcolor=blue3,
+}
+
+\usepackage{functional}
+%\Functional{scoping=false,tracing=true}
+
+\begin{document}
+
+\title{\sffamily LaTeX2 \textcolor{green3}{Functional} Interfaces to LaTeX3 Programming Layer}
+\author{Jianrui Lyu (tolvjr at 163.com)\\\url{https://github.com/lvjr/functional}}
+\date{\mydate\vspace{1cm}\\\myabstract\vspace{10cm}}
+
+\newcommand\myabstract{\parbox{\linewidth}{\hrule\vspace{0.8em}\large
+LaTeX3 programming layer (\textsf{expl3}) is very powerful for advanced users,
+but it is a little complicated for normal users.
+This \textcolor{green3}{\sffamily functional} package aims to provide
+intuitive LaTeX2 functional interfaces for it.
+\par\vspace{0.5em}
+Although there are functions in LaTeX3, 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{JavaScript} or \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{code}
+-- lua code --
+function MathSquare (arg)
+  local lTmpaInt = arg * arg
+  return lTmpaInt
+end
+print(MathSquare(5))
+print(MathSquare(MathSquare(5)))
+\end{code}
+
+\begin{codehigh}
+%% function code
+\ExplSyntaxOn
+\PrgNewFunction \MathSquare { m } {
+  \IntSet \lTmpaInt { \IntEval { #1 * #1 } }
+  \Result { \Value \lTmpaInt }
+}
+\ExplSyntaxOff
+\MathSquare{5}
+\MathSquare{\MathSquare{5}}
+\end{codehigh}
+
+%\ExplSyntaxOn
+%\PrgNewFunction \MathSquare { m }{
+%  \IntSet \lTmpaInt { \IntEval { #1 * #1 } }
+%  \Result { \Value \lTmpaInt }
+%}
+%\ExplSyntaxOff
+%\MathSquare{5}
+%\MathSquare{\MathSquare{5}}
+
+%\ExplSyntaxOn
+%\PrgNewFunction \MathCubic { m }
+%  {
+%    \IntSet \lTmpaInt { \IntEval { #1 * #1 * #1 } }
+%    \Result { \Value \lTmpaInt }
+%  }
+%\ExplSyntaxOff
+%\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 othe programming languages
+such as \verb!Lua! or \verb!JavsScript!.
+
+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{Result} 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!\ExplSyntaxOn! and
+\verb!\ExplSyntaxOff! 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{code}
+-- lua code --
+function Factorial (n)
+  if n == 0 then
+    return 1
+  else
+    return n * Factorial(n-1)
+  end
+end
+print(Factorial(4))
+\end{code}
+
+\begin{codehigh}
+\ExplSyntaxOn
+\PrgNewFunction \Factorial { m } {
+  \IntCompareTF {#1} = {0} {
+    \Result {1}
+  }{
+    \Result { \IntMathMult {#1} { \Factorial { \IntMathSub{#1}{1} } } }
+  }
+}
+\ExplSyntaxOff
+\Factorial{4}
+\end{codehigh}
+
+%\ExplSyntaxOn
+%\PrgNewFunction \Factorial { m } {
+%  \IntCompareTF {#1} = {0} {
+%    \Result {1}
+%  }{
+%    \Result { \IntMathMult {#1} { \Factorial { \IntMathSub{#1}{1} } } }
+%  }
+%}
+%\ExplSyntaxOff
+%\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.
+For example
+
+\begin{code}
+-- lua code --
+local a = 1
+print(a)          ---- 1
+function SomeFun()
+  local a = 2
+  print(a)        ---- 2
+  if 1 > 0 then
+    local a = 3
+    print(a)      ---- 3
+  end
+  print(a)        ---- 2
+end
+SomeFun()
+print(a)          ---- 1
+\end{code}
+
+In \verb!functional! package, a condition expression is in fact a function,
+and you can make every function become a group by setting
+\verb!\Functional{scoping=true}!. For example
+
+\begin{codehigh}
+\Functional{scoping=true}
+\ExplSyntaxOn
+\IntSet \lTmpaInt {1}
+\IntLog \lTmpaInt             % ---- 1
+\PrgNewFunction \SomeFun { } {
+  \IntSet \lTmpaInt {2}
+  \IntLog \lTmpaInt           % ---- 2
+  \IntCompareTF {1} > {0} {
+    \IntSet \lTmpaInt {3}
+    \IntLog \lTmpaInt         % ---- 3
+  }{ }
+  \IntLog \lTmpaInt           % ---- 2
+}
+\SomeFun
+\IntLog \lTmpaInt             % ---- 1
+\ExplSyntaxOff
+\end{codehigh}
+
+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 varianbles 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{codehigh}
+\Functional{scoping=true}
+\IntSet \gTmpaInt {1}
+\IntLog \gTmpaInt             % ---- 1
+\PrgNewFunction \SomeFun { } {
+  \IntSet \gTmpaInt {2}
+  \IntLog \gTmpaInt           % ---- 2
+  \IntCompareTF {1} > {0} {
+    \IntSet \gTmpaInt {3}
+    \IntLog \gTmpaInt         % ---- 3
+  }{ }
+  \IntLog \gTmpaInt           % ---- 3
+}
+\SomeFun
+\IntLog \gTmpaInt             % ---- 3
+\end{codehigh}
+
+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] \Expand{\int_eval:n {5*5}}
+%                    [O] 25
+%                [I] \Result{25}
+%                [O] 25
+%            [O] 25
+%        [I] \IntSet\lTmpaInt {25}
+%        [O]
+%            [I] \Value\lTmpaInt
+%            [O] 25
+%        [I] \Result{25}
+%        [O] 25
+%    [O] 25
+%\end{codehigh}
+\begin{codehigh}[]
+[I] \MathSquare{5}
+        [I] \IntEval{5*5}
+                [I] \Expand{\int_eval:n {5*5}}
+                [O] 25
+            [I] \Result{25}
+            [O] 25
+        [O] 25
+    [I] \IntSet\lTmpaInt {25}
+    [O]
+        [I] \Value\lTmpaInt
+        [O] 25
+    [I] \Result{25}
+    [O] 25
+[O] 25
+[I] \MathSquare{25}
+        [I] \IntEval{25*25}
+                [I] \Expand{\int_eval:n {25*25}}
+                [O] 625
+            [I] \Result{625}
+            [O] 625
+        [O] 625
+    [I] \IntSet\lTmpaInt {625}
+    [O]
+        [I] \Value\lTmpaInt
+        [O] 625
+    [I] \Result{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{code}[language=latex/latex3]
+\cs_new:Npn
+\cs_new_nopar:Npn
+\cs_new_protected:Npn
+\cs_new_protected_nopar:Npn
+\cs_new:Nn
+\cs_new_nopar:Nn
+\cs_new_protected:Nn
+\cs_new_protected_nopar:Nn
+\end{code}
+
+Within \verb!functional! package, there is only one command (\cs{PrgNewFunction})
+for defining new functions, which is good for normal 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{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}
+
+\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}
+
+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{Name}, \cs{Expand}, \cs{Value}, respetively),
+which are easier to use for normal users.
+
+\begin{demohigh}
+\newcommand\test{uvw}
+\Name{test}
+\end{demohigh}
+
+\begin{demohigh}
+\newcommand\test{uvw}
+\Expand{111\test222}
+\end{demohigh}
+
+\begin{demohigh}
+\IntSet\lTmpaInt{123}
+\Value\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{Name} and \cs{Value} functions:
+
+\begin{demohigh}
+\IntSet\lTmpaInt{123}
+\Value{\Name{lTmpaInt}}
+\end{demohigh}
+
+\chapter{Basic Definitions (\texttt{l3basics})}
+
+\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{Result} 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}{\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 \verb!\cTrueBool!
+or \verb!\cFalseBool! and be passed with \cs{Result} function..
+The definition is global and an error results if the \meta{function} is already defined.
+\par
+Assume the \meta{function} is \verb!\FooIfBar!, then another function \verb!\FooIfBarTF!
+will be created at the same time. \verb!\FooIfBarTF! function has two extra arguments
+which are \Arg{true code} and \Arg{false code}.\par
+\end{function}
+
+\begin{function}{\Result}
+\begin{syntax}
+\cs{Result} \Arg{tokens}
+\end{syntax}
+Appends \meta{tokens} to \verb!\gResultTl!, which holds the returned value of current function.
+This function is normally used in the \meta{code} of \cs{PrgNewFunction} and \cs{PrgNewConditional}.
+\end{function}
+
+\section{Expanding and Using Tokens}
+
+\begin{function}{\Name}
+\begin{syntax}
+\cs{Name} \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}{\Value}
+\begin{syntax}
+\cs{Value} \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}{\Expand}
+\begin{syntax}
+\cs{Expand} \Arg{tokens}
+\end{syntax}
+Expands the \meta{tokens} exhaustively and returns the result.
+\end{function}
+
+\begin{function}{\ExpNot}
+\begin{syntax}
+\cs{ExpNot} \Arg{tokens}
+\end{syntax}
+Prevents expansion of the \meta{tokens} inside the argument of \cs{Expand} function.
+The argument of \cs{ExpNot} \emph{must} be surrounded by braces.
+%\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}{\ExpValue}
+\begin{syntax}
+\cs{ExpValue} \meta{variable}
+\end{syntax}
+Recovers the content of the \meta{variable}, then prevents expansion
+of this material inside the argument of \cs{Expand} function.
+\end{function}
+
+\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{l3prg})}
+
+\section{Scratch Variables of Booleans}
+
+\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}
+
+%\BoolIfTF\cTrueBool{\Result{true}}{\Result{false}}
+%\BoolIfTF\cFalseBool{\Result{true}}{\Result{false}}
+
+\section{Public Functions for 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}{\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}{\BoolIf,\BoolIfTF}
+\begin{syntax}
+\cs{BoolIf} \meta{boolean}
+\cs{BoolIfTF} \meta{boolean} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests the current truth of \meta{boolean}, and continues evaluation
+based on this result. For example
+\begin{demohigh}
+\BoolSetTrue\lTmpaBool
+\BoolIfTF\lTmpaBool{\Result{True!}}{\Result{False!}}
+\BoolSetFalse\lTmpaBool
+\BoolIfTF\lTmpaBool{\Result{True!}}{\Result{False!}}
+\end{demohigh}
+\end{function}
+
+\chapter{Token Lists (\texttt{l3tl})}
+
+\section{Scratch Variables of Token Lists}
+
+\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{Public Functions for 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.
+\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.
+\end{function}
+
+\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. For example
+\begin{demohigh}
+\TlSet\lTmpiTl{\IntMathMult{4}{5}}
+\TlUse\lTmpiTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\TlClear}
+\begin{syntax}
+\cs{TlClear} \meta{tl~var}
+\end{syntax}
+Clears all entries from the \meta{tl~var}. For example
+\begin{demohigh}
+\TlSet\lTmpjTl{One}
+\TlClear\lTmpjTl
+\TlSet\lTmpjTl{Two}
+\TlUse\lTmpjTl
+\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}. For example
+\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}. For example
+\begin{demohigh}
+\TlSet\lTmpkTl{Functional}
+\TlPutRight\lTmpkTl{World}
+\TlUse\lTmpkTl
+\end{demohigh}
+\end{function}
+
+\begin{function}{\TlIfEmpty,\TlIfEmptyTF}
+\begin{syntax}
+\cs{TlIfEmpty} \meta{tl~var}
+\cs{TlIfEmptyTF} \meta{tl~var} \Arg{true code} \Arg{false code}
+\end{syntax}
+Tests if the \meta{token list variable} is entirely empty
+(\emph{i.e.}~contains no tokens at all). For example
+\begin{demohigh}
+\TlSet\lTmpaTl{abc}
+\TlIfEmptyTF\lTmpaTl{\Result{Empty}}{\Result{NonEmpty}}
+\TlClear\lTmpaTl
+\TlIfEmptyTF\lTmpaTl{\Result{Empty}}{\Result{NonEmpty}}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\TlIfEq,\TlIfEqTF}
+\begin{syntax}
+\cs{TlIfEq} \meta{tl~var_1} \meta{tl~var_2}
+\cs{TlIfEqTF} \meta{tl~var_1} \meta{tl~var_2} \Arg{true code} \Arg{false code}
+\end{syntax}
+Compares the content of two \meta{token list variables} and
+is logically \texttt{true} if the two contain the same list of
+tokens (\emph{i.e.}~identical in both the list of characters they
+contain and the category codes of those characters). For example
+\begin{demohigh}
+\TlSet\lTmpaTl{abc}
+\TlSet\lTmpbTl{abc}
+\TlSet\lTmpcTl{xyz}
+\TlIfEqTF\lTmpaTl\lTmpbTl{\Result{Yes}}{\Result{No}}
+\TlIfEqTF\lTmpaTl\lTmpcTl{\Result{Yes}}{\Result{No}}
+\end{demohigh}
+%See also \cs{StrIfEqTF} for a comparison that ignores category codes.
+\end{function}
+
+\chapter{Integers (\texttt{l3int})}
+
+\section{Scratch Variables of Integers}
+
+\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{Public Functions for Integers}
+
+\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}
+\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_1} from \Arg{integer expression_2},
+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}
+Divides \Arg{integer expression_1} by \Arg{integer expression_2},
+and returns the result. For example
+\begin{demohigh}
+\IntMathDiv{7}{3}
+\end{demohigh}
+\end{function}
+
+\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}{\IntUse}
+\begin{syntax}
+\cs{IntUse} \meta{integer}
+\end{syntax}
+Recovers the content of an \meta{integer} and returns the value.
+An error is raised if the variable does
+not exist or if it is invalid. Can be omitted in places where an
+\meta{integer} is required (such as in the first and third arguments
+of \cs{IntCompareTF}).%
+%\begin{texnote}
+%\cs{IntUse} is the \TeX{} primitive \tn{the}: this is one of
+%several \verb!functional! names for this primitive.
+%\end{texnote}
+\end{function}
+
+\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}{\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}{\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}
+
+\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}
+\TlClear\lTmpaTl
+\IntStepVariable{1}{3}{30}\lTmpiTl{
+  \TlPutRight\lTmpaTl{\Value\lTmpiTl}
+  \TlPutRight\lTmpaTl{ }
+}
+\Result{\Value\lTmpaTl}
+\end{demohigh}
+\end{function}
+
+\begin{function}{\IntCompare,\IntCompareTF}
+\begin{syntax}
+\cs{IntCompare} \Arg{intexpr_1} \meta{relation} \Arg{intexpr_2}
+\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}{\Result{Greater}}{\Result{Less}}
+\IntCompareTF{2}>{3}{\Result{Greater}}{\Result{Less}}
+\end{demohigh}
+\end{function}
+
+\chapter{The Source Code}
+
+%\CodeHigh{lite}
+\setlength\parskip{0pt}
+\dochighinput[language=latex/latex3]{functional.sty}
+
+\end{document}
+


Property changes on: branches/branch2021.final/Master/texmf-dist/doc/latex/functional/functional.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: branches/branch2021.final/Master/texmf-dist/tex/latex/functional/functional.sty
===================================================================
--- branches/branch2021.final/Master/texmf-dist/tex/latex/functional/functional.sty	                        (rev 0)
+++ branches/branch2021.final/Master/texmf-dist/tex/latex/functional/functional.sty	2022-03-11 23:36:45 UTC (rev 62648)
@@ -0,0 +1,686 @@
+%%% -*- coding: utf-8 -*-
+%% ----------------------------------------------------------------------------
+%% Functional: LaTeX2 functional interfaces to LaTeX3 programming layer
+%% Copyright : 2022 (c) Jianrui Lyu <tolvjr at 163.com>
+%% Repository: https://github.com/lvjr/functional
+%% License   : The LaTeX Project Public License 1.3c
+%% ----------------------------------------------------------------------------
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Function Definitions (l3basics)}
+%%% --------------------------------------------------------
+
+\NeedsTeXFormat{LaTeX2e}[2018-04-01]
+
+\RequirePackage{expl3}
+\ProvidesExplPackage{functional}{2022-03-10}{2022A}
+  {^^JLaTeX2 functional interfaces to LaTeX3 programming layer}
+
+\cs_generate_variant:Nn \iow_log:n { V }
+\cs_generate_variant:Nn \tl_set:Nn { Ne }
+
+\tl_new:N \gResultTl
+\int_new:N \l__fun_arg_count_int
+\tl_new:N \l__fun_parameters_defined_tl
+\tl_const:Nn \c__fun_parameter_defined_i__tl     {  } % no argument
+\tl_const:Nn \c__fun_parameter_defined_i_i_tl    { #1 }
+\tl_const:Nn \c__fun_parameter_defined_i_ii_tl   { #1 #2 }
+\tl_const:Nn \c__fun_parameter_defined_i_iii_tl  { #1 #2 #3 }
+\tl_const:Nn \c__fun_parameter_defined_i_iv_tl   { #1 #2 #3 #4 }
+\tl_const:Nn \c__fun_parameter_defined_i_v_tl    { #1 #2 #3 #4 #5 }
+\tl_const:Nn \c__fun_parameter_defined_i_vi_tl   { #1 #2 #3 #4 #5 #6 }
+\tl_const:Nn \c__fun_parameter_defined_i_vii_tl  { #1 #2 #3 #4 #5 #6 #7 }
+\tl_const:Nn \c__fun_parameter_defined_i_viii_tl { #1 #2 #3 #4 #5 #6 #7 #8 }
+\tl_const:Nn \c__fun_parameter_defined_i_ix_tl   { #1 #2 #3 #4 #5 #6 #7 #8 #9 }
+\tl_new:N \l__fun_parameters_called_tl
+\tl_const:Nn \c__fun_parameter_called_i_i_tl   { {#1} }
+\tl_const:Nn \c__fun_parameter_called_i_ii_tl  { {#1}{#2} }
+\tl_const:Nn \c__fun_parameter_called_i_iii_tl { {#1}{#2}{#3} }
+\tl_const:Nn \c__fun_parameter_called_i_iv_tl  { {#1}{#2}{#3}{#4} }
+\tl_const:Nn \c__fun_parameter_called_i_v_tl   { {#1}{#2}{#3}{#4}{#5} }
+\tl_const:Nn \c__fun_parameter_called_i_vi_tl  { {#1}{#2}{#3}{#4}{#5}{#6} }
+\tl_const:Nn \c__fun_parameter_called_i_vii_tl { {#1}{#2}{#3}{#4}{#5}{#6}{#7} }
+\tl_new:N \l__fun_parameters_true_tl
+\tl_new:N \l__fun_parameters_false_tl
+\tl_const:Nn \c__fun_parameter_called_i_tl    { {#1} }
+\tl_const:Nn \c__fun_parameter_called_ii_tl   { {#2} }
+\tl_const:Nn \c__fun_parameter_called_iii_tl  { {#3} }
+\tl_const:Nn \c__fun_parameter_called_iv_tl   { {#4} }
+\tl_const:Nn \c__fun_parameter_called_v_tl    { {#5} }
+\tl_const:Nn \c__fun_parameter_called_vi_tl   { {#6} }
+\tl_const:Nn \c__fun_parameter_called_vii_tl  { {#7} }
+\tl_const:Nn \c__fun_parameter_called_viii_tl { {#8} }
+\tl_const:Nn \c__fun_parameter_called_ix_tl   { {#9} }
+\tl_new:N \l__fun_argument_tl
+\tl_new:N \l__fun_argument_i_tl
+\tl_new:N \l__fun_argument_ii_tl
+\tl_new:N \l__fun_argument_iii_tl
+\tl_new:N \l__fun_argument_iv_tl
+\tl_new:N \l__fun_argument_v_tl
+\tl_new:N \l__fun_argument_vi_tl
+\tl_new:N \l__fun_argument_vii_tl
+\tl_new:N \l__fun_argument_viii_tl
+\tl_new:N \l__fun_argument_ix_tl
+
+%% #1: function name; #2: argument specification; #3 function body
+\cs_new_protected:Npn \__fun_new_function:Nnn #1 #2 #3
+  {
+    \int_set:Nn \l__fun_arg_count_int { \tl_count:n {#2} } % spaces are ignored
+    \tl_set_eq:Nc \l__fun_parameters_defined_tl
+      { c__fun_parameter_defined_i_ \int_to_roman:n { \l__fun_arg_count_int } _tl }
+    \exp_last_unbraced:NcV \cs_new_protected:Npn
+      { __fun_defined_ \cs_to_str:N #1 : w }
+      \l__fun_parameters_defined_tl
+      {
+        \__fun_group_begin:
+        \tl_gclear:N \gResultTl
+        #3
+        \__fun_tracing_log:e { [O] ~ \gResultTl }
+        \__fun_group_end:
+      }
+    \use:c { __fun_new_with_arg_ \int_to_roman:n { \l__fun_arg_count_int } :NnV }
+      #1 {#2} \l__fun_parameters_defined_tl
+  }
+\cs_generate_variant:Nn \__fun_new_function:Nnn { cne }
+
+\cs_set_eq:NN \PrgNewFunction \__fun_new_function:Nnn
+
+\tl_new:N \g__fun_last_result_tl
+
+%% #1: function name; #2: argument specification; #3 function body
+\cs_new_protected:Npn \__fun_new_conditional:Nnn #1 #2 #3
+  {
+    \__fun_new_function:Nnn #1 { #2 } { #3 }
+    \tl_set_eq:Nc \l__fun_parameters_called_tl
+      { c__fun_parameter_called_i_ \int_to_roman:n { \l__fun_arg_count_int } _tl }
+    \tl_set_eq:Nc \l__fun_parameters_true_tl
+      { c__fun_parameter_called_ \int_to_roman:n { \l__fun_arg_count_int + 1 } _tl }
+    \tl_set_eq:Nc \l__fun_parameters_false_tl
+      { c__fun_parameter_called_ \int_to_roman:n { \l__fun_arg_count_int + 2 } _tl }
+    \__fun_new_function:cne { \cs_to_str:N #1 TF } { #2 n n }
+      {
+        #1 \exp_not:V \l__fun_parameters_called_tl
+        \exp_not:n
+          {
+            \tl_set_eq:NN \g__fun_last_result_tl \gResultTl
+            \tl_gclear:N \gResultTl
+            \exp_last_unbraced:NV \bool_if:NTF \g__fun_last_result_tl
+          }
+        \exp_not:V \l__fun_parameters_true_tl
+        \exp_not:V \l__fun_parameters_false_tl
+      }
+  }
+
+\cs_set_eq:NN \PrgNewConditional \__fun_new_conditional:Nnn
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+%% Some times we need to create a function without arguments
+\cs_new_protected:Npn \__fun_new_with_arg_:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_i:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl { ##1 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_i:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_ii:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl  { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl { ##2 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_ii:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_iii:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_iii:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_iv:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_iv:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_v:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
+        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_v:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_vi:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
+        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
+        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_vi:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_vii:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl   { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl  { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl  { ##4 }
+        \tl_set:Nn \l__fun_argument_v_tl   { ##5 }
+        \tl_set:Nn \l__fun_argument_vi_tl  { ##6 }
+        \tl_set:Nn \l__fun_argument_vii_tl { ##7 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_vii:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_viii:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
+        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
+        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
+        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
+        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_viii:Nnn { NnV }
+
+%% #1: function name; #2: argument specifications; #3 parameters tl defined
+\cs_new_protected:Npn \__fun_new_with_arg_ix:Nnn #1 #2 #3
+  {
+    \cs_new_protected:Npn #1 #3
+      {
+        \tl_set:Nn \l__fun_argument_i_tl    { ##1 }
+        \tl_set:Nn \l__fun_argument_ii_tl   { ##2 }
+        \tl_set:Nn \l__fun_argument_iii_tl  { ##3 }
+        \tl_set:Nn \l__fun_argument_iv_tl   { ##4 }
+        \tl_set:Nn \l__fun_argument_v_tl    { ##5 }
+        \tl_set:Nn \l__fun_argument_vi_tl   { ##6 }
+        \tl_set:Nn \l__fun_argument_vii_tl  { ##7 }
+        \tl_set:Nn \l__fun_argument_viii_tl { ##8 }
+        \tl_set:Nn \l__fun_argument_ix_tl   { ##9 }
+        \__fun_evaluate:Nn #1 {#2}
+      }
+  }
+\cs_generate_variant:Nn \__fun_new_with_arg_ix:Nnn { NnV }
+
+\int_new:N \g__fun_nesting_level_int
+\int_new:N \l__fun_argtype_number_int
+\tl_new:N \l__fun_argtype_tl
+\tl_const:Nn \c__fun_argtype_m_tl { m }
+\tl_const:Nn \c__fun_argtype_M_tl { M }
+\tl_const:Nn \c__fun_argtype_n_tl { n }
+\tl_const:Nn \c__fun_argtype_N_tl { N }
+
+%% #1: function name; #2: argument specifications
+\cs_new_protected:Npn \__fun_evaluate:Nn #1 #2
+  {
+    \int_zero:N \l__fun_argtype_number_int
+    \int_gincr:N \g__fun_nesting_level_int
+    \__fun_arguments_gclear:
+    \tl_map_variable:nNn { #2 } \l__fun_argtype_tl % spaces are ignored
+      {
+        \int_incr:N \l__fun_argtype_number_int
+        \tl_set_eq:Nc \l__fun_argument_tl
+          { l__fun_argument_ \int_to_roman:n { \l__fun_argtype_number_int } _tl }
+        \tl_case:Nn \l__fun_argtype_tl
+          {
+            \c__fun_argtype_m_tl
+              {
+                \__fun_evaluate_and_put_argument:N \l__fun_argument_tl
+              }
+            \c__fun_argtype_M_tl
+              {
+                \__fun_evaluate_and_put_argument:N \l__fun_argument_tl
+              }
+            \c__fun_argtype_n_tl
+              {
+                \__fun_arguments_gput:e { { \exp_not:V \l__fun_argument_tl } }
+              }
+            \c__fun_argtype_N_tl
+              {
+                \__fun_arguments_gput:e { \exp_not:V \l__fun_argument_tl }
+              }
+          }
+      }
+    \__fun_arguments_log:N #1
+    \__fun_arguments_called:c { __fun_defined_ \cs_to_str:N #1 : w }
+    \int_gdecr:N \g__fun_nesting_level_int
+    \__fun_return_result:
+  }
+
+\cs_set_eq:NN \__fun_cs_temp:w \scan_stop:
+
+\cs_new_protected:Npn \__fun_evaluate_and_put_argument:N #1
+  {
+    \cs_set_eq:Nc \__fun_cs_temp:w
+      {
+        __fun_defined_ \exp_last_unbraced:Ne \cs_to_str:N { \tl_head:N #1 } : w
+      }
+    \cs_if_exist:NTF \__fun_cs_temp:w
+      {
+        #1
+        \__fun_arguments_gput:e { { \exp_not:V \gResultTl } }
+      }
+      {
+        \__fun_arguments_gput:e { { \exp_not:V #1 } }
+      }
+  }
+
+\cs_new_protected:Npn \__fun_arguments_called:N #1
+  {
+    \exp_last_unbraced:Nv
+      #1 { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
+  }
+\cs_generate_variant:Nn \__fun_arguments_called:N { c }
+
+\cs_new_protected:Npn \__fun_arguments_gclear:
+  {
+    \tl_gclear:c { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
+  }
+
+\cs_new_protected:Npn \__fun_arguments_log:N #1
+  {
+    \__fun_tracing_log:e
+    {
+      [I] ~ \token_to_str:N #1
+     \exp_not:v { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl }
+    }
+  }
+
+\cs_new_protected:Npn \__fun_arguments_gput:n #1
+  {
+    \tl_gput_right:cn
+      { g__fun_arguments_ \int_use:N \g__fun_nesting_level_int _tl } { #1 }
+  }
+\cs_generate_variant:Nn \__fun_arguments_gput:n { e }
+
+\cs_new_protected:Npn \__fun_put_result:n #1
+  {
+    \tl_gput_right:Nn \gResultTl { #1 }
+  }
+\cs_generate_variant:Nn \__fun_put_result:n { e, V }
+
+\PrgNewFunction \Result { m }
+  {
+    \__fun_put_result:n { #1 }
+  }
+
+\PrgNewFunction \Name { m }
+  {
+    \exp_args:Nc \__fun_put_result:n { #1 }
+  }
+\cs_set_eq:NN \UseName \Name
+
+\PrgNewFunction \Expand { m }
+  {
+    \__fun_put_result:e { #1 }
+  }
+\cs_set_eq:NN \UseExpand \Expand
+
+\PrgNewFunction \Value { M }
+  {
+    \__fun_put_result:V #1
+  }
+\cs_set_eq:NN \UseValue \Value
+
+\cs_set_eq:NN \ExpNot \exp_not:n
+\cs_set_eq:NN \ExpValue \exp_not:V
+
+\cs_new_protected:Npn \__fun_return_result:
+  {
+    \int_compare:nNnT { \g__fun_nesting_level_int } = { 0 }
+      { \tl_use:N \gResultTl }
+  }
+
+\tl_new:N \l__fun_variable_type_tl
+
+\prg_new_protected_conditional:Npnn \__fun_if_global_variable:N #1 { TF }
+  {
+    \tl_set:Ne \l__fun_variable_type_tl
+      { \exp_args:Ne \tl_head:n { \cs_to_str:N #1 } }
+    \str_if_eq:VnTF \l__fun_variable_type_tl { g }
+      { \prg_return_true: }
+      {
+        \str_if_eq:VnTF \l__fun_variable_type_tl { c }
+          { \prg_return_true: }
+          { \prg_return_false: }
+      }
+  }
+
+%% We must not put an assignment inside a group
+\cs_new_protected:Npn \__fun_do_assignment:Nnn #1 #2 #3
+  {
+    \__fun_group_end:
+    \__fun_if_global_variable:NTF #1 { #2 } { #3 }
+    \__fun_group_begin:
+  }
+
+\bool_new:N \l__fun_scoping_bool
+
+\cs_new_protected:Npn \__fun_scoping_true:
+  {
+    \cs_set_eq:NN \__fun_group_begin: \group_begin:
+    \cs_set_eq:NN \__fun_group_end: \group_end:
+  }
+
+\cs_new_protected:Npn \__fun_scoping_false:
+  {
+    \cs_set_eq:NN \__fun_group_begin: \scan_stop:
+    \cs_set_eq:NN \__fun_group_end: \scan_stop:
+  }
+
+\cs_new_protected:Npn \__fun_scoping_set:
+  {
+    \bool_if:NTF \l__fun_scoping_bool
+      { \__fun_scoping_true: } { \__fun_scoping_false: }
+  }
+
+\bool_new:N \l__fun_tracing_bool
+\tl_new:N \l__tracing_text_tl
+
+\cs_new_protected:Npn \__fun_tracing_log_on:n #1
+  {
+    \tl_set:Ne \l__tracing_text_tl
+      {
+        \prg_replicate:nn
+          { \int_eval:n { (\g__fun_nesting_level_int - 1) * 4 } } { ~ }
+      }
+    \tl_put_right:Nn \l__tracing_text_tl { #1 }
+    \iow_log:V \l__tracing_text_tl
+  }
+\cs_generate_variant:Nn \__fun_tracing_log_on:n { e, V }
+
+\cs_new_protected:Npn \__fun_tracing_log_off:n #1 { }
+\cs_generate_variant:Nn \__fun_tracing_log_off:n { e, V }
+
+\cs_new_protected:Npn \__fun_tracing_true:
+  {
+    \cs_set_eq:NN \__fun_tracing_log:n \__fun_tracing_log_on:n
+    \cs_set_eq:NN \__fun_tracing_log:e \__fun_tracing_log_on:e
+    \cs_set_eq:NN \__fun_tracing_log:V \__fun_tracing_log_on:V
+  }
+
+\cs_new_protected:Npn \__fun_tracing_false:
+  {
+    \cs_set_eq:NN \__fun_tracing_log:n \__fun_tracing_log_off:n
+    \cs_set_eq:NN \__fun_tracing_log:e \__fun_tracing_log_off:e
+    \cs_set_eq:NN \__fun_tracing_log:V \__fun_tracing_log_off:V
+  }
+
+\cs_new_protected:Npn \__fun_tracing_set:
+  {
+    \bool_if:NTF \l__fun_tracing_bool
+      { \__fun_tracing_true: } { \__fun_tracing_false: }
+  }
+
+\keys_define:nn { functional }
+  {
+    scoping .bool_set:N = \l__fun_scoping_bool,
+    tracing .bool_set:N = \l__fun_tracing_bool,
+  }
+
+\NewDocumentCommand \Functional { m }
+  {
+    \keys_set:nn { functional } { #1 }
+    \__fun_scoping_set:
+    \__fun_tracing_set:
+  }
+
+\Functional { scoping = false, tracing = false }
+
+\PrgNewFunction \UseOne { n }
+  {
+    \Result { #1 }
+  }
+
+\PrgNewFunction \GobbleOne { n }
+  {
+    \Result { }
+  }
+
+\PrgNewFunction \UseGobble { n n }
+  {
+    \UseOne { #1 }
+  }
+
+\PrgNewFunction \GobbleUse { n n }
+  {
+    \UseOne { #2 }
+  }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Control Structures (l3prg)}
+%%% --------------------------------------------------------
+
+\bool_const:Nn \cTrueBool { \c_true_bool }
+\bool_const:Nn \cFalseBool { \c_false_bool }
+
+\bool_new:N \lTmpaBool   \bool_new:N \lTmpbBool   \bool_new:N \lTmpcBool
+\bool_new:N \lTmpiBool   \bool_new:N \lTmpjBool   \bool_new:N \lTmpkBool
+\bool_new:N \l at Funx@Bool \bool_new:N \l at Funy@Bool \bool_new:N \l at Funz@Bool
+
+\bool_new:N \gTmpaBool   \bool_new:N \gTmpbBool   \bool_new:N \gTmpcBool
+\bool_new:N \gTmpiBool   \bool_new:N \gTmpjBool   \bool_new:N \gTmpkBool
+\bool_new:N \g at Funx@Bool \bool_new:N \g at Funy@Bool \bool_new:N \g at Funz@Bool
+
+\cs_set_eq:NN \BoolNew \bool_new:N
+\cs_set_eq:NN \BoolLog \bool_log:N
+
+\PrgNewFunction \BoolSetTrue { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \bool_gset_true:N #1 } { \bool_set_true:N #1 }
+  }
+
+\PrgNewFunction \BoolSetFalse { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \bool_gset_false:N #1 } { \bool_set_false:N #1 }
+  }
+
+\PrgNewConditional \BoolIf { N }
+  {
+    \Result { #1 }
+  }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Token Lists (l3tl)}
+%%% --------------------------------------------------------
+
+\tl_new:N \lTmpaTl   \tl_new:N \lTmpbTl   \tl_new:N \lTmpcTl
+\tl_new:N \lTmpiTl   \tl_new:N \lTmpjTl   \tl_new:N \lTmpkTl
+\tl_new:N \l at Funx@Tl \tl_new:N \l at Funy@Tl \tl_new:N \l at Funz@Tl
+
+\tl_new:N \gTmpaTl   \tl_new:N \gTmpbTl   \tl_new:N \gTmpcTl
+\tl_new:N \gTmpiTl   \tl_new:N \gTmpjTl   \tl_new:N \gTmpkTl
+\tl_new:N \g at Funx@Tl \tl_new:N \g at Funy@Tl \tl_new:N \g at Funz@Tl
+
+\cs_set_eq:NN \TlNew \tl_new:N
+\cs_set_eq:NN \TlLog \tl_log:N
+
+\PrgNewFunction \TlClear { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \tl_gclear:N #1 } { \tl_clear:N #1 }
+  }
+
+\PrgNewFunction \TlSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \tl_gset:Nn #1 {#2} } { \tl_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlPutLeft { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \tl_gput_left:Nn #1 {#2} } { \tl_put_left:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlPutRight { M m }
+  {
+    \__fun_do_assignment:Nnn #1
+      { \tl_gput_right:Nn #1 {#2} } { \tl_put_right:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \TlUse { M }
+  {
+    \Result { \Value #1 }
+  }
+
+\PrgNewConditional \TlIfEmpty { N }
+  {
+    \tl_if_empty:NTF #1
+      { \Result { \cTrueBool } }
+      { \Result { \cFalseBool } }
+  }
+
+\PrgNewConditional \TlIfEq { N N }
+  {
+    \tl_if_eq:NNTF #1 #2
+      { \Result { \cTrueBool } }
+      { \Result { \cFalseBool } }
+  }
+
+%%% --------------------------------------------------------
+%%> \section{Interfaces for Integers (l3int)}
+%%% --------------------------------------------------------
+
+\int_new:N \lTmpaInt   \int_new:N \lTmpbInt   \int_new:N \lTmpcInt
+\int_new:N \lTmpiInt   \int_new:N \lTmpjInt   \int_new:N \lTmpkInt
+\int_new:N \l at Funx@Int \int_new:N \l at Funy@Int \int_new:N \l at Funz@Int
+
+\int_new:N \gTmpaInt   \int_new:N \gTmpbInt   \int_new:N \gTmpcInt
+\int_new:N \gTmpiInt   \int_new:N \gTmpjInt   \int_new:N \gTmpkInt
+\int_new:N \g at Funx@Int \int_new:N \g at Funy@Int \int_new:N \g at Funz@Int
+
+\cs_set_eq:NN \IntNew \int_new:N
+\cs_set_eq:NN \IntLog \int_log:N
+
+\PrgNewFunction \IntZero { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gzero:N #1 } { \int_zero:N #1 }
+  }
+
+\PrgNewFunction \IntIncr { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gincr:N #1 } { \int_incr:N #1 }
+  }
+
+\PrgNewFunction \IntDecr { M }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gdecr:N #1 } { \int_decr:N #1 }
+  }
+
+\PrgNewFunction \IntSet { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gset:Nn #1 {#2} } { \int_set:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \IntAdd { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gadd:Nn #1 {#2} } { \int_add:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \IntSub { M m }
+  {
+    \__fun_do_assignment:Nnn #1 { \int_gsub:Nn #1 {#2} } { \int_sub:Nn #1 {#2} }
+  }
+
+\PrgNewFunction \IntUse { M }
+  {
+    \Result { \Value #1 }
+  }
+
+\PrgNewFunction \IntEval { m }
+  {
+    \Result { \Expand { \int_eval:n { #1 } } }
+  }
+
+\PrgNewFunction \IntMathAdd { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 + #2 } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathSub { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 - #2 } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathMult { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 * #2 } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntMathDiv { m m }
+  {
+    \int_set:Nn \l at Funx@Int { \int_eval:n { #1 / #2 } }
+    \Result { \Value \l at Funx@Int }
+  }
+
+\PrgNewFunction \IntStepVariable { m m m M n }
+  {
+    \int_step_variable:nnnNn { #1 } { #2 } { #3 } #4 { #5 }
+  }
+
+\PrgNewConditional \IntCompare { m N m }
+  {
+    \int_compare:nNnTF {#1} #2 {#3}
+      { \Result { \cTrueBool } }
+      { \Result { \cFalseBool } }
+  }
+


Property changes on: branches/branch2021.final/Master/texmf-dist/tex/latex/functional/functional.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: branches/branch2021.final/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
===================================================================
--- branches/branch2021.final/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2022-03-11 23:36:20 UTC (rev 62647)
+++ branches/branch2021.final/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2022-03-11 23:36:45 UTC (rev 62648)
@@ -543,6 +543,7 @@
 depend fullblck
 depend fullminipage
 depend fullwidth
+depend functional
 depend fundus-calligra
 depend fundus-cyr
 depend fundus-sueterlin

Added: branches/branch2021.final/Master/tlpkg/tlpsrc/functional.tlpsrc
===================================================================


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