¿Cómo comprobar un argumento booleano en un comando con argumentos opcionales?

¿Cómo comprobar un argumento booleano en un comando con argumentos opcionales?

Tengo un comando con un argumento opcional y quiero ejecutar algún código dependiendo de si el argumento es trueo false(estoy seguro de que este comando siempre tendrá algún argumento convertible a booleano, porque será un comando privado, no un comando de usuario). ). Con mi código me sale este error:

! Missing number, treated as zero.
<to be read again> 
                   t
l.8     \test{
              }
?

Gracias a todos por cualquier ayuda.

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\newcommand{\test}[1][true]{
\bool_if:NTF{#1}{\message{true}}{\message{false}}
}
\test{}
\ExplSyntaxOff
\end{document}

Respuesta1

Primero, tenga en cuenta que \bool_if:N(TF)espera un único token (el Ntipo -) como argumento, por lo que \bool_if:NTF {true} {T}{F}es sintácticamente inválido. Necesitarías el nargumento -type: \bool_if:nTF {true} {T}{F}. Sin embargo, esto tampoco funciona porque expl3las funciones booleanas de no entienden los literales truey false, por lo que debes ayudarlo a comprender lo que quieres decir.

Puede utilizar, por ejemplo, \str_case:nnFpara comparar el argumento de entrada con una serie de casos predefinidos y, si ninguno coincide, escapar a través de la Frama, lo que permite \bool_if:n(TF)realizar el análisis:

\documentclass{article}
\usepackage{xparse}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand \test { O{true} }
  {
    \bool_if:nTF
      {
        \str_case:nnF {#1}
          { % Known cases
            { true  } { \c_true_bool  }
            { T     } { \c_true_bool  }
            { 1     } { \c_true_bool  }
            %
            { false } { \c_false_bool }
            { F     } { \c_false_bool }
            { 0     } { \c_false_bool }
          }
          {#1} % Otherwise
      }
      { \iow_term:n {true} }
      { \iow_term:n {false} }
  }
%
\test % no argument
\test[true]  \test[1] \test[T] \test[\c_true_bool]  % true input
\test[false] \test[0] \test[F] \test[\c_false_bool] % false input
\test[\int_compare_p:n { 2+2>4 } && !\c_false_bool] % expressions
%
\ExplSyntaxOff
\end{document}

Imprimirá:

true
true
true
true
true
false
false
false
false
false

Tenga en cuenta que esto no protege contra entradas arbitrariamente incorrectas, solo cubre algunos casos adicionales, por lo que no podrá usarcualquier cosacomo entrada. Además, los literales truey falsesólo se reconocen si se usan solos. Es decir, \test[true]funciona \test[false]como se esperaba, pero \test[!true]no lo hará porque !trueno lo reconoce \str_case:nn(TF)y el literal trueva directamente a \bool_if:n(TF), que luego falla como antes.

Además, si se trata de un comando de uso privado que puede garantizar que tendrá un argumento, entonces no tiene sentido hacer que el argumento sea opcional, ya que sólo ralentizará el procesamiento.

Respuesta2

No diste muchos detalles sobre lo que debería hacer tu comando. Pero en lugar de usar los argumentos "verdadero" y "falso" y luego comparar cadenas con ellos, normalmente es mejor usar la sintaxis clave val en el argumento y establecer valores booleanos reales con ellos:

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\keys_define:nn { alek }
 {
   dothis .bool_set:N = \l__alex_dothis_bool
 }

\newcommand{\test}[1][]
 {
  \keys_set:nn {alek}{dothis=true,#1} 
  \bool_if:NTF\l__alex_dothis_bool
   {true}
   {false}
 }
\ExplSyntaxOff

\test{}

\test[dothis]

\test[dothis=false]

\test[]
\end{document}

información relacionada