¿Qué le pasa a mi macro de freno?

¿Qué le pasa a mi macro de freno?

Basado en la solución alternativa de egreg para miPregunta anteriorde donde aprendí la idea de convertir caracteres en macros, ahora he definido una sintaxis diferente para brackets que en realidad me gusta aún más. mi macrocasifunciona (aunque hay un poco de programación de culto a la carga aquí porque copié una parte de su solución que no entendí completamente (las dos líneas que comienzan con \begingroup\lccode) en mi macro y las adapté ligeramente; sospecho que el problema es ahí, porque el resto creo que lo entiendo suficientemente, gracias a las explicaciones de egregs a la otra pregunta).

Aquí está mi definición de macro:

\newcommand{\braket}[2][\middle]{\ensuremath{
\begingroup
\begingroup\lccode`~=`<
  \lowercase{\endgroup\def~}{#1\langle}
\begingroup\lccode`~=`|
  \lowercase{\endgroup\def~}{#1\pipedel}
\begingroup\lccode`~=`>
  \lowercase{\endgroup\def~}{#1\rangle}
\edef\pipedel{\delimiter\the\delcode`|}
\mathchardef\lt\mathcode`<
\mathchardef\pipechar\mathcode`|
\mathchardef\gt\mathcode`>
\mathcode`\<=\string"8000
\mathcode`\|=\string"8000
\mathcode`\>=\string"8000
\left.
#2
\right.
\endgroup
}}

Todos los siguientes usos funcionan como se esperaba:

\braket{<\psi|\psi>}
\braket{<\psi|A|\psi>}
\braket{<\psi|\frac{p^2}{2m}|\psi>}
\braket[\Big]{<\alpha|\beta>}
\braket{|a \gt 0>}
\braket[]{<\psi|\frac{p^2}{2m}|\phi>}

(el último simplemente desactiva la adaptación automática de tamaño).

Sin embargo, lo siguiente hacenofuncionar correctamente:

\braket{<0|1>}

Debería dar "〈0|1〉" pero sólo da "〈0〉".

Entonces, ¿qué le pasa a mi macro y cómo lo soluciono?

Respuesta1

El problema es que cuando TeX encuentra la tubería activa, la expande a

\delimiter 2532108

y un número a continuación se incorporará a dicho código.

\mathchardef\lt\mathcode`<
\mathchardef\pipechar\mathcode`|
\mathchardef\gt\mathcode`>
\edef\pipedel{\delimiter\the\delcode`| }
\show\pipedel
\newcommand{\braket}[2][\middle]{
  \begingroup
  \begingroup\lccode`~=`<
    \lowercase{\endgroup\def~}{#1\langle}
  \begingroup\lccode`~=`|
    \lowercase{\endgroup\def~}{#1\pipedel\relax}
  \begingroup\lccode`~=`>
     \lowercase{\endgroup\def~}{#1\rangle}
  \mathcode`\<=\string"8000
  \mathcode`\|=\string"8000
  \mathcode`\>=\string"8000
  \mathopen{}\left.#2\right.\mathclose{}
  \endgroup
}

Evitarán \relaxel problema. Además, algunas partes son mejores fuera de la definición y \ensuremathno son recomendables.

Nota sobre el \lowercasetruco

Cuando a un carácter (del código de categoría 11 o 12) se le asigna un código matemático "8000y se encuentra en modo matemático, TeX lo trata como si estuviera activo (es decir, como una macro) y se necesita una definición del mismo como carácter activo. .

Un truco muy utilizado es explotar eso.~ esactivo; Cuando queremos darle un significado a lo activo <, existen dos estrategias. El primero es

{\catcode`<=\active \gdef<{something}}

lo cual tiene algún inconveniente: nos vemos obligados a ejecutarlo con antelación y esglobal. Entonces usamos una estrategia diferente:

\begingroup\lccode`~=`< \lowercase{\endgroup\def~}{something}

¿Cómo funciona esto? En primer lugar, abrimos un grupo y en el grupo le decimos a TeX que la contraparte en minúscula ~es <. Entonces lo hacemos \lowercase, lo que se transformafichas de personajeen su contraparte minúscula (pero dejando las secuencias de control inalteradas) y devuelve las fichas como si estuvieran allí desde el principio. Entonces TeX ve

\endgroup\def<{something}

(pero< esactivo, ya que \lowercaseno cambia los códigos de categoría). Se \endgroupdeshace la correspondencia entre ~y <y se realiza la definición. Cuando, más tarde, digamos \mathcode`<=\string"8000, la magia sucederá ( \stringes una precaución contraBabelque podría haberse convertido "en un personaje activo).

información relacionada