Saltar al contenido

¿Qué hacen exactamente csname y endcsname?

Nuestros mejores programadores han agotado sus depósitos de café, buscando día y noche por la resolución, hasta que Perla halló el resultado en GitLab así que hoy la comparte contigo.

Solución:

Normalmente, los nombres de las secuencias de control se componen únicamente de letras o de uno carácter no alfabético.

Una letra es, más precisamente, un carácter que tiene el código de categoría 11 en el momento en que se lee el nombre de la secuencia de control. Por lo tanto, cualquier carácter puede convertirse en parte de un nombre de secuencia de control, siempre que cambiemos su catcode antes de la definición y cada uso.

Con csname...endcsname nos liberamos de esta limitación y cada personaje puede entrar en ellos para formar un nombre de secuencia de control (por supuesto, % se excluye porque desaparece junto con lo que queda en la línea antes de que TeX haga su trabajo en los caracteres).

Sin embargo, este no es el objetivo principal de csname...endcsname. Esta construcción se utiliza para construir comandos a partir de “partes variables”. Piense, por ejemplo, en LaTeX newcounter: después newcounterfoo, TeX sabe thefoo que se construye precisamente de esta manera. Aproximadamente, lo que hace LaTeX es

newcommandnewcounter[1]%
   expandafternewcountcsname [email protected]#1endcsname
   expandafterdefcsname the#1endcsnamearabic#1%
 

así que eso newcounterfoo hace el trabajo correcto. Es más complicado que esto, por supuesto, pero lo principal está aquí; newcount es el comando de bajo nivel para asignar un contador. los expandafter es solo construir la secuencia de control antes newcount y def ver la ficha.

Dentro csname...endcsname, los códigos de categoría no importan (con una excepción principal: caracteres activos voluntad ser expandido si no está precedido por string, ver nota final). LaTeX aprovecha esto para crear nombres de secuencia de control a los que los usuarios no podrán acceder (fácilmente). Por ejemplo, la secuencia de control para elegir la fuente de diez puntos predeterminada es OT1/cmr/m/n/10, que se puede dividir fácilmente internamente (mediante la operación “inversa” que es string) y no está disponible para el usuario ocasional.

Otro uso importante es en entornos: cuando dices newenvironmentfoo, LaTeX realmente define foo y endfoo. Al encontrar beginfoo, LaTeX hace un poco de contabilidad y luego ejecuta csname fooendcsname (por eso se puede decir también newenvironmentfoo*); de manera similar, en endfoo LaTeX se ejecuta csname endfooendcsname y después de esto vuelve a hacer un poco de contabilidad.

Otros usos: labelfoo definirá secuencias de control basadas en foo vía csname...endcsname que puede ser utilizado por ref.

Cuando uno dice csname fooendcsname, LaTeX buscará si foo se define; si no, se ejecutará relax y a partir de entonces (respetando la agrupación), foo será interpretado como relax. Un uso interesante de esta función es que se puede decir

chapter*Introduction
csname phantomsectionendcsname
addcontentslinetocchapterIntroduction

y mantener hyperref feliz si está cargado, sin hacer nada si el paquete no está cargado.

Es posible darle muchos otros usos interesantes a este truco. Pero siempre hay que tener en cuenta que TeX no expansión completa de lo que encuentra en ese contexto y que solo personajes debe permanecer. Entonces

csname abcrelax defendcsname

está prohibido. Pero después defxyzabc,

csname xyz defendcsname

será legal y equivalente a decir csname abcdefendcsname o abcdef.

Nota final

Es mejor agregar algo sobre los códigos de categoría. Un personaje activo en csname...endcsname se expandirá, por lo que para obtener un literal ~ uno tiene que escribir string~. Los caracteres de comentario (categoría 14), ignorados (categoría 9) e inválidos (categoría 15) seguirán siendo tales. Entonces

csname %endcsname

dará un error (Falta endcsname); en csname ^^@endcsname Habrá no personaje y csname ^^?endcsname generará un error.

Como referencia, del Libro TeX (con ligeros cambios de formato), Capítulo 7: Cómo lee TeX lo que escribe (pág.40):

… puedes pasar de una lista de tokens de caracteres a una secuencia de control diciendo csnameendcsname. Los tokens que aparecen en esta construcción entre csname y endcsname puede incluir otras secuencias de control, siempre que esas secuencias de control finalmente se expandan en caracteres en lugar de primitivas TeX; los caracteres finales pueden ser de cualquier categoría, no necesariamente letras. Por ejemplo, csname
TeXendcsname
es esencialmente lo mismo que TeX; pero
csnameTeXendcsname es ilegal, porque TeX se expande en tokens que contienen el kern primitivo. Es más,
csnamestringTeXendcsname producirá la secuencia de control inusual \TeX, es decir, la ficha , que normalmente no se puede escribir.

He usado esto indirectamente usando el labelref sistema y definición de etiquetas basadas en contadores:

newcountermycount
%...
newcommandmycmd%
  stepcountermycount%
  labelabcthemycount%
  %...

Esto crea una “etiqueta sucesiva abc1, abc2, … por cada llamada a mycmd, para evitar crear etiquetas definidas de forma múltiple con el mismo nombre. Indirectamente, labelabcthemycount llamadas @namedef[email protected]themycount, que llama

expandafterdefcsname [email protected]themycountendcsname

expandiendo así [email protected]themycount para [email protected] y definiendo [email protected] para la primera etiqueta, [email protected] para la segunda etiqueta, etc. Sí, las etiquetas en LaTeX son en realidad secuencias de control precedidas por [email protected] y se construye usando csname ... endcsname que luego permite numerales.

Suponga que quiere definir un comando foo2. No puede hacer esto porque 2 no es una letra. Sin embargo, esta construcción funciona: csname foo2endcsname. A veces esto es útil, por ejemplo, cuando necesita una serie de comandos, foo1, foo2, etc. (otra forma es usar números romanos). Otro ejemplo, suponga que desea definir una serie de comandos como endsection, endsubsection, etc. Entonces puedes usar un bucle con expandafterdefcsname end#1endcsname...

valoraciones y comentarios

Si te ha resultado de ayuda nuestro post, sería de mucha ayuda si lo compartieras con otros entusiastas de la programación de este modo contrubuyes a extender nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *