Saltar al contenido

Comprensión de los delimitadores / terminadores implícitos

Anduvimos buscando en internet y de este modo mostrarte la solución a tu duda, si tienes alguna duda puedes dejar la duda y te contestamos porque estamos para servirte.

Solución:

Te hice una versión expandible de rnumexpr que no requiere un delimitador y se detendrá en el primer no expandible, numexpr-simbolo no valido. Eso intentos emular el comportamiento de numexpr hasta cierto punto e ignore los pares de llaves.

La cosa sobre numexpr, lo que ya todos comentaron, es que es un primitivo, por lo que sus reglas son diferentes a las reglas que gobiernan los reinos de los hombres que tratan con macros simples. Desafortunadamente, algunas cosas simplemente no se pueden hacer sin un apoyo primitivo.

Desea capacidad de expansión, por lo que, de inmediato, no puede tener anticipación (con futurelet). futurelet le permitiría mirar el siguiente token y decidir qué hacer con él. La capacidad de expansión te restringe a tomar tokens como argumentos y pasarlos de maneras divertidas, y tomar cosas como argumento (con un comando abierto como rnumexpr) significa que:

  1. rnumexpr 1+1 es imposible porque TeX te gritará cuando agarre }
  2. rnumexpr 1+1 ⟨something else⟩ eventualmente agarrará ⟨something else⟩, sea lo que sea, determine si tiene que expandirse o no, y trátelo en consecuencia.

Con un argumento delimitado, podría usar algo como expl3‘s __tl_act:NNNnn para recorrer de forma expansible una lista de tokens y actuar sobre un elemento de manera diferente, dependiendo de si se trata de un espacio, una lista de tokens agrupada u otro token único, lo que facilitaría mucho la tarea en cuestión.


Primero déjame señalar algunas cosas sobre tu código. En tu prueba de vacuidad expandafterifxrelax#2relax, los expandafter salta ifx y se expande relax, por lo que no es de mucha utilidad y se puede quitar. Además, esta prueba puede imprimir caracteres no deseados si la entrada contiene un relax. Por supuesto que estás en medio de una numexpr, por lo que esto es simplemente quisquilloso.

Además, su condicional no termina en cada iteración de @rnumexpr, pero solo al final del numexpr. Esto, para expresiones grandes (y con grandes me refiero a suficientes copias de +1 para obtener un resultado superior a 1500–muy large) utilizan toda la pila de entrada de TeX. Y finalmente, tu definición no funciona para rnumexpr+1+1+1rrelax y otras combinaciones de llaves (demasiado extrañas para ser consideradas como entrada normal).


Definí una emulación lenta, ciertamente subóptima, probablemente demasiado complicada, probablemente con errores, ⟨insertar-other-qualifiers-here⟩, de numexpr. En general, el comportamiento es el mismo (en la medida de las pruebas que hice), excepto que ignora las llaves.

Comienza a escanear la entrada, token por token, y luego decide qué hacer con cada uno. Intenta expandir los tokens a medida que avanza y se detiene en el primer no expandible, numexpr-simbolo no valido. Si esa ficha es relax, se consume, como numexpr lo hace, por lo que el comportamiento es muy similar en este aspecto.

La principal diferencia es que, como toma tokens como argumentos no delimitados, los espacios se ignoran, por lo que mientras que el resultado de thenumexpr 1+1 1 es 21 (2 adjunto con un 1), el resultado de thernumexpr 1+1 1 es 12 (1+11), por lo que necesita un token de finalización “más difícil” que numexpr. Esto se puede evitar utilizando un relax: thernumexpr 1+1relax 1 para terminar el rnumexpr o usando obeyspaces para que los espacios se envíen al subyacente numexpr que luego hará lo correcto.

aquí está:

documentclassarticle

makeatletter
defrnumexprromannumeral-`0[email protected]
longdef[email protected]#1#2%
  [email protected]#2%
    %
      [email protected]@[email protected]#2%
        [email protected]#1#2%
        [email protected]#1#2%
    %
    %
      [email protected]#2%
        %
          [email protected]#2%
            [email protected]#1%
            [email protected]@after#1#2%
        %
        [email protected]#1#2%
    %

def[email protected][email protected]
def[email protected]@after#1%
  [email protected]@[email protected]expandafterrnumexpr#1[email protected][email protected]
def[email protected]@[email protected]#1#2%
  ifx#2[email protected]
    [email protected]@expandafter#1%
  else
    expandafter[email protected]@[email protected]
  fi
    #1expandafter#2%

def[email protected]@expandafter#1#2fi#3[email protected]%
  fi#1romannumeral-`0[email protected]@unexpandable
longdef[email protected]@unexpandable#1%
  expandafter[email protected]@[email protected]expandafter#1%
    romannumeral-`0#1
longdef[email protected]@[email protected]#1#2%
  ifx#1#2%
    expandafter[email protected]
  else
    expandafter[email protected]
  fi
  #1#2
longdef[email protected]#1#2#2
longdef[email protected]#1#2relax#2
longdef[email protected]#1#2%
  numexpr#1relax#2
longdef[email protected]#1%
  ifx#1relax
    expandafter@firstoftwo
  else
    expandafter@secondoftwo
  fi

def[email protected]@[email protected]#1%
  expandafter[email protected]@[email protected]@tokenexpandafternumber`#1
def[email protected]@[email protected]@token#1%
  if
    ifnum58>#1    1else xfi
    ifnum   #1>39 1else yfi
    ifnum
      ifnum#1=44 1else 0fi
      ifnum#1=46 1else 0fi
      =0
      [email protected]
    else
      [email protected]
    fi
  else
    ifnum#1=32
      [email protected]
    else
      [email protected]
    fi
  fi

def[email protected]expandafter@firstoftworomannumeral-`0
def[email protected]expandafter@secondoftworomannumeral-`0
edef[email protected]thecatcode`&
catcode`&=11
longdef[email protected]#1&%
  romannumeral-`0[email protected]@gobble#1[email protected] &
longdef[email protected]@gobble#1#2&%
  ifx[email protected]#1%
    expandafter[email protected]@[email protected]
  else
    expandafter[email protected]@tail
  fi#2
def[email protected]@[email protected] 
longdef[email protected]@tail#1[email protected] #1
longdef[email protected]#1%
  [email protected]#1%
    @secondoftwo%
    %
      ifrelaxexpandafter[email protected]detokenize#1&relax
        expandafter@firstoftwo
      else
        expandafter@secondoftwo
      fi
    %

longdef[email protected]#1%
  [email protected]#1%
    @secondoftwo%
    %
      [email protected]@[email protected]@group#1%
        @secondoftwo%
        %
          ifrelaxdetokenizeexpandafterexpandafter
              expandafter[email protected]#1&relax
            expandafter@firstoftwo
          else
            expandafter@secondoftwo
          fi
        %
    %

longdef[email protected]@[email protected]@group#1%
  ifcatexpandafter@gobbleexpandafterexpandafterstring#1?**%
    expandafter@secondoftwo
  else
    expandafter@firstoftwo
  fi


catcode`&=[email protected]
longdef[email protected]#1%
  ifrelaxdetokenize#1relax
    expandafter@firstoftwo
  else
    expandafter@secondoftwo
  fi

makeatother

begindocument

deftwop+1+1

thenumexpr 1+1 1

thernumexpr 1+1 1

thenumexprtwop+1+1+1
thenumexprtwop+1+1+1
thenumexprtwop+1+1+1
thenumexprtwop+1+1+1+1+1
thenumexprtwop+1+1+1+1+1

thenumexpr 1+1
thenumexpr 1+1twop

deftwop+1+1

thernumexprtwop+1+1+1relax
thernumexprtwop+1+1+1relax
thernumexprtwop+1+1+1relax
thernumexprtwop+1+1+1+1+1relax
thernumexprtwop+1+1+1+1+1relax

thernumexpr 1+1
thernumexpr 1+1twop

Expandable! edefzthernumexpr+1+1+1+1relaxtextttmeaningz

thernumexpr1+1+1+1+1relax

thernumexpr1+1+1relax

thenumexpr1+1+1

Groups everywhere:
thernumexpr+1+1+1+1+1+1+1+1+1+1+1,
thernumexpr+1+1+1+1+1+1+1+1+1+1+1,
thernumexpr+1+1+1,
thernumexpr+1

No leftover:
detokenizeexpandafterthernumexpr+1+1+1relax

% thernumexpr1+1+1 STILL WON'T WORK :(

enddocument

ingrese la descripción de la imagen aquí

La macro podría ser mucho más rápida si la expresión se evaluara con thenumexpr0 de antemano, en lugar de agarrar cada ficha y evaluarlas solo en el amargo final. Sin embargo, esto estropearía la “estabilidad” (si se le puede llamar así) de la macro porque en cada evaluación (tantos como grupos), un relax se consumiría, por lo que para finalizar correctamente la macro tendría que recurrir a cosas como thernumexpr1+1+1+1relaxrelaxrelaxrelax, así que opté por no participar en esta posibilidad.

La entrada para numexpr termina cuando algo (inexpugnable) que no puede aparecer en un numexpr es encontrado. Tenga en cuenta que numexpr activa la expansión hasta que la entrada termina como se definió anteriormente.

Si el token que señaló el final de la expresión entera es relax, se elimina por completo; por lo que no aparecerá si dices

edeftestthenumexpr1+1relax

que se expandiría a 2.

No se permiten llaves en expresiones enteras, a menos que se utilicen para delimitar argumentos a macros que se expanden a medida que se escanea la expresión entera. Entonces

defaddition#1#2#1+#2
numexpraddition12relax

evaluará a 3. Pero numexpr 1+1+1relax es ilegal, porque el { detiene el escaneo y el operando por primera vez + Está perdido.

Puedes usar ( y ) para delimitar subexpresiones a evaluar con las reglas de precedencia habituales: numexpr2*(1+3)relax evalúa a 8.

Sección de Reseñas y Valoraciones

Si sostienes algún reparo o capacidad de innovar nuestro ensayo te recordamos escribir una observación y con gusto lo estudiaremos.

¡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 *