summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prg.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx174
1 files changed, 162 insertions, 12 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index 7339862d22d..2636aa962af 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
@@ -22,8 +22,6 @@
%
%<*driver>
\documentclass[full]{l3doc}
-\def\ExplFileDate{2017/03/18}
-\def\ExplFileVersion{7019}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
@@ -32,8 +30,6 @@
%
% \title{^^A
% The \pkg{l3prg} package\\ Control structures^^A
-% \thanks{This file describes v\ExplFileVersion,
-% last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
@@ -45,7 +41,7 @@
% }^^A
% }
%
-% \date{Released \ExplFileDate}
+% \date{Released 2017/04/01}
%
% \maketitle
%
@@ -178,8 +174,8 @@
% \cs{prg_new_eq_conditional:NNn} \cs[no-index]{\meta{name_1}:\meta{arg spec_1}} \cs[no-index]{\meta{name_2}:\meta{arg spec_2}} \Arg{conditions}
% \end{syntax}
% These functions copy a family of conditionals. The \texttt{new} version
-% will check for existing definitions (\emph{cf.}~\cs{cs_new:Npn}) whereas
-% the \texttt{set} version will not (\emph{cf.}~\cs{cs_set:Npn}). The
+% will check for existing definitions (\emph{cf.}~\cs{cs_new_eq:NN}) whereas
+% the \texttt{set} version will not (\emph{cf.}~\cs{cs_set_eq:NN}). The
% conditionals copied are depended on the comma-separated list of
% \meta{conditions}, which should be one or more of \texttt{p}, \texttt{T},
% \texttt{F} and \texttt{TF}.
@@ -190,7 +186,7 @@
% \cs{prg_return_true:}
% \cs{prg_return_false:}
% \end{syntax}
-% These `return' functions define the logical state of a conditional statement.
+% These \enquote{return} functions define the logical state of a conditional statement.
% They appear within the code for a conditional
% function generated by \cs{prg_set_conditional:Npnn}, \emph{etc}, to indicate
% when a true or false branch should be taken.
@@ -198,7 +194,7 @@
% the execution of the conditional must result in the expansion of one of these
% two functions \emph{exactly once}.
%
-% The return functions trigger what is internally an f-expansion process to complete
+% The return functions trigger what is internally an \texttt{f}-expansion process to complete
% the evaluation of the conditional. Therefore, after \cs{prg_return_true:} or \cs{prg_return_false:}
% there must be no non-expandable material in the input stream for the remainder of
% the expansion of the conditional code. This includes other instances of either of these functions.
@@ -271,7 +267,7 @@
% \begin{syntax}
% \cs{bool_set_eq:NN} \meta{boolean_1} \meta{boolean_2}
% \end{syntax}
-% Sets the content of \meta{boolean_1} equal to that of \meta{boolean_2}.
+% Sets \meta{boolean_1} to the current value of \meta{boolean_2}.
% \end{function}
%
% \begin{function}[updated = 2012-07-08]
@@ -373,7 +369,41 @@
% is a valid boolean expression.
%
% At present, the infix operators |&&| and \verb"||" perform lazy
-% evaluation as well, but this will change in a future release.
+% evaluation, but this will change in the near future.
+% Contrarily to some other programming languages, the operators |&&| and
+% \verb"||" will evaluate both operands in all cases, even when the first
+% operand is enough to determine the result. This \enquote{eager}
+% evaluation should be contrasted with the \enquote{lazy} evaluation of
+% \cs[no-index]{bool_lazy_\ldots{}} functions.
+%
+% \begin{texnote}
+% The eager evaluation of boolean expressions is unfortunately
+% necessary. Indeed, a lazy parser can get confused if |&&| and
+% \verb"||" appear as (unbraced) arguments of some predicates.
+% \end{texnote}
+%
+% Minimal (lazy) evaluation can be obtained using the conditionals
+% \cs{bool_lazy_all:nTF}, \cs{bool_lazy_and:nnTF}, \cs{bool_lazy_any:nTF}, or
+% \cs{bool_lazy_or:nnTF}, which only evaluate their boolean expression
+% arguments when they are needed to determine the resulting truth
+% value. For example, when evaluating the boolean expression
+% \begin{verbatim}
+% \bool_lazy_and_p:nn
+% {
+% \bool_lazy_any_p:n
+% {
+% { \int_compare_p:n { 2 = 3 } }
+% { \int_compare_p:n { 4 <= 4 } }
+% { \int_compare_p:n { 1 = \error } } % skipped
+% }
+% }
+% { ! \int_compare_p:n { 2 = 4 } }
+% \end{verbatim}
+% the line marked with |skipped| is not expanded because the result
+% of \cs{bool_lazy_any_p:n} is known once the second boolean expression is
+% found to be logically \texttt{true}. On the other hand, the last
+% line is expanded because its logical value is needed to determine the
+% result of \cs{bool_lazy_and_p:nn}.
%
% \begin{function}[EXP, pTF, updated = 2012-07-08]{\bool_if:n}
% \begin{syntax}
@@ -388,6 +418,60 @@
% |!| (\enquote{Not}) and parentheses. The logical Not applies to
% the next predicate or group.
% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_all:n}
+% \begin{syntax}
+% \cs{bool_lazy_all_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \}
+% \cs{bool_lazy_all:nTF} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{And} operation on the \meta{boolean
+% expressions}, hence is \texttt{true} if all of them are
+% \texttt{true} and \texttt{false} if any of them is \texttt{false}.
+% Contrarily to the infix operator |&&|, only the \meta{boolean
+% expressions} which are needed to determine the result of
+% \cs{bool_lazy_all:nTF} will be evaluated. See also \cs{bool_lazy_and:nnTF}
+% when there are only two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_and:nn}
+% \begin{syntax}
+% \cs{bool_lazy_and_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
+% \cs{bool_lazy_and:nnTF} \Arg{boolexpr_1} \Arg{boolexpr_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{And} operation between two boolean
+% expressions, hence is \texttt{true} if both are \texttt{true}.
+% Contrarily to the infix operator |&&|, the \meta{boolexpr_2} will
+% only be evaluated if it is needed to determine the result of
+% \cs{bool_lazy_and:nnTF}. See also \cs{bool_lazy_all:nTF} when there are more
+% than two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_any:n}
+% \begin{syntax}
+% \cs{bool_lazy_any_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \}
+% \cs{bool_lazy_any:nTF} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{Or} operation on the \meta{boolean
+% expressions}, hence is \texttt{true} if any of them is
+% \texttt{true} and \texttt{false} if all of them are \texttt{false}.
+% Contrarily to the infix operator \verb"||", only the \meta{boolean
+% expressions} which are needed to determine the result of
+% \cs{bool_lazy_any:nTF} will be evaluated. See also \cs{bool_lazy_or:nnTF}
+% when there are only two \meta{boolean expressions}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2015-11-15]{\bool_lazy_or:nn}
+% \begin{syntax}
+% \cs{bool_lazy_or_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
+% \cs{bool_lazy_or:nnTF} \Arg{boolexpr_1} \Arg{boolexpr_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Implements the \enquote{Or} operation between two boolean
+% expressions, hence is \texttt{true} if either one is \texttt{true}.
+% Contrarily to the infix operator \verb"||", the \meta{boolexpr_2}
+% will only be evaluated if it is needed to determine the result of
+% \cs{bool_lazy_or:nnTF}. See also \cs{bool_lazy_any:nTF} when there are more
+% than two \meta{boolean expressions}.
+% \end{function}
%
% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n}
% \begin{syntax}
@@ -1231,6 +1315,72 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[pTF]{\bool_lazy_all:n}
+% \begin{macro}[aux]{\@@_lazy_all:n}
+% \UnitTested
+% Go through the list of expressions, stopping whenever an expression
+% is \texttt{false}. If the end is reached without finding any
+% \texttt{false} expression, then the result is \texttt{true}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_all:n #1 { p , T , F , TF }
+ { \@@_lazy_all:n #1 \q_recursion_tail \q_recursion_stop }
+\cs_new:Npn \@@_lazy_all:n #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \prg_return_true: }
+ \bool_if:nF {#1}
+ { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_false: } }
+ \@@_lazy_all:n
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_and:nn}
+% \UnitTested
+% Only evaluate the second expression if the first is \texttt{true}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_and:nn #1#2 { p , T , F , TF }
+ {
+ \bool_if:nTF {#1}
+ { \bool_if:nTF {#2} { \prg_return_true: } { \prg_return_false: } }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_any:n}
+% \begin{macro}[aux]{\@@_lazy_any:n}
+% \UnitTested
+% Go through the list of expressions, stopping whenever an expression
+% is \texttt{true}. If the end is reached without finding any
+% \texttt{true} expression, then the result is \texttt{false}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_any:n #1 { p , T , F , TF }
+ { \@@_lazy_any:n #1 \q_recursion_tail \q_recursion_stop }
+\cs_new:Npn \@@_lazy_any:n #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \prg_return_false: }
+ \bool_if:nT {#1}
+ { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_true: } }
+ \@@_lazy_any:n
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\bool_lazy_or:nn}
+% \UnitTested
+% Only evaluate the second expression if the first is \texttt{false}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \bool_lazy_or:nn #1#2 { p , T , F , TF }
+ {
+ \bool_if:nTF {#1}
+ { \prg_return_true: }
+ { \bool_if:nTF {#2} { \prg_return_true: } { \prg_return_false: } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\bool_not_p:n}
% \UnitTested
% The Not variant just reverses the outcome of \cs{bool_if_p:n}. Can
@@ -1245,7 +1395,7 @@
% \begin{macro}{\bool_xor_p:nn}
% \UnitTested
% Exclusive or. If the boolean expressions have same truth value,
-% return false, otherwise return true.
+% return \texttt{false}, otherwise return \texttt{true}.
% \begin{macrocode}
\cs_new:Npn \bool_xor_p:nn #1#2
{