8

There's \int_case:Nnn, \tl_case:Nnn, \str_case:Nnn, but I can't find something like \bool_case:Nnn.

I know I can write:

\bool_if:NT \l__<mymodule>_<nameA>_bool { ... }
\bool_if:NT \l__<mymodule>_<nameB>_bool { ... }
\bool_if:NT \l__<mymodule>_<nameC>_bool { ... }
\bool_if:NT \l__<mymodule>_<nameD>_bool { ... }

to achieve something of the same effect, or even

\bool_if:NTF \l__<mymodule>_<nameA>_bool 
{
   <some code>
}
{
    \bool_if:NTF \l__<mydoclue>_<nameB>_bool
    {
        <some code>
    }
    {
        <continue nesting w/ default value in last *F*> 
    }
}

But the first example evaluates all the booleans and there is not clean way to have a default value if all fail. The second example is just really clunky, difficult to read and hard to change if, for example, you later decide that the booleans should be tested in a different order.

Is there an alternative I'm not thinking of?

  • Well, booleans are true or false. You're thinking to something like \elseif which doesn't seem to fit in the model. – egreg Jun 25 '13 at 19:55
  • @egreg I know. But I have a bunch of switches that are either on or off. They're listed in a particular order, which ever of the earlier switches is first turned on should result in behavior just for that switch (regardless of the settings of later switches). If none of the switches are turned on, then I want a default state. – A.Ellett Jun 25 '13 at 19:58
  • @egreg I suppose I could set a \tl_<variable> with each switch and then do a \tl_case:Nnn on the values of the tokens. But it seems like it would be cleaner if I could do it without having to nest or add a layer of something else to effect the testing. – A.Ellett Jun 25 '13 at 19:59
  • 3
    Do you want something like ||? A boolean expression is an expression which given input in the form of predicate functions and boolean variables, return boolean ⟨true⟩ or ⟨false⟩. It supports the logical operations And, Or and Not as the well-known infix operators &&, || and ! with their usual precedences. In addition to this, parentheses can be used to isolate sub-expressions. – Marco Daniel Jun 25 '13 at 20:03
  • 1
    One might encode a set of booleans in a number in binary form and then do a \int_case:nnn using this number. – egreg Jun 25 '13 at 20:07
4

Adapting the code from \tl_case:Nnn, I have this:

\documentclass{minimal}
\usepackage{expl3, xparse}

\ExplSyntaxOn

\cs_new:Npn \bool_case:nn #1#2
  {
    \tex_romannumeral:D
      \__bool_case:w #1 \c_true_bool {#2} \q_recursion_stop
  }
\cs_new:Npn \__bool_case:w #1#2
  {
    \bool_if:nTF { #1 }
      { \__bool_case_end:nw {#2} }
      { \__bool_case:w }
  }
\cs_new_eq:NN \__bool_case_end:nw \__prg_case_end:nw

\bool_gset_false:N \g_tmpa_bool
\bool_gset_true:N \g_tmpb_bool

\NewDocumentCommand \testboolcase {} {
    \bool_case:nn {
        \g_tmpa_bool { false;~ can't~ happen }
        \g_tmpb_bool { true;~ should~ happen }
      }
      { else;~ can't~ happen }
  }

\NewDocumentCommand \testboolcaseelse {} {
    \bool_case:nn {
        \g_tmpa_bool { false;~ can't~ happen }
        { !\g_tmpb_bool } { false;~ can't~ happen }
      }
      { else;~ should~ happen }
  }

\ExplSyntaxOff

\begin{document}
\testboolcase

\testboolcaseelse
\end{document}

Note that some boolean expressions work, but things like { 1 = 2 } won’t.

  • Very nice. This is exactly what I was looking for. Now to figure out why this does what it does. – A.Ellett Jun 27 '13 at 5:03
  • @A.Ellett, that’s a new question: How do the \xx_case: functions work? – J. C. Salomon Jun 27 '13 at 15:03
  • Note that this is now \bool_case:nn, not \bool_case:Nnn. Numbers in the boolean expressions will confuse \romannumeral. – J. C. Salomon Jun 27 '13 at 16:37
  • Unfortunately this code no longer compiles, it seems to be related to \__prg_case_end:nw. I have found use of a \bool_case:nn in a personal package. Will you update the answer or is it a new question? – Simon Jul 24 '18 at 18:55
  • @Simon, I’d suggest looking up the current version of \tl_case:Nnn and see if you can adapt the code accordingly—a new answer is probably the right way to go, unless the change to my code above is trivial. (I have not touched this in years and can’t follow it to fix it right now.) – J. C. Salomon Jul 24 '18 at 19:37
1

I think I'm looking for something like

\bool_new:N \l_ae_a_bool
\bool_new:N \l_ae_b_bool
\bool_new:N \l_ae_c_bool
\bool_new:N \l_ae_d_bool

<intermediary code>

\bool_new:N \l_ae_continue_bool
\bool_set_false:N \l_ae_continue_bool
\bool_if:NTF \l_ae_a_bool 
  { 
    <code-a> 
    \bool_set_false:N \l_ae_continue_bool %% here for just good measure!
  } 
  { 
     \bool_set_true:N \l_ae_continue_bool 
  }
\bool_if:NT \l_ae_continue_bool
  {
    \bool_if:NTF \l_ae_b_bool 
      {
        <code-b> 
        \bool_set_false:N \l_ae_continue_bool
      } 
      { 
        \bool_set_true:N \l_ae_continue_bool 
      }
  }
\bool_if:NT \l_ae_continue_bool
  {
    \bool_if:NTF \l_ae_c_bool 
      {
        <code-c> 
        \bool_set_false:N \l_ae_continue_bool
      } 
      { 
        \bool_set_true:N \l_ae_continue_bool 
      }
  }
\bool_if:NT \l_ae_continue_bool
  {
    \bool_if:NTF \l_ae_d_bool 
      {
        <code-d> 
        \bool_set_false:N \l_ae_continue_bool
      } 
      { 
        \bool_set_true:N \l_ae_continue_bool 
      }
  }
\bool_if:NF \l_ae_continue_bool
  {
    <default code>
  }
  • Is this a solution? If not please edit your original question and remove this one. Thanks – Marco Daniel Jun 26 '13 at 5:11
  • @MarcoDaniel It does what I want to accomplish. So, I'd say it's a solution, but I was hoping someone could come up with something better. – A.Ellett Jun 26 '13 at 5:15

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.