5

I'm implementing a command with xparse's boolean token processing

\NewDocumentCommand{\op}{s o t' t. t^ g}{
    % Here I need to check for
    %     (#3 || #4 || #5) && !(#3 && #4 && #5)
}

I'd like to avoid all the \IfBooleanTF combinations and instead to check via \bool_if:nTF. That is, of the boolean tokens passed to the function not all at the same time should be true or false. Testing with \IfBooleanTF for

(p ∨ q ∨ r) ∧ ¬(p ∧ q ∧ r)

is very tedious (a higher-order exclusive disjunction, XOR), especially given more such arguments.

I could assign boolean "variables" in expl3 based on xparse's tests, e.g.,

\IfBooleanTF{#1}
{\bool_set_true:N \l_first_arg_bool}
{\bool_set_false:N \l_first_arg_bool}

That's okay. But is there a way to access the boolean flags set by xparse for the arguments directly?

  • 1
    Welcome do TeX-SX! Could you please try to explain your question in more detail and describe what you are trying to do? – ienissei Oct 5 '15 at 9:59
  • 1
    Take a look into xparse.sty. The flags seem to exist only locally – user31729 Oct 5 '15 at 11:08
  • Can't you just pass all variables to the underlying function and make the test there? – clemens Oct 5 '15 at 11:21
  • @ChristianHupfer: Good idea, I'll take a look. – user89173 Oct 5 '15 at 11:24
  • @clemens: What do you mean by an underlying function? – user89173 Oct 5 '15 at 11:24
5

It is probably not such a good idea to rely on an implementation detail, but xparse defines

\cs_new_eq:NN \BooleanFalse \c_false_bool
\cs_new_eq:NN \BooleanTrue  \c_true_bool

which means that the booleans that are signalled by your arguments are just regular expl3 booleans which can go directly into \bool_if:nTF.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \op { s o t' t. t^ g }
{
  \bool_if:nTF { (#3 || #4 || #5) && !(#3 && #4 && #5) }
    { True }
    { False }
}

\ExplSyntaxOff

\begin{document}

\op*[foo]'.^{bar} % False

\end{document}
2

Implementing this XOR is quite easy:

\int_new:Nn \l_foo_bad_check_int

\NewDocumentCommand{\bad}{t' t. t^}
 {
  \int_zero:N \l_foo_bad_check_int
  \IfBooleanTF { #1 } { \int_incr:N \l_foo_bad_check_int }
  \IfBooleanTF { #2 } { \int_incr:N \l_foo_bad_check_int }
  \IfBooleanTF { #3 } { \int_incr:N \l_foo_bad_check_int }
  \int_compare:nTF { 0 < \l_foo_bad_check_int < 3 }
   { Good }
   { Bad }
 }

On the other hand, such a syntax would be confusing even for the macro creator, particularly with an argument specifier such as

s o t' t. t^ g

with six optional parts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.