diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prg.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3prg.dtx | 174 |
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 { |