Como verificar um argumento booleano em um comando com argumentos opcionais?

Como verificar um argumento booleano em um comando com argumentos opcionais?

Eu tenho um comando com um argumento opcional e quero executar algum código dependendo se o argumento for trueou false(tenho certeza que este comando sempre terá algum argumento conversível em booleano, porque será um comando privado, não um comando de usuário ). Com meu código recebo este erro:

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

Obrigado a todos por qualquer ajuda.

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

Responder1

Primeiro, observe que \bool_if:N(TF)espera um único token (o N-type) como argumento, portanto, \bool_if:NTF {true} {T}{F}é sintaticamente inválido. Você precisaria do nargumento -type: \bool_if:nTF {true} {T}{F}. No entanto, isso também não funciona porque expl3as funções booleanas de ' não entendem os literais truee false, então você precisa ajudá-lo a entender o que você quer dizer.

Você pode usar, por exemplo, \str_case:nnFpara verificar o argumento de entrada em relação a vários casos predefinidos e, se nenhum corresponder, escapar pela Framificação, o que permite \bool_if:n(TF)fazer a análise:

\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}

Irá imprimir:

true
true
true
true
true
false
false
false
false
false

Observe que isso não protege contra entradas arbitrariamente ruins, apenas cobre alguns casos extras, portanto você não poderá usarqualquer coisacomo entrada. Além disso, os literais truee falsesó são reconhecidos se usados ​​sozinhos. Ou seja, \test[true]e \test[false]funciona como esperado, mas \test[!true]não funcionará, porque !truenão é reconhecido por \str_case:nn(TF), e o literal truevai diretamente para \bool_if:n(TF), que falha como antes.

Além disso, se for um comando de uso privado que você pode garantir que terá um argumento, então não faz sentido tornar o argumento opcional, pois isso apenas retardará o processamento.

Responder2

Você não deu muitos detalhes sobre o que seu comando deveria fazer. Mas em vez de usar argumentos "true" e "false" e depois fazer uma comparação de strings com eles, normalmente é melhor usar a sintaxe key val no argumento e definir booleanos reais com eles:

\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}

informação relacionada