
Me gustaría diseñar un \comparator
comando expandible que se base fpeval
en 3 ramas:
- rama verdaderacuando la comparación es igual a 1
- rama falsacuando la comparación es igual a cero
- rama inválidacuando no se puede realizar la comparación (en lugar de devolver un error de compilación)
Aquí está el código actual que uso:
\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xfp}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\compare}{r[] m m m m m}{
\compare_evaluation:eeennn{#1}{#2}{#3}{#4}{#5}{#6}
}
\cs_new:Nn \compare_evaluation:nnnnnn{
\compare_result:ennn{\fpeval{#2 #1 #3}}{#4}{#5}{#6}
}
\cs_new:Nn \compare_result:nnnn{
\str_case:nnTF{#1}{
{0}{#3}
{1}{#2}
}{}{#4}
}
\cs_generate_variant:Nn \compare_evaluation:nnnnnn{eeennn}
\cs_generate_variant:Nn \compare_result:nnnn{ennn}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{c}
\compare[<]{1.5}{2.5}{true}{false}{invalid} \\
\compare[<]{2.5}{1.5}{true}{false}{invalid} \\
\compare[<]{xx}{xx}{true}{false}{invalid} \\ % CRASHES
\end{tabular}
\end{document}
que, por supuesto, falla en la última línea de la prueba.
PREGUNTA:¿Cómo hacerlo compilable y bifurcado correctamente (aquí para imprimir invalid
)?
Respuesta1
Si la capacidad de expansión no es un requisito, puede verificar la sintaxis usando una expresión regular
\documentclass[preview = true, varwidth = true]{standalone}
% These only needed in old latex releases
% \usepackage{xparse}
% \usepackage{xfp}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\compare}{r[] m m m m m}{
\compare_evaluation:eeennn{#1}{#2}{#3}{#4}{#5}{#6}
}
\cs_new:Nn \compare_evaluation:nnnnnn{
\regex_match:nnTF
{^[0-9]*(\.[0-9]*)?([eE][0-9]+)?@@@[0-9]*(\.[0-9]*)?([eE][0-9]+)?$}
{#2@@@#3}
{
\compare_result:ennn{\fpeval{#2 #1 #3}}{#4}{#5}{#6}
}
{#6}
}
\cs_new:Nn \compare_result:nnnn{
\str_case:nnTF{#1}{
{0}{#3}
{1}{#2}
}{}{#4}
}
\cs_generate_variant:Nn \compare_evaluation:nnnnnn{eeennn}
\cs_generate_variant:Nn \compare_result:nnnn{ennn}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{c}
\compare[<]{1.5}{2.5}{true}{false}{invalid} \\
\compare[<]{2.5}{1.5}{true}{false}{invalid} \\
\compare[<]{2.5e2}{15e3}{true}{false}{invalid} \\
\compare[<]{xx}{xx}{true}{false}{invalid} \\ % CRASHES
\end{tabular}
\end{document}
aquí supuse @@@
que era seguro usarlo como separador, podría usar expresiones regulares en los dos argumentos por separado o usar un comando personalizado tken, pero esto muestra la idea básica. Además, es posible que la expresión regular no sea exactamente la misma sintaxis que l3fp en los casos extremos (y no cubre las expresiones fp), pero capta las sintaxis literales principales.