
Com base na solução alternativa do egreg para o meupergunta anteriorcom o qual aprendi a ideia de transformar caracteres em macros, agora defini uma sintaxe diferente para colchetes, da qual gosto ainda mais. Minha macroquasefunciona (embora haja um pouco de programação de culto à carga acontecendo aqui porque copiei uma parte de sua solução que não entendi completamente - as duas linhas que começam com \begingroup\lccode
- em minha macro e as adaptei ligeiramente; suspeito que o problema seja aí, porque o resto creio ter compreendido suficientemente, graças às explicações da egregs para a outra questão).
Aqui está minha definição 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 os usos a seguir funcionam conforme o esperado:
\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>}
(o último simplesmente desativa a adaptação automática de tamanho).
No entanto, o seguinte faznãofuncionar corretamente:
\braket{<0|1>}
Deveria dar "〈0|1〉" mas só dá "〈0〉".
Então, o que há de errado com minha macro e como posso corrigir isso?
Responder1
O problema é que quando o TeX encontra o pipe ativo, ele o expande para
\delimiter 2532108
e um número seguinte será incorporado a esse 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
}
Isso \relax
evitará o problema. Além disso, algumas partes são melhores fora da definição e \ensuremath
não são recomendáveis.
Nota sobre o \lowercase
truque
Quando um caractere (de código de categoria 11 ou 12) recebe código matemático "8000
e é encontrado no modo matemático, ele é tratado pelo TeX como se estivesse ativo (ou seja, como uma macro) e é necessária uma definição dele como um caractere ativo. .
Um truque muito comumente usado é explorar isso~
éativo; quando queremos dar um significado ao ativo <
, existem duas estratégias. O primeiro é
{\catcode`<=\active \gdef<{something}}
que tem alguma desvantagem: somos obrigados a executá-lo antecipadamente e églobal. Então usamos uma estratégia diferente:
\begingroup\lccode`~=`< \lowercase{\endgroup\def~}{something}
Como é que isso funciona? Primeiro de tudo, abrimos um grupo e no grupo dizemos ao TeX que a contraparte minúscula de ~
é <
. Então fazemos \lowercase
, o que transformafichas de personagemem sua contraparte minúscula (mas deixando as sequências de controle inalteradas) e coloca de volta os tokens como se estivessem lá desde o início. Então o TeX vê
\endgroup\def<{something}
(mas<
éativo, pois \lowercase
não altera códigos de categoria). O \endgroup
desfaz a correspondência entre ~
e <
e a definição é executada. Quando, mais tarde, dissermos \mathcode`<=\string"8000
, a mágica vai acontecer ( \string
é uma precaução contrababelque poderia ter se tornado "
um personagem ativo).