
Tengo un comando con un argumento opcional y quiero ejecutar algún código dependiendo de si el argumento es true
o 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 N
tipo -) como argumento, por lo que \bool_if:NTF {true} {T}{F}
es sintácticamente inválido. Necesitarías el n
argumento -type: \bool_if:nTF {true} {T}{F}
. Sin embargo, esto tampoco funciona porque expl3
las funciones booleanas de no entienden los literales true
y false
, por lo que debes ayudarlo a comprender lo que quieres decir.
Puede utilizar, por ejemplo, \str_case:nnF
para comparar el argumento de entrada con una serie de casos predefinidos y, si ninguno coincide, escapar a través de la F
rama, 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 true
y false
sólo se reconocen si se usan solos. Es decir, \test[true]
funciona \test[false]
como se esperaba, pero \test[!true]
no lo hará porque !true
no lo reconoce \str_case:nn(TF)
y el literal true
va 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}