
Quero escrever uma macro que se expanda de maneira diferente dependendo do padrão que a segue. Especificamente, quero usá-lo para permitir uma notação mais legível para estados da mecânica quântica, por exemplo
% 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 }
Da forma como o LaTeX funciona, ele pode expandir apenas uma das definições. Se eu pulasse o último, uma possível solução seria alterar o catcode de <
, |
, >
para 11, mas isso traz seus próprios problemas (por exemplo, quebrando \ifnum .. < ..
formulários).
Existe alguma facilidade no látex, talvez através de um pacote, que permite combinar uma única macro com vários padrões de tokens subsequentes?
EsclarecimentoPorque surgiu: não quero definir comandos \bra
, ket
, etc, ou melhor, foi isso que fiz até agora. Estou tentando mudar para uma solução que resulte em um código mais legível e, embora escrever \bra <\psi_i| \Operator \ket |\psi_j>
seja um passo em direção a esse objetivo, prefiro um formulário o mais próximo possível <\psi_i|\Operator|\psi_j>
; A correspondência de padrões seria a solução mais próxima que eu poderia imaginar que poderia funcionar sem pré-processamento fora do látex.
Além disso, escrever macros complexas, que analisam o fluxo de tokens, não é algo que eu queira fazer por documento. Eu preferiria que houvesse um pacote que abstraísse essas coisas, de modo que até mesmo a definição do padrão permanecesse bem legível para evitar comportamentos inesperados. Se a correspondência de padrões fosse suportada nativamente pelo TeX \def
, o código de exemplo acima atenderia a esse requisito.
Responder1
ATUALIZARAbrace o poder de expl3
e xparse
. Eu escolho o delimitador ;
para tornar a macro possível. Para ser sincero v.2: foi bem simples e eu menti totalmente antes! Esta é a nova macro
\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
Olha que lindo!
Você pode usar a macro da seguinte maneira: \BrKt<j|\otimes<k|e^{a^\dagger/\hbar}|n>\otimes|m>;
, \BrKt|0>|1>|0>|1> = |3>_4;
ou \BrKt|m>\equiv<\Psi|A|B|\varphi>|n>;$
. Isto permite uma variedade muito maior do que a originalmente pretendida.
Postagem antiga
Para ser honesto: não acho que você não consiga alcançar perfeitamente o que deseja com pouco esforço. Seria possível, no entanto. Mas se você seguir o básico, poderá usar o poder do xparse
. Eu planejei o começo
\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
Esta estrutura de comando exige estritamente a entrada do formulário \m<input1|input2>
, porém verifica se input1
ou input2
está vazio e processa a entrada de acordo. Mas observe, isso não pode criar algo como <\Psi\Phi>
, sem o cano no meio. Observe também que nesta realização a abertura <
não é obrigatória e só produzirá um aviso se estiver faltando. Espero que você possa trabalhar com isso e seguir em frente.
Responder2
Isso é possível com o pacote de sufixo:
\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}
No entanto, há uma limitação significativa nesta abordagem, pois o mesmo "sufixo" só pode ser usado uma vez, portanto a \m<#1>
sintaxe proposta não pode ser suportada por este pacote tão bem quanto pelo \m<#1|
. Isso, sem dúvida, torna a abordagem um fracasso, mas achei que seria bom adicionar esta resposta para completar.
Responder3
Com expl3
a sintaxe proposta \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}
E com LaTeX simples e uma sintaxe um pouco diferente \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: em vez do \:
habitual é usar \;
mas me parecem grandes demais, você pode usar \nonscript\muskip5mu
ou o que quiser.
Responder4
(Revisou o código Lua depois de perceber que o OP não deseja a notação "definida" (com chaves) para itens como <a|b>
, mas, em vez disso, colchetes grandes e uma barra vertical central alta.)
Um comentário inicial: recomendo fortemente que você use um símbolo delimitador que provavelmente não ocorrerá em suas expressões do tipo freio. Dessa forma, nenhuma ambigüidade pode surgir sobre quando essas expressões começam e quando terminam. No código abaixo, utilizo &
como este símbolo; sinta-se à vontade para mudar para um diferente.
Eu preferiria um formulário o mais próximo possível de
<\psi_i|\Operator|\psi_j>
Com a convenção de notação que estou propondo, você escreveria & <\psi_i|\Operator|\psi_j> &
.
Aqui está uma solução baseada em LuaLaTeX. A função Lua brkt
está configurada para varrer cada linha de entrada e realizar correspondência sequencial de padrões. Os padrões para os quais há correspondência são convertidos em instruções que usam as macros do braket
pacote -- \Braket
, \Bra
, e \Ket
. A digitalização e a substituição acontecem numa fase muito inicial do processamento, ou seja,antesOs “olhos” e “boca” do TeX começam seu trabalho.
Duas macros do lado do TeX também são fornecidas: \braketON
para iniciar o processamento e \braketOFF
caso você precise interromper o processamento em algum ponto do documento.
% !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}