Что не так с моим макросом для брэкета?

Что не так с моим макросом для брэкета?

На основе альтернативного решения egreg для моегопредыдущий вопросиз которого я почерпнул идею превращения символов в макросы, теперь я определил другой синтаксис для скобок, который мне нравится даже больше. Мой макроспочтиработает (хотя здесь есть немного программирования карго-культа, потому что я скопировал некоторую часть его решения, которую не до конца понял — две строки, начинающиеся с \begingroup\lccode— в свой макрос и немного адаптировал их; я подозреваю, что проблема именно там, потому что остальное, как мне кажется, я понимаю достаточно хорошо, благодаря объяснениям egregs к другому вопросу).

Вот мое определение макроса:

\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
}}

Все следующие варианты использования работают так, как и ожидалось:

\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>}

(последний вариант просто отключает автоматическую адаптацию размера).

Однако, следующее делаетнетработают правильно:

\braket{<0|1>}

Он должен выдать «〈0|1〉», но выдает только «〈0〉».

Так что же не так с моим макросом и как это исправить?

решение1

Проблема в том, что когда TeX находит активный канал, он расширяет его до

\delimiter 2532108

и следующий за ним номер будет включен в этот код.

\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
}

Это \relaxпозволит избежать проблемы. Также некоторые части лучше за пределами определения и \ensuremathне рекомендуются.

Примечание к \lowercaseтрюку

Когда символу (с кодом категории 11 или 12) назначен математический код "8000и он находится в математическом режиме, TeX обрабатывает его так, как если бы он был активным (то есть как макрос), и требуется его определение как активного символа.

Очень часто используемый трюк — это использовать это~ являетсяактивный; когда мы хотим придать значение активному <, есть две стратегии. Первая -

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

что имеет некоторые недостатки: мы вынуждены выполнять его заранее, и этоГлобальный. Поэтому мы используем другую стратегию:

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

Как это работает? Сначала мы открываем группу и в группе говорим TeX, что строчный аналог — ~это <. Затем мы делаем \lowercase, что преобразуетжетоны персонажейв их строчные аналоги (но оставляя управляющие последовательности неизменными) и возвращает токены, как будто они были там с самого начала. Так TeX видит

\endgroup\def<{something}

(но< являетсяактивный, так как \lowercaseне изменяет коды категорий). \endgroupОтменяет соответствие между ~и <и выполняется определение. Когда позже мы скажем \mathcode`<=\string"8000, произойдет волшебство ( \stringпредосторожность противвавилонкоторый мог бы стать "активным персонажем).

Связанный контент