diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3prg.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3prg.dtx | 433 |
1 files changed, 179 insertions, 254 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3prg.dtx b/Master/texmf-dist/source/latex/expl3/l3prg.dtx index 43e2e77448a..72084e07132 100644 --- a/Master/texmf-dist/source/latex/expl3/l3prg.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3prg.dtx @@ -32,30 +32,26 @@ %% %% ----------------------------------------------------------------------- % -%<package>\RequirePackage{l3names} -%<*dtx> +%<*driver|package> +\RequirePackage{l3names} +%</driver|package> %\fi -\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{% - \def\fileversion{#2}% - \def\filedate{#3/#4/#5}% - \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]% -} -%\iffalse -%</dtx> -%\fi -\GetIdInfo$Id: l3prg.dtx 574 2006-08-21 23:30:10Z morten $ +\GetIdInfo$Id: l3prg.dtx 697 2007-11-27 14:14:54Z morten $ {L3 Experimental control structures} -% -% \iffalse +%\iffalse %<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse \documentclass{l3doc} - \begin{document} -\DocInput{l3prg.dtx} +\DocInput{\filename.\filenameext} \end{document} %</driver> % \fi % +% % \title{The \textsf{l3prg} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ @@ -69,25 +65,25 @@ % % \subsection{Choosing modes} % -% \begin{function}{\mode_vertical_p:| -% \mode_vertical:TF | -% \mode_vertical:T | -% \mode_vertical:F +% \begin{function}{\mode_if_vertical_p:| +% \mode_if_vertical:TF | +% \mode_if_vertical:T | +% \mode_if_vertical:F % } % \begin{syntax} -% "\mode_vertical:TF" "{"<true code>"}" "{"<false code>"}" +% "\mode_if_vertical:TF" "{"<true code>"}" "{"<false code>"}" % \end{syntax} % Determines if \TeX{} is in vertical mode or not and executes either % <true code> or <false code> accordingly. % \end{function} % -% \begin{function}{\mode_horizontal_p:| -% \mode_horizontal:TF | -% \mode_horizontal:T | -% \mode_horizontal:F +% \begin{function}{\mode_if_horizontal_p:| +% \mode_if_horizontal:TF | +% \mode_if_horizontal:T | +% \mode_if_horizontal:F % } % \begin{syntax} -% "\mode_horizontal:TF" "{"<true code>"}" "{"<false code>"}" +% "\mode_if_horizontal:TF" "{"<true code>"}" "{"<false code>"}" % \end{syntax} % Determines if \TeX{} is in horizontal mode or not and executes either % <true code> or <false code> accordingly. @@ -95,25 +91,25 @@ % % % \begin{function}{ -% \mode_inner_p:| -% \mode_inner:TF| -% \mode_inner:T| -% \mode_inner:F +% \mode_if_inner_p:| +% \mode_if_inner:TF| +% \mode_if_inner:T| +% \mode_if_inner:F % } % \begin{syntax} -% "\mode_inner:TF" "{"<true code>"}" "{"<false code>"}" +% "\mode_if_inner:TF" "{"<true code>"}" "{"<false code>"}" % \end{syntax} % Determines if \TeX{} is in inner mode or not and executes either % <true code> or <false code> accordingly. % \end{function} % % \begin{function}{ -% \mode_math:TF| -% \mode_math:T| -% \mode_math:F| +% \mode_if_math:TF| +% \mode_if_math:T| +% \mode_if_math:F| % } % \begin{syntax} -% "\mode_math:TF" "{"<true code>"}" "{"<false code>"}" +% "\mode_if_math:TF" "{"<true code>"}" "{"<false code>"}" % \end{syntax} % Determines if \TeX{} is in math mode or not and executes either % <true code> or <false code> accordingly. @@ -214,14 +210,14 @@ % connected to both parts as sometimes you want to execute some code % depending on the value of a switch (e.g.,~draft/final) and other % times you perhaps want to use it as a predicate function in an -% "\if:w" test. Here \TeX's original concept with "\iffalse" and -% "\iftrue" is a little difficult to handle so the easiest is simply -% to let a boolean either be "\c_true" or "\c_false". This also means -% we get the logical operations And, Or, and Not which can then be -% used on both the boolean type and predicate functions. All -% functions by the name |\prg_if_predicate_| are expandable and -% expect the input to also be fully expandable. More generic -% constructs do not contain |predicate| in their names. +% "\if:w" test. Parsing "\iffalse" +% and "\iftrue" tokens can be quite tricky at times so the easiest is to +% simply let a boolean either be "\c_true" or "\c_false". This +% also means we get the logical operations And, Or, and Not which can +% then be used on both the boolean type and predicate functions. All +% functions by the name |\predicate| are expandable and expect the +% input to also be fully expandable. More generic constructs do not +% contain |predicate| in their names. % % % \subsubsection{The boolean data type} @@ -324,48 +320,49 @@ % % % \begin{function}{% -% \prg_if_predicate:nTF | -% \prg_if_predicate:nT | -% \prg_if_predicate:nF | +% \predicate_p:n | +% \predicate:nTF | +% \predicate:nT | +% \predicate:nF | % } % \begin{syntax} -% "\prg_if_predicate:nTF" "{"<predicate>"}" "{"<true>"}" "{"<false>"}" \\ +% "\predicate:nTF" "{"<list of predicates>"}" "{"<true>"}" +% "{"<false>"}" % \end{syntax} -% The first argument can either be a predicate function like -% "\cs_free_p:N \foo" or one of the logic tests below. +% The functions evaluate the truth value of \m{list of predicates} +% where each predicate is separated by \verb+&&+ or \verb+||+ +% denoting logical And and Or functions. Minimal evaluation is +% carried out so that whenever a truth value cannot be changed +% anymore, the remainding tests are not carried out. Hence +% \begin{verbatim} +% \predicate_p:n{ +% \int_compare_p:nNn 1=1 && +% \predicate_p:n { +% \int_compare_p:nNn 2=3 || +% \int_compare_p:nNn 4=4 || +% \int_compare_p:nNn 1=\error % is skipped +% } && +% \int_compare_p:nNn 2=2 +% } +% \end{verbatim} +% returns \meta{true}. % \end{function} % % % % % \begin{function}{% -% \prg_if_predicate_ors_p:n | -% \prg_if_predicate_or_p:nn | -% \prg_if_predicate_ands_p:n | -% \prg_if_predicate_and_p:nn | -% \prg_if_predicate_not_p:n | +% \predicate_not_p:n | % } % \begin{syntax} -% "\prg_if_predicate_ors_p:n" "{"<predicate> <predicate> ..."}" \\ -% "\prg_if_predicate_or_p:nn" "{"<predicate>"}" "{"<predicate>"}" \\ -% "\prg_if_predicate_ands_p:n" "{"<predicate> <predicate> ..."}" \\ -% "\prg_if_predicate_and_p:nn" "{"<predicate>"}" "{"<predicate>"}" \\ -% "\prg_if_predicate_not_p:n" "{"<predicate>"}" +% "\predicate_not_p:n" "{"<list of predicates>"}" % \end{syntax} -% "\prg_if_predicate_or_p:nn" compares the outcome of two predicate -% functions (or other logic tests) and if either turns out to be -% \m{true} returns \m{true} itself. "\prg_if_predicate_and_p:nn" -% works in a similar way but requires both outcomes to be \m{true} in -% order for it to return \m{true} itself. "\prg_if_predicate_not_p:n" -% reverses the truth value of a predicate test or a logic -% operation. Thus +% "\predicate_not_p:n" +% reverses the truth value of its argument. Thus % \begin{quote} % "\prg_if_predicate_not_p:n {\prg_if_predicate_not_p:n {\c_true}}" % \end{quote} -% ultimately returns \m{true}. The argument of the functions -% "\prg_if_predicate_ors_p:n" and "\prg_if_predicate_ands_p:n" take a -% list of predicate functions (and their arguments) and return either -% \m{true} or \m{false}. +% ultimately returns \m{true}. % \end{function} % % \subsubsection{Generic loops} @@ -446,6 +443,8 @@ % We start by ensuring that the required packages are loaded. % \begin{macrocode} %<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} \RequirePackage{l3quark} \RequirePackage{l3toks} \RequirePackage{l3int} @@ -456,57 +455,57 @@ % % \subsubsection{Choosing modes} % -% \begin{macro}{\mode_vertical_p:} -% \begin{macro}{\mode_vertical:TF} -% \begin{macro}{\mode_vertical:T} -% \begin{macro}{\mode_vertical:F} +% \begin{macro}{\mode_if_vertical_p:} +% \begin{macro}{\mode_if_vertical:TF} +% \begin{macro}{\mode_if_vertical:T} +% \begin{macro}{\mode_if_vertical:F} % For testing vertical mode. % \begin{macrocode} -\def_new:Npn \mode_vertical_p: { +\def_new:Npn \mode_if_vertical_p: { \if_mode_vertical: \c_true \else: \c_false\fi:} -\def_test_function_new:npn{mode_vertical:}{\if_mode_vertical:} +\def_test_function_new:npn{mode_if_vertical:}{\if_mode_vertical:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\mode_horizontal_p:} -% \begin{macro}{\mode_horizontal:TF} -% \begin{macro}{\mode_horizontal:T} -% \begin{macro}{\mode_horizontal:F} +% \begin{macro}{\mode_if_horizontal_p:} +% \begin{macro}{\mode_if_horizontal:TF} +% \begin{macro}{\mode_if_horizontal:T} +% \begin{macro}{\mode_if_horizontal:F} % For testing horizontal mode. % \begin{macrocode} -\def_new:Npn \mode_horizontal_p: { +\def_new:Npn \mode_if_horizontal_p: { \if_mode_horizontal: \c_true \else: \c_false\fi:} -\def_test_function_new:npn{mode_horizontal:}{\if_mode_horizontal:} +\def_test_function_new:npn{mode_if_horizontal:}{\if_mode_horizontal:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\mode_inner_p:} -% \begin{macro}{\mode_inner:TF} -% \begin{macro}{\mode_inner:T} -% \begin{macro}{\mode_inner:F} +% \begin{macro}{\mode_if_inner_p:} +% \begin{macro}{\mode_if_inner:TF} +% \begin{macro}{\mode_if_inner:T} +% \begin{macro}{\mode_if_inner:F} % For testing inner mode. % \begin{macrocode} -\def_new:Npn \mode_inner_p: { +\def_new:Npn \mode_if_inner_p: { \if_mode_inner: \c_true \else: \c_false\fi:} -\def_test_function_new:npn{mode_inner:}{\if_mode_inner:} +\def_test_function_new:npn{mode_if_inner:}{\if_mode_inner:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\mode_math:TF} -% \begin{macro}{\mode_math:T} -% \begin{macro}{\mode_math:F} +% \begin{macro}{\mode_if_math:TF} +% \begin{macro}{\mode_if_math:T} +% \begin{macro}{\mode_if_math:F} % For testing math mode. Uses the kern-save |\scan_align_safe_stop:|. % \begin{macrocode} -\def_test_function_new:npn{mode_math:} { +\def_test_function_new:npn{mode_if_math:} { \scan_align_safe_stop: \if_mode_math: } % \end{macrocode} % \end{macro} @@ -535,8 +534,9 @@ % by using code documented only in Appendix~D of % \emph{The \TeX book}\dots % \begin{macrocode} -\def_new:Npn \group_align_safe_begin: {\if_false:{\fi:\if_num:w0=`}\fi:} -\def_new:Npn \group_align_safe_end: {\if_num:w0=`{\fi:\if_false:}\fi:} +\def_new:Npn \group_align_safe_begin: { + \if_false:{\fi:\if_num:w`}=\c_zero\fi:} +\def_new:Npn \group_align_safe_end: {\if_num:w`{=\c_zero}\fi:} % \end{macrocode} % \end{macro} % \end{macro} @@ -797,15 +797,15 @@ % Defining and setting a boolean is easy. % \begin{macrocode} \def_new:Npn \bool_new:N #1 { \let_new:NN #1 \c_false } -\def_new:Npn \bool_new:c #1 { \let_new:cN #1 \c_false } +\def_new:Npn \bool_new:c #1 { \let_new:cN {#1} \c_false } \def_new:Npn \bool_set_true:N #1 { \let:NN #1 \c_true } -\def_new:Npn \bool_set_true:c #1 { \let:cN #1 \c_true } +\def_new:Npn \bool_set_true:c #1 { \let:cN {#1} \c_true } \def_new:Npn \bool_set_false:N #1 { \let:NN #1 \c_false } -\def_new:Npn \bool_set_false:c #1 { \let:cN #1 \c_false } +\def_new:Npn \bool_set_false:c #1 { \let:cN {#1} \c_false } \def_new:Npn \bool_gset_true:N #1 { \glet:NN #1 \c_true } -\def_new:Npn \bool_gset_true:c #1 { \glet:cN #1 \c_true } +\def_new:Npn \bool_gset_true:c #1 { \glet:cN {#1} \c_true } \def_new:Npn \bool_gset_false:N #1 { \glet:NN #1 \c_false } -\def_new:Npn \bool_gset_false:c #1 { \glet:cN #1 \c_false } +\def_new:Npn \bool_gset_false:c #1 { \glet:cN {#1} \c_false } % \end{macrocode} % \end{macro} % \end{macro} @@ -995,177 +995,102 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\prg_if_predicate:nTF} -% \begin{macro}{\prg_if_predicate:nT} -% \begin{macro}{\prg_if_predicate:nF} -% As the boolean type is actually a predicate function, the next ones -% are just aliases. -% \begin{macrocode} -\let_new:NN \prg_if_predicate:nTF \bool_if:NTF -\let_new:NN \prg_if_predicate:nT \bool_if:NT -\let_new:NN \prg_if_predicate:nF \bool_if:NF -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\prg_if_predicate_or_p:nn} -% \begin{macro}{\prg_if_predicate_and_p:nn} -% \begin{macro}{\prg_if_predicate_not_p:n} -% The logic operations require a little more work. The idea is to have -% the end result of the logic "and" and "or" functions return "00" and -% "01" resp.\ to be used in an "\if:w" test. The arguments of the -% functions are always something expanding to "\c_true" or "\c_false" -% which is usually resulting from a predicate function or from another -% logical operation. All the functions start with a "0" and depending -% on the results of the tests return either "0" or "1" to the input -% stream to form a new true or false statement. -% -% The comments in the following is mostly to convince myseld of the -% validity of the code. -% \begin{macrocode} -\def_new:Npn \prg_if_predicate_or_p:nn #1#2{ -% \end{macrocode} -% Form a number of the input which is one of "0000", "0001", "0100", or -% "0101". If the truth value of both tests are false we get the "0101" -% else we get a number less than that. So we check if the number formed -% is less than $101$. -% \begin{macrocode} - \if_num:w #1#2<\c_hundred_one -% \end{macrocode} -% If it is we put a "\c_true" back into the input stream. +% \begin{macro}{\predicate_p:n} +% \begin{macro}{\predicate:nTF} +% \begin{macro}{\predicate:nT} +% \begin{macro}{\predicate:nF} +% \begin{macro}{\predicate_auxi:NN} +% \begin{macro}{\predicate_auxii:NNN} +% \begin{macro}{\predicate_88_0:w}^^A% fix! +% \begin{macro}{\predicate_88_1:w}^^A% fix! +% \begin{macro}{\predicate_II_0:w}^^A% fix! +% \begin{macro}{\predicate_II_1:w}^^A fix! +% \begin{macro}{\predicate_02_0:w} +% \begin{macro}{\predicate_02_1:w} +% +% Evaluating the truth value of a list of predicates is done using +% an input syntax somewhat similar to the one found in other +% programming languages. The function evaluates predicates from +% left to right, expanding them to 00 and 01 resp., which leads to +% six different situations of tokens in the input stream: +% \begin{itemize} +% \item[\texttt{00\&\&}] Current truth value is true, logical And +% seen, continue to see if next is also true. +% \item[\texttt{01\&\&}] Current truth value is false, logical And +% seen, break the scanning and return \meta{false}. +% \item[\texttt{00\char`\|\char`\|}] Current truth value is true, +% logical Or seen, break the scanning and return \meta{true}. +% \item[\texttt{01\char`\|\char`\|}] Current truth value is false, +% logical Or seen, continue to see if a later predicate is true. +% \item[\texttt{0002}] Current truth value is true, end marker +% seen, return \meta{true}. +% \item[\texttt{0102}] Current truth value is false, end marker +% seen, return \meta{false}. +% \end{itemize} +% To accomplish this we pre-expand the predicate list using |f| +% type expansion which leads to |00| or |01|, possibly with a +% sequence of unfinished |\else: \c_false \fi:| or similar after +% it, which we remove using the same trick. We also carry over the +% truth value of the evaluated predicate. The expansion stops when +% it sees the end marker or \verb+&&+ or \verb+||+ (assuming these +% are not active characters at the programming level). % \begin{macrocode} - \c_true - \else: -% \end{macrocode} -% Otherwise we insert "\c_false". -% \begin{macrocode} - \c_false - \fi: +\def_long_new:Npn \predicate_p:n #1{ + \group_align_safe_begin: + \exp_after:NN \predicate_auxi:NN + \int_to_roman:w-`\q #1 02\scan_stop: } -% \end{macrocode} -% The "and" function is a little different. Again we can have input of -% the types "0000", "0001", "0100", or "0101". As we require both -% values to be \m{true} in order to continue we simply check if the -% number formed by the input is "0" or not and then put the -% corresponding "0" or "1" back in the input stream as above. We could -% use "\if_num:w" for this test as well but that'll require us to read -% the additional "=\c_zero" which runs a little slower than using -% "\if_case:w" directly, so we use the latter. -% \begin{macrocode} -\def_new:Npn \prg_if_predicate_and_p:nn #1#2{ - \if_case:w #1#2 ~ - \c_true - \else: - \c_false - \fi: +\def_long_test_function_new:npn {predicate:n}#1{ + \group_align_safe_begin: + \if:w \exp_after:NN \predicate_auxi:NN + \int_to_roman:w-`\q #1 02\scan_stop: +} +\def_new:Npn \predicate_auxi:NN 0 #1{ + \exp_after:NN \predicate_auxii:NNN \exp_after:NN #1 + \int_to_roman:w-`\q } % \end{macrocode} -% The "not" function checks a single truth value and reverses it. Here -% we either get a "00" or "01". If the input equals "0" we put a "1" -% in the input stream, else we put a "0". Again we use "\if_case:w" -% because it's slightly faster. +% After removing trailing conditionals we call a macro for the case we +% are in (see list above). % \begin{macrocode} -\def_new:Npn \prg_if_predicate_not_p:n #1{ - \if_case:w #1 ~ - \c_false - \or: - \c_true - \fi: +\def_new:Npn \predicate_auxii:NNN #1#2#3{ + \cs_use:c{predicate_#2#3_#1:w} } +\def_new:cpn{predicate_&&_0:w}{ + \exp_after:NN \predicate_auxi:NN\int_to_roman:w-`\q +} +\def_long_new:cpn{predicate_&&_1:w} #1 02\scan_stop:{ + \group_align_safe_end: 01} +\def_long_new:cpn{predicate_||_0:w} #1 02\scan_stop:{ + \group_align_safe_end: 00} +\def_new:cpn{predicate_||_1:w}{ + \exp_after:NN \predicate_auxi:NN\int_to_roman:w-`\q } +\def_new:cpn{predicate_02_0:w}\scan_stop:{ \group_align_safe_end: 00 } +\def_new:cpn{predicate_02_1:w}\scan_stop:{ \group_align_safe_end: 01 } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % -% \begin{macro}{\prg_if_predicate_ors_p:n} -% \begin{macro}{\prg_if_predicate_ands_p:n} -% \begin{macro}{\prg_if_predicate_andor_aux:NNN} -% \begin{macro}{\prg_if_predicate_andor_break:NNN } -% For longer lists of predicates we can't rely on such structures -% as above. The "\prg_if_predicate_ands_p:n" would have been easy to -% program as simply -% \begin{verbatim} -% \def_new:Npn \prg_if_predicate_and_p:n #1 { -% 0\tex_ifcase:D #1 ~ \exp_after:NN 0 \else: \exp_after:NN 1 \fi: -% } -% \end{verbatim} -% but this would fail with a "! Number too big." in case we were -% testing six predicate functions where the first was false. This -% would mean we would have to first convert the string from binary -% into numerical and then check. While challenging and interesting -% in itself (See \textsf{binhex}) it still imposes a restriction of -% 15 predicate functions\footnote{We would probably never hit that -% limit but why create a restriction when we can avoid it?} and we -% haven't dealt with the "or" case either. -% -% The solution below expands a predicate function until |\c_false| or -% |\c_true| are seen and expanded to |01| or |00| respectively. If -% we're testing the logical AND operation, all predicate functions -% must return \meta{true}; if they don't we can exit and return -% \meta{false}. In an OR operation, we just need one predicate -% function to return \meta{true}, the rest don't matter. Since every -% expansion in the internal loop results in a result of either |00| -% or |01|, we can test against this number to decide what to do. -% -% First up is the top level functions. -% \begin{macrocode} -\def_long_new:Npn \prg_if_predicate_ands_p:n #1{ - \exp_after:NN \prg_if_predicate_andor_aux:NNN \exp_after:NN \c_true - \int_to_roman:w -`0 #1 \scan_stop: \scan_stop: -} -\def_long_new:Npn \prg_if_predicate_ors_p:n #1{ - \exp_after:NN \prg_if_predicate_andor_aux:NNN \exp_after:NN \c_false - \int_to_roman:w -`0 #1 \scan_stop: \scan_stop: -} -% \end{macrocode} -% When we reach the inner loop we have already expanded all tokens in -% the first predicate function as far as possible. This means that -% either are arguments |#2| and |#3| \emph{both} |\scan_stop:| or else -% |#2| is |0| and |#3| is |0| if the predicate returned \meta{true} or -% |1| if it returned \meta{false}. If we reached the end we return -% \meta{true} for the AND function and \meta{false} for the OR -% function. If |#3| is |0| and we are doing the OR test, we want to -% exit and return \meta{true}. If |#3| is |0| and we are in the AND -% test we must continue to check the remaining predicate functions. If -% |#3| is |1| and we are in the OR test we continue in case a later -% predicate function returns \meta{true}. Finally, if |#3| is |1| and -% we are in the AND test we can exit and return \meta{false} before -% deciding what to do. -% \begin{macrocode} -\def_new:Npn \prg_if_predicate_andor_aux:NNN #1#2#3{ - \token_if_eq_meaning:NNTF \scan_stop: #2 - { #1 } - { - \int_compare:nNnTF #3 = #1 - { \exp_after:NN \prg_if_predicate_andor_aux:NNN } - { \exp_after:NN \prg_if_predicate_andor_break:NNN } - \exp_after:NN #1 \int_to_roman:w -`0 - } -} -% \end{macrocode} -% The break loop is called when we know what the final outcome -% is. However we keep expanding because a)~we don't know which tokens -% we might have left dangling ahead and b)~it also provides error -% checking on the remaining predicate functions. |#1| is \meta{false} -% for the OR function and \meta{true} for the AND function so we -% reverse them here. +% \begin{macro}{\predicate_not_p:n} +% The "not" variant just reverses the outcome of |\predicate_p:n|. % \begin{macrocode} -\def_new:Npn \prg_if_predicate_andor_break:NNN #1#2#3{ - \token_if_eq_meaning:NNTF \scan_stop: #2 - { \if:w #1\c_false\else:\c_true\fi: } - { - \exp_after:NN \prg_if_predicate_andor_break:NNN \exp_after:NN #1 - \int_to_roman:w -`0 - } +\def_long_new:Npn \predicate_not_p:n #1{ + \if:w \predicate_p:n{#1} \c_false \else: \c_true \fi: } % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} +% \end{macro} +% % % \subsubsection{Sorting} % |