5

I'd like to typeset ordered pairs with comma-separated components while \langle and \rangle as their delimiters. I want line breaks at commas for an ordered pair in inline math mode.

So I came up with the following piece of code, however, there is an annoying bug in it.

\documentclass{article}

%\usepackage{amsmath,physics}

\def\opair#1{% \mathopen\langle \kern 2pt \begingroup \edef@tempa{#1,}% \expandafter \endgroup \expandafter\opairImpl@tempa\relax \kern 2pt \mathclose\rangle } \def\opairImpl#1,#2\relax{% {#1}% \begingroup \ifx\relax#2\relax \def\next{ \endgroup }% \else \def\next{ \endgroup ,,\allowbreak \opairImpl#2\relax } \fi \next }

\begin{document} ( \opair{x , y, z} ) ( \opair{ \cos\alpha, \cos\beta, \cos\gamma } )

( \opair{x_1,x_2,\cdots{},x_n} )

(\opair{a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z}) \end{document}

When \usepackage{amsmath,physics} is disabled, \( \opair{x_1,x_2,\cdots{},x_n} \) yields terrible output, where the comma behind x_2 went missing, as is shown in the screenshot below.

Missing Comma

When \usepackage{amsmath,physics} is enabled, an even more annoying bug emerged. The log file is shown below.

This is XeTeX, Version 3.14159265-2.6-0.999992 (TeX Live 2020/W32TeX) (preloaded format=xelatex 2021.3.15)  11 APR 2021 22:34
entering extended mode
 restricted \write18 enabled.
 %&-line parsing enabled.
**tmp.tex
(./tmp.tex
LaTeX2e <2020-02-02> patch level 5
L3 programming layer <2020-03-06>
(~/texlive/2020/texmf-dist/tex/latex/base/article.cls
Document Class: article 2019/12/20 v1.4l Standard LaTeX document class
(~/texlive/2020/texmf-dist/tex/latex/base/size10.clo
File: size10.clo 2019/12/20 v1.4l Standard LaTeX file (size option)
)
\c@part=\count163
\c@section=\count164
\c@subsection=\count165
\c@subsubsection=\count166
\c@paragraph=\count167
\c@subparagraph=\count168
\c@figure=\count169
\c@table=\count170
\abovecaptionskip=\skip47
\belowcaptionskip=\skip48
\bibindent=\dimen134
)
(~/texlive/2020/texmf-dist/tex/latex/amsmath/amsmath.sty
Package: amsmath 2020/01/20 v2.17e AMS math features
\@mathmargin=\skip49

For additional information on amsmath, use the `?' option. (~/texlive/2020/texmf-dist/tex/latex/amsmath/amstext.sty Package: amstext 2000/06/29 v2.01 AMS text

(~/texlive/2020/texmf-dist/tex/latex/amsmath/amsgen.sty File: amsgen.sty 1999/11/30 v2.0 generic functions @emptytoks=\toks15 \ex@=\dimen135 )) (~/texlive/2020/texmf-dist/tex/latex/amsmath/amsbsy.sty Package: amsbsy 1999/11/29 v1.2d Bold Symbols \pmbraise@=\dimen136 ) (~/texlive/2020/texmf-dist/tex/latex/amsmath/amsopn.sty Package: amsopn 2016/03/08 v2.02 operator names ) \inf@bad=\count171 LaTeX Info: Redefining \frac on input line 227. \uproot@=\count172 \leftroot@=\count173 LaTeX Info: Redefining \overline on input line 389. \classnum@=\count174 \DOTSCASE@=\count175 LaTeX Info: Redefining \ldots on input line 486. LaTeX Info: Redefining \dots on input line 489. LaTeX Info: Redefining \cdots on input line 610. \Mathstrutbox@=\box45 \strutbox@=\box46 \big@size=\dimen137 LaTeX Font Info: Redeclaring font encoding OML on input line 733. LaTeX Font Info: Redeclaring font encoding OMS on input line 734. \macc@depth=\count176 \c@MaxMatrixCols=\count177 \dotsspace@=\muskip16 \c@parentequation=\count178 \dspbrk@lvl=\count179 \tag@help=\toks16 \row@=\count180 \column@=\count181 \maxfields@=\count182 \andhelp@=\toks17 \eqnshift@=\dimen138 \alignsep@=\dimen139 \tagshift@=\dimen140 \tagwidth@=\dimen141 \totwidth@=\dimen142 \lineht@=\dimen143 @envbody=\toks18 \multlinegap=\skip50 \multlinetaggap=\skip51 \mathdisplay@stack=\toks19 LaTeX Info: Redefining [ on input line 2859. LaTeX Info: Redefining ] on input line 2860. ) (~/texlive/2020/texmf-dist/tex/latex/physics/physics.sty Package: physics

(~/texlive/2020/texmf-dist/tex/latex/l3packages/xparse/xparse.sty (~/texlive/2020/texmf-dist/tex/latex/l3kernel/expl3.sty Package: expl3 2020-03-06 L3 programming layer (loader)

(~/texlive/2020/texmf-dist/tex/latex/l3backend/l3backend-xdvipdfmx.def File: l3backend-xdvipdfmx.def 2020-03-12 L3 backend support: xdvipdfmx \g__graphics_track_int=\count183 \l__pdf_internal_box=\box47 \g__pdf_backend_object_int=\count184 \g__pdf_backend_annotation_int=\count185 )) Package: xparse 2020-03-06 L3 Experimental document command parser \l__xparse_current_arg_int=\count186 \g__xparse_grabber_int=\count187 \l__xparse_m_args_int=\count188 \l__xparse_v_nesting_int=\count189 )) No file tmp.aux. \openout1 = `tmp.aux'.

LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 31. LaTeX Font Info: Trying to load font information for TS1+cmr on input line 3

(~/texlive/2020/texmf-dist/tex/latex/base/ts1cmr.fd File: ts1cmr.fd 2019/12/16 v2.5j Standard LaTeX font definitions ) LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for TU/lmr/m/n on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 31. LaTeX Font Info: ... okay on input line 31. LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 31. LaTeX Font Info: ... okay on input line 31.

! Undefined control sequence. \DN@ ->\def \next@

l.32 ( \opair{x_1,x_2,\cdots{},x_n} ) Here is how much of TeX's memory you used: 1999 strings out of 479418 31789 string characters out of 5884585 281504 words of memory out of 5000000 19574 multiletter control sequences out of 15000+600000 532800 words of font info for 27 fonts, out of 8000000 for 9000 1348 hyphenation exceptions out of 8191 44i,3n,40p,309b,52s stack positions out of 5000i,500n,10000p,200000b,80000s

No pages of output.

I noticed that \( \opair{x_1,x_2, \cdots{},x_n} \) ensures the comma before \cdots{} show up correctly, in contrast to \( \opair{x_1,x_2,\cdots{},x_n} \); but I don't know why so.

What should I do then? Plz help and thx in advance.


EDIT:

Expected output:

Expected output IMAGE

Expected behavior:

Bug-free when using together with packages like amsmath and physics.


EDIT 1:

After taking @egrep 's approach, the following snipet yields Undefined control sequence error:

\begin{align*}
\mat{T}
&=\opair{
\eval{\jacobi{F,G}{y,z}}_M,
\eval{\jacobi{F,G}{z,x}}_M,
\eval{\jacobi{F,G}{x,y}}_M
} \\
&=\opair{
\begin{vmatrix}
F_y & F_z \\
G_y & G_z \\
\end{vmatrix}_{M},
\begin{vmatrix}
F_z & F_x \\
G_z & G_x \\
\end{vmatrix}_{M},
\begin{vmatrix}
F_x & F_y \\
G_x & G_y \\
\end{vmatrix}_{M}
}.
\end{align*}

Log file:

! Argument of \__clist_use:nwwwwnwn has an extra }.
<inserted text> 
                \par 
l.42 \end{align*}

?

BTW I defined \let\mat\boldsymbol and \newcommand{\jacobi}[2]{ \pdv{ (#1) }{ (#2) } }%

Expected output:

Ordered pairs with matrices as components

I think it is the fault of \jacobi, but I don't know what to do.

1 Answers1

5

The error is in \edef\@tempa{#1,} because \cdots (in the amsmath version) doesn't survive it.

There is no need for \edef and \def suffices.

Here's an alternative implementation that doesn't substantially differs from yours, except that I use mu units for the leading and trailing space and I add some small flexibility in the glue after commas to allow for justification.

Instead of reinventing the wheel to process the comma list, I use a predefined method in expl3. If you're running a version of LaTeX prior to 2020-10-01, you need \usepackage{xparse}.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn \NewDocumentCommand{\opair}{m} { \langle\mspace{4mu} \clist_set:Nn \l_tmpa_clist { #1 } \clist_use:Nn \l_tmpa_clist {,\mspace{3mu plus 1mu minus 1mu}\allowbreak} \mspace{4mu}\rangle } \ExplSyntaxOff

\begin{document} ( \opair{x , y, z} ) ( \opair{ \cos\alpha, \cos\beta, \cos\gamma } )

( \opair{x_1,x_2,\cdots,x_n} )

(\opair{a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y, z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z}) \end{document}

Don't use {} to terminate commands in math mode, because it adds possibly unwanted empty atoms.

enter image description here

A different implementation that only allows line breaks after the second item but only up to the penultimate one: you don't want that an ordered pair is broken across lines, but possibly want it for longer tuples.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\opair}{m} { \langle\mspace{4mu} \kaiserkatze_opair:n { #1 } \mspace{4mu}\rangle }

\seq_new:N \l__kaiserkatze_opair_items_seq \tl_new:N \l__kaiserkatze_opair_first_tl

\cs_new_protected:Nn \kaiserkatze_opair:n { \seq_set_from_clist:Nn \l__kaiserkatze_opair_items_seq { #1 } % set off the first item and insert it \seq_pop_left:NN \l__kaiserkatze_opair_items_seq \l__kaiserkatze_opair_first_tl \tl_use:N \l__kaiserkatze_opair_first_tl % now insert commas and allowed breaks \seq_map_indexed_inline:Nn \l__kaiserkatze_opair_items_seq { % comma and thin space ,\mspace{3mu plus 1mu minus 1mu} % but \allowbreak only after the second item and before the penultimate \int_compare:nT { 1 < ##1 < \seq_count:N \l__kaiserkatze_opair_items_seq } { \allowbreak } % the item ##2 } } \ExplSyntaxOff

\begin{document} ( \opair{x , y, z} ) ( \opair{ \cos\alpha, \cos\beta, \cos\gamma } )

( \opair{x_1,x_2,\cdots{},x_n} )

(\opair{a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y, z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z})

\parbox[t]{0pt}{ (\opair{a,b,c,d,e,f,g,h}) }

\end{document}

The \parbox is just to show where breaks are allowed.

enter image description here

egreg
  • 1,121,712