¿Cómo saber con certeza en contextos de expansión el momento en que está ahí el resultado de una función expl3 totalmente expandible?

¿Cómo saber con certeza en contextos de expansión el momento en que está ahí el resultado de una función expl3 totalmente expandible?

Hay muchas funciones proporcionadas por el entorno de programación expl3 que en interface3.pdf están marcadas con un asterisco negro (completamente ampliable) o con un asterisco blanco (ampliable restringida).

¿Por qué tantas funciones están marcadas como totalmente expandibles sin proporcionar información oficial sobre la cantidad de expansiones necesarias para obtener el resultado?

Bueno, con algunas cosas recursivas de cola completamente expandibles donde los medios de control de expansión como \exp:w/ \exp_end:no se aplican en la implementación, tanto la cantidad de recursiones como la cantidad de expansiones necesarias para obtener el resultado dependen de los argumentos proporcionados por los usuarios. Por lo tanto, allí no se puede proporcionar información exacta sobre la cantidad de expansiones necesarias para obtener el resultado.

Pero hay muchas funciones en las que este no es el caso y en las que se puede proporcionar información exacta sobre la cantidad de expansiones necesarias para obtener el resultado.

¿Cómo, con funciones expl3 totalmente expandibles, saber con certeza en contextos de expansión el momento en que el resultado está ahí?

Por ejemplo, me gustaría saber la cantidad de expansiones que se deben activar para obtener el resultado de \str_tail:n.

En contextos de expansión no puede usar x-expansion ya que en sí mismo no es expandible.
No puedes usar f-expansion de forma segura ya que eso podría eliminar otro espacio inicial de la cadena.
Si la función totalmente expandible en cuestión no fuera \str_tail:nalgo en lo que los argumentos en sí mismos no fueran cadenas de tokens de caracteres explícitos no expandibles, entonces ela expansión podría desencadenar más expansión de la deseada. Además de esto, con motores donde el \expandedprimitivo no está disponible, ela expansión es costosa.

En el caso de \str_tail:nuno, se podría tener la idea de buscar en source3.pdf y descubrir que con la implementación actual se necesitan cuatro expansiones:

\cs_new:Npn \str_tail:n #1
  {
    \exp_after:wN \__str_tail_auxi:w
    \reverse_if:N \if_charcode:w
    \scan_stop: \tl_to_str:n {#1} X X \s__str_stop
  }
\cs_new:Npn \__str_tail_auxi:w #1 X #2 \s__str_stop { \fi: #1 }

La expansión 1 le proporciona el texto de reemplazo de \str_tail:n.
La expansión 2 hace \exp_after:wNlo que finaliza cuando se evalúa el resultado de la \if_charcode:wprueba y, por lo tanto, el primer token de la cadena se utiliza como argumento para comparar su código de categoría con el código de categoría de \scan_stop:.
La expansión 3 expande \__str_tail_auxi:wlo que antepone \fi:para hacer coincidir \if_charcode:wy mantiene el Xargumento delimitado por categoría-11 y elimina el \s__str_stopargumento delimitado.
La expansión 4 elimina \fi:.

Pero buscar en source3.pdf no es una forma de obtener información sobre los detalles oficiales de la implementación.

En caso de que la implementación interna cambie, la cantidad de expansiones necesarias para obtener el resultado \str_tail:ntambién podría cambiar.

No veo un método general con una función totalmente expandible para garantizar que se tenga el momento adecuado para rodear con otros tokens los tokens que forman el resultado de esa función, aparte de conocer la cantidad de expansiones después de las cuales se obtiene el resultado de la función. está ahí.
Cuando se utiliza \exp:wpara activar la expansión de una función totalmente expandible proporcionada por el entorno de programación expl3 hasta que el resultado de esa función esté ahí, no veo un método genérico para garantizar que \exp_end:se lleve a cabo en el momento adecuado para detener \exp:wla expansión, lo cual Puede prescindir de conocer la cantidad de expansiones después de las cuales el resultado de esa función está ahí.

Así que creo que con funciones totalmente ampliables, esta información debería proporcionarse como información oficial.

¿Cuántas expansiones se necesitan hasta el resultado de funciones \exp_args:...o \use_i:nnhay?
Esa información no se proporciona oficialmente en interface3.pdf.
¿Puedo confiar con seguridad, por ejemplo, en \use_i:nnrequerir siempre exactamente una expansión sin que nadie se queje porque deduzco información de detalles de implementación internos en lugar de confiar únicamente en hechos que están documentados oficialmente?
¿Qué debería hacerme confiar en la coherencia entre las versiones de expl3 en aspectos que no están documentados oficialmente?
(La distribución LaTeX que viene con mi distribución de Linux difiere mucho de TeX Live 2024...)

Respuesta1

La situación de la documentación es inherente al diseño. Hay muy pocas funciones (de bajo nivel) donde la cantidad de expansiones es importante y donde el equipo u otros han necesitado saberlo o confiar en ello: están documentadas. En otros casos, el uso de expansión de tipo e- o f- suele ser suficiente. Por ejemplo,\str_tail:n necesariamenteproduce una cadena; por lo tanto, esto es seguro en un econtexto de tipo, por lo que no hayNo hay necesidadpara documentar cuántas expansiones se requieren.

De manera más general, si una función tomadocumentotokens, entonces no puede usar ela expansión de tipo -, pero en general, manténgala \protected@edefya que funciona con comandos robustos de LaTeX2e; expl3generalmente no hace esto. Para texto completo, \text_expand:nhace algo similar \protected@edefpero no funciona bien con la expansión no textual. De cualquier manera, estos enfoques permiten la expansión de expl3funciones preservando al mismo tiempo el material frágil de LaTeX2e (por ejemplo, \textbfo similar).

Documentar la cantidad de expansiones requeridas impone una restricción a cualquier cambio de código: en la medida de lo posible, no hacemos esto; las restricciones son solo aquellas que forman parte de la API. Si tiene un caso de uso claro que parece requerir dicha estabilidad de API, registre un problema y solicite un cambio (en la documentación).

información relacionada