マクロ: パターンに応じて異なる展開をしますか?

マクロ: パターンに応じて異なる展開をしますか?

それに続くパターンに応じて異なる展開をするマクロを書きたい。具体的には、量子力学の状態をより読みやすい表記にするためにこれを使いたい。例えば、

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

LaTeX の仕組み上、定義の 1 つしか展開できません。最後の定義をスキップした場合、考えられる修正方法は、、の catcode を<11に変更することですが、これによって独自の問題が発生します (たとえば、フォームが壊れるなど|) 。>\ifnum .. < ..

LaTeX には、パッケージなどを通じて、単一のマクロを後続のトークンの複数のパターンに一致させることができる機能がありますか?

説明\bra次のようなことが起こったからです: コマンド、などを定義したくありませんket。というか、これまではこれでした。より読みやすいコードになるソリューションに移行しようとしていますが、 と書くことは\bra <\psi_i| \Operator \ket |\psi_j>その目標に向けた一歩ですが、 にできるだけ近い形式を好みます<\psi_i|\Operator|\psi_j>。パターン マッチングは、LaTeX の外部で前処理せずに機能する、私が考えられる最も近いソリューションです。

さらに、トークン ストリームを分析する複雑なマクロを記述することは、ドキュメント レベルでは実行したくないことです。予期しない動作を回避するために、パターンの定義さえも読みやすいままになるように、そのようなものを抽象化するパッケージがあればよいと思います。TeX が\defネイティブでパターン マッチングをサポートしている場合、上記のサンプル コードはその要件に適合します。

答え1

アップデートexpl3との力を活用しましょうxparse。マクロを可能にするために区切り文字を選択しました;。正直に言うと、v.2: 非常にシンプルで、先ほどは完全に嘘をつきました。これが新しいマクロです。

\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

なんて美しいのでしょう!

ここに画像の説明を入力してください

マクロは、\BrKt<j|\otimes<k|e^{a^\dagger/\hbar}|n>\otimes|m>;、 、\BrKt|0>|1>|0>|1> = |3>_4;のように使用できます\BrKt|m>\equiv<\Psi|A|B|\varphi>|n>;$。これにより、当初意図されていたよりもはるかに多様な使用が可能になります。


古い投稿 正直に言うと、少しの努力で望むことを完璧に達成できないとは思いません。でも、それは可能でしょう。しかし、基本に忠実であれば、の力を使うことができますxparse。私はスタートを切りました

\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

このコマンド構造は、 という形式の入力を厳密に要求します\m<input1|input2>が、 またはinput1input2空かどうかをチェックし、それに応じて入力を処理します。ただし、<\Psi\Phi>中間にパイプがないと、 のようなものを作成できないことに注意してください。また、この実現では、開始は<必須ではなく、開始がない場合は警告のみが生成されることに注意してください。これを使用して、さらに先に進んでいただければ幸いです。

答え2

これは、サフィックス パッケージを使用するとある程度可能です。

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

ただし、このアプローチには、同じ「サフィックス」を 1 回しか使用できないという重大な制限があるため、提案された\m<#1>構文は、このパッケージだけでなく でもサポートできません\m<#1|。このため、このアプローチは間違いなく非現実的ですが、完全性のためにこの回答を追加するのが良いと思いました。

答え3

expl3提案された構文では\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}

そして、プレーンな LaTeX と少し異なる構文を使用します\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}

ここに画像の説明を入力してください

\:PS:通常の代わりのものを使用するのです\;が、私には大きすぎるように見えます。\nonscript\muskip5mu代わりに、好きなものを使用することもできます。

答え4

(OP が<a|b>、 などの項目に「set」表記 (中括弧を使用) ではなく、大きな山括弧と長い中央の縦棒を使用したいと考えていることに気付き、Lua コードを修正しました。)

事前にコメントしておきますが、括弧のような式に出現する可能性が低い区切り記号を使用することを強くお勧めします。こうすることで、これらの式の開始と終了のタイミングが曖昧になることがなくなります。以下のコードでは、&この記号として を使用していますが、自由に別の記号に切り替えてください。

できるだけ近い形を希望します<\psi_i|\Operator|\psi_j>

私が提案する表記法では、 と書きます& <\psi_i|\Operator|\psi_j> &

これは LuaLaTeX ベースのソリューションです。Lua 関数は、brkt各入力行をスキャンして順次パターン マッチングを実行するように設定されています。一致するパターンは、パッケージのマクロ ( braket、、\Braketおよび\Bra)を使用する命令に変換されます\Ket。スキャンと置換は、処理の非常に早い段階で行われます。つまり、前にTeX の「目」と「口」が働き始めます。

\braketON処理を開始するためのマクロと、\braketOFFドキュメント内のある時点で処理を停止する必要がある場合のためのマクロの 2 つも TeX 側で提供されています。

ここに画像の説明を入力してください

% !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}

関連情報