
Eu tenho um comando com um argumento opcional e quero executar algum código dependendo se o argumento for true
ou 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 n
argumento -type: \bool_if:nTF {true} {T}{F}
. No entanto, isso também não funciona porque expl3
as funções booleanas de ' não entendem os literais true
e false
, então você precisa ajudá-lo a entender o que você quer dizer.
Você pode usar, por exemplo, \str_case:nnF
para verificar o argumento de entrada em relação a vários casos predefinidos e, se nenhum corresponder, escapar pela F
ramificaçã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 true
e false
só são reconhecidos se usados sozinhos. Ou seja, \test[true]
e \test[false]
funciona como esperado, mas \test[!true]
não funcionará, porque !true
não é reconhecido por \str_case:nn(TF)
, e o literal true
vai 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}