Makro: Je nach Muster unterschiedlich expandieren?

Makro: Je nach Muster unterschiedlich expandieren?

Ich möchte ein Makro schreiben, das je nach folgendem Muster unterschiedlich expandiert. Insbesondere möchte ich es verwenden, um eine besser lesbare Notation für quantenmechanische Zustände zu ermöglichen, z. B.

% Non-working example
\def \m<#1|    { \left\langle #1 \right|}
\def \m|#1>    { \left|       #1 \right\rangle }
\def \m<#1>    { \left\langle #1 \right\rangle }
\def \m<#1|#2> { \left\langle #1 \middle| #2 \right\rangle }

<So wie LaTeX funktioniert, kann es nur eine der Definitionen erweitern. Wenn ich die letzte übersprungen habe, wäre eine mögliche Lösung, den Catcode von , |, in 11 zu ändern >, aber das bringt seine eigenen Probleme mit sich (z. B. durch das Unterbrechen von \ifnum .. < ..Formularen).

Gibt es in Latex eine Funktion, möglicherweise über ein Paket, die es ermöglicht, ein einzelnes Makro mehreren Mustern nachfolgender Token zuzuordnen?

KlärungWeil es herauskam: Ich möchte keine Befehle \bra, ket, usw. definieren, oder vielmehr ist das, was ich bisher getan habe. Ich versuche, zu einer Lösung zu gelangen, die zu besser lesbarem Code führt, und obwohl das Schreiben \bra <\psi_i| \Operator \ket |\psi_j>ein Schritt in Richtung dieses Ziels wäre, würde ich eine Form bevorzugen, die so nah wie möglich an herankommt <\psi_i|\Operator|\psi_j>; Mustervergleich wäre die beste Lösung, die mir einfällt und die ohne Vorverarbeitung außerhalb von Latex funktionieren könnte.

Außerdem möchte ich nicht auf Dokumentebene komplexe Makros schreiben, die den Token-Stream analysieren. Mir wäre es lieber, wenn es ein Paket gäbe, das solche Dinge abstrahiert, sodass sogar die Definition des Musters gut lesbar bleibt, um unerwartetes Verhalten zu vermeiden. Wenn TeX \defMustervergleiche nativ unterstützt, würde der obige Beispielcode diese Anforderung erfüllen.

Antwort1

AKTUALISIERENNutzen Sie die Kraft von expl3und xparse. Ich habe das Trennzeichen gewählt, ;um das Makro zu ermöglichen. Um ehrlich zu sein, v.2: Es war ziemlich einfach und ich habe vorhin total gelogen! Dies ist das neue Makro

\ExplSyntaxOn
\tl_new:N \kdb_temp
\DeclareDocumentCommand{\BrKt}{u;}%
{
    \left.
    \tl_set:Nn \kdb_temp {#1}
    \tl_replace_all:Nnn \kdb_temp{<}{\middle\langle}
    \tl_replace_all:Nnn \kdb_temp{|}{\middle|}
    \tl_replace_all:Nnn \kdb_temp{>}{\middle\rangle}
    \tl_use:N \kdb_temp
    \right.
}
\ExplSyntaxOff

Schau, wie schön es ist!

Bildbeschreibung hier eingeben

Sie können das Makro wie folgt verwenden: \BrKt<j|\otimes<k|e^{a^\dagger/\hbar}|n>\otimes|m>;, \BrKt|0>|1>|0>|1> = |3>_4;oder \BrKt|m>\equiv<\Psi|A|B|\varphi>|n>;$. Dies ermöglicht eine viel größere Vielfalt als ursprünglich vorgesehen.


Alter Beitrag Ehrlich gesagt: Ich glaube nicht, dass man mit wenig Aufwand nicht genau das erreichen kann, was man will. Es wäre aber möglich. Aber wenn man sich an die Grundlagen hält, kann man die Kraft von nutzen xparse. Ich habe den Anfang ausgearbeitet

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareDocumentCommand{\m}{t< u{|} u>}%
{
    \IfBooleanTF{#1}{}{\GenericWarning{}{Watch out! A missing "<" encountered!}}
    \if\relax\detokenize{#2}\relax
        \if\relax\detokenize{#3}\relax
%           \langle\rangle
        \else
            \left| #3\right\rangle
        \fi
    \else
        \if\relax\detokenize{#3}\relax
            \left\langle #2\right|
        \else
            \left\langle #2 \middle| #3\right\rangle
        \fi
    \fi
}
\ExplSyntaxOff

Diese Befehlsstruktur verlangt strikt eine Eingabe in der Form \m<input1|input2>, prüft jedoch, ob input1oder input2leer ist und verarbeitet die Eingabe entsprechend. Beachten Sie jedoch, dass dies nichts wie erzeugen kann <\Psi\Phi>, ohne das Pipe-Zeichen in der Mitte. Beachten Sie auch, dass in dieser Realisierung die Öffnung <nicht obligatorisch ist und nur dann eine Warnung erzeugt, wenn sie fehlt. Ich hoffe, Sie können damit arbeiten und weitermachen.

Antwort2

Dies ist mit dem Suffixpaket in gewisser Weise möglich:

\documentclass{article}
\usepackage{suffix}
\begin{document}
\WithSuffix\def\m<#1|{\left\langle #1 \right|}
\WithSuffix\def\m|#1>{\left|       #1 \right\rangle}
\[ \m<x| \quad \m|y>  \]
\end{document}

Dieser Ansatz hat jedoch eine erhebliche Einschränkung, da dasselbe „Suffix“ nur einmal verwendet werden kann, sodass Ihre vorgeschlagene \m<#1>Syntax von diesem Paket nicht so gut unterstützt wird wie \m<#1|. Dies macht den Ansatz zweifellos zum Scheitern verurteilt, aber ich dachte, es wäre gut, diese Antwort der Vollständigkeit halber hinzuzufügen.

Antwort3

Mit expl3der vorgeschlagenen Syntax \m{<x|y>}.

\documentclass{article}

\usepackage{mathtools,xparse}
\usepackage{mleftright}

\ExplSyntaxOn
\NewDocumentCommand \m { m } { \kdb_m:n {\begm#1\endm} }
\cs_new_protected:Npn \kdb_m:n #1
 {
  \group_begin:
   \tl_set:Nn \l_tmpa_tl {#1}
   \tl_replace_once:Nnn \l_tmpa_tl { \begm< } { \mleft\langle  }
   \tl_replace_once:Nnn \l_tmpa_tl { \begm| } { \mleft\lvert   }
   \tl_replace_once:Nnn \l_tmpa_tl { >\endm } { \mright\rangle }
   \tl_replace_once:Nnn \l_tmpa_tl { |\endm } { \mright\rvert  }
   \tl_replace_all:Nnn \l_tmpa_tl { | } { \:\middle\vert\: }
   \tl_use:N \l_tmpa_tl
  \group_end:
 }
\ExplSyntaxOff

\begin{document}

\[
  \m{<x>} \quad \m{<x|} \quad \m{|x>} \quad \m{<x|y|z>} \quad \m{<x^{2^{2^{2^{2^{2^2}}}}}|y>}
\]

\end{document}

Und mit einfachem LaTeX und etwas anderer Syntax \m<x|>.

\documentclass{article}

\usepackage{mathtools}
\usepackage{mleftright}

\makeatletter
\def\activevert{\@ifnextchar\mlast{\mright\rvert\@gobble}{\:\middle\vert\:}}
{\catcode`\|=\active\gdef|{\activevert}}
\gdef\m<#1>{\begingroup\mathcode`\|="8000
   \@ifnextchar|{\mleft\lvert\@gobble}{\mleft\langle}#1\mlast\endgroup}
\def\mlast{\mright\rangle}
\makeatother

\begin{document}

\[
  \m<x> \quad \m<x|> \quad \m<|x> \quad \m<x|y|z> \quad \m<x^{2^{2^{2^{2^{2^2}}}}}|y>
\]

\end{document}

Bildbeschreibung hier eingeben

PS: Anstatt \:das Übliche zu verwenden \;, aber es sieht mir zu groß aus, können Sie \nonscript\muskip5mustattdessen oder was auch immer Sie möchten verwenden.

Antwort4

(Lua-Code überarbeitet, nachdem mir aufgefallen war, dass der OP für Elemente wie „.. keine „Set“-Notation (mit geschweiften Klammern) <a|b>, sondern stattdessen große spitze Klammern und einen hohen vertikalen Strich in der Mitte wünscht.)

Ein Kommentar vorweg: Ich empfehle dringend, dass Sie ein Trennzeichen verwenden, das in Ihren Klammern-ähnlichen Ausdrücken wahrscheinlich nicht vorkommt. Auf diese Weise kann keine Unklarheit darüber entstehen, wann diese Ausdrücke beginnen und wann sie enden. Im folgenden Code verwende ich &dieses Symbol; Sie können es gerne durch ein anderes ersetzen.

Ich bevorzuge eine Form, die so nah wie möglich an<\psi_i|\Operator|\psi_j>

Mit der von mir vorgeschlagenen Notation würden Sie schreiben & <\psi_i|\Operator|\psi_j> &.

Hier ist eine LuaLaTeX-basierte Lösung. Die Lua-Funktion brktist so eingestellt, dass sie jede Eingabezeile scannt und sequentielle Mustervergleiche durchführt. Muster, für die es eine Übereinstimmung gibt, werden in Anweisungen umgewandelt, die die Makros des braketPakets verwenden -- \Braket, \Bra, und \Ket. Das Scannen und Ersetzen erfolgt in einem sehr frühen Stadium der Verarbeitung, d. h.VorDie „Augen“ und der „Mund“ von TeX beginnen ihre Arbeit.

Es werden außerdem zwei TeX-seitige Makros bereitgestellt: \braketONzum Starten der Verarbeitung und \braketOFFfür den Fall, dass Sie die Verarbeitung an einer bestimmten Stelle im Dokument stoppen müssen.

Bildbeschreibung hier eingeben

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode,braket,mathtools,mleftright}
\DeclarePairedDelimiter\abs\lvert\rvert % just for this example

%% Lua-side code
\begin{luacode}
function brkt ( buff )
  buff = string.gsub ( buff, "&[%s]-<([^&]-)|([^&]-)|([^&]-)>[%s]-&", "\\Braket{%1|%2|%3}" )
  buff = string.gsub ( buff, "&[%s]-<([^&]-)|([^&]-)>[%s]-&" , "\\mleft\\langle %1\\;\\middle|\\; %2\\mright\\rangle" )
  buff = string.gsub ( buff, "&[%s]-<([^&]-)>[%s]-&", "\\mleft\\langle %1\\mright\\rangle " )
  buff = string.gsub ( buff, "&[%s]-<([^&]-)%|[%s]-&", "\\Bra{%1}" )
  buff = string.gsub ( buff, "&[%s]-|([^&]-)>[%s]-&", "\\Ket{%1}" )  
  return buff
end
\end{luacode}

%% TeX-side code
\newcommand\braketON{\directlua{%
  luatexbase.add_to_callback ( "process_input_buffer", brkt, "brkt" )}}
\newcommand\braketOFF{\directlua{%
  luatexbase.remove_from_callback ( "process_input_buffer", "brkt" )}}

\begin{document}
\braketON

$
&< \phi | \frac{\partial^2}{\partial t^2} | \psi > &, \quad
&   <x\in\mathbf{R}^2 | 0<\abs*{\frac{x}{2}}<5 > & , \quad
& <\frac{a}{b},\frac{c}{d}> &$

\medskip
$ \displaystyle
&  < \phi | \frac{\partial^2}{\partial t^2} | \psi > &, \quad
&<x\in\mathbf{R}^2 | 0<\abs*{\frac{x}{2}}<5 >&,
\quad
& <\frac{a}{b},\frac{c}{d}> &$

\medskip
$ &<A|&, &<B|&, &|C>&,  &<D|& $

\bigskip
$ & <x^{2^{2^{2^{2^{2^2}}}}}|y> &$ % with a nod to @Manuel's code :-)
\end{document}

verwandte Informationen