I am trying to write macros for quickly formatting matrices in math mode. Here is a simple, working example:
\documentclass{article}
\usepackage{amsmath}
\newcommand{\pmat}[1]{\begin{pmatrix}#1\end{pmatrix}}
\begin{document}
\begin{displaymath}
M = \pmat{1&0\\0&1}
\end{displaymath}
\end{document}
This also works if used within an aligned environment (a table
, align
environment, cases
environment, etc.):
\documentclass{article}
\usepackage{amsmath}
\newcommand{\pmat}[1]{\begin{pmatrix}#1\end{pmatrix}}
\begin{document}
\begin{align}
M &= \pmat{1&0\\0&1}
\end{align}
\end{document}
Normally, within the align
environment the &
symbol tells LaTeX to start a new column, but since the matrix values are contained between {}
group tokens, LaTeX does not attempt to parse the 1&0\\0&1
argument and thus everything works as it was intended.
Let's create a new macro that does not use the group tokens {}
to denote the macro argument. For example, it is fairly common to use square brackets to group an argument as in this working example (try it!):
\documentclass{article}
\usepackage{amsmath}
\newcommand{\bmat}[1][]{\begin{bmatrix}#1\end{bmatrix}}
\begin{document}
\begin{displaymath}
M = \bmat[1&0\\0&1]
\end{displaymath}
\end{document}
So far, so good. Here comes the problem! If I try to use my new macro \bmat
within another aligned environment:
% DOES NOT WORK!!!
\documentclass{article}
\usepackage{amsmath}
\newcommand{\bmat}[1][]{\begin{bmatrix}#1\end{bmatrix}}
\begin{document}
\begin{align}
M &= \bmat[1&0\\0&1]
\end{align}
\end{document}
I get an error because LaTeX tries to interpret the &
within the matrix argument as part of the outer align
environment.
The difference between the way LaTeX treats the first macro \pmat{}
and the second one \bmat[]
is that the group tokens {}
prevent LaTeX from parsing the argument contained within the curly braces until after the macro \pmat
has been called. On the other hand, when LaTeX sees the \bmat[arg]
macro, the argument is not surrounded by group tokens and so LaTeX tries to parse it before getting eaten up by \bmat
. The extra &
character screws up the syntax of the align
environment and so LaTeX crashes. At least, that is my understanding of what is going on, and I could be wrong!
So, the question is whether or not it is possible to force LaTeX to treat the argument in the []
case just as it did in the {}
case (without causing additional problems). In other words, I want to be able to write a macro a-la \bmat[1&0\\0&1]
that works in aligned environments but retains the square bracket syntax.
CONCLUSION:
Here is the final macro with working []
syntax, thanks to egreg (requires xparse
and must be contained in a separate package file or between \makeatletter
and \makeatother
in preamble):
\DeclareDocumentCommand\mat{}{{\ifnum\z@=`}\fi\@mat}
\DeclareDocumentCommand\@mat{ g o d() d|| }
{
\IfNoValueTF{#1}
{
\IfNoValueTF{#2}
{
\IfNoValueTF{#3}
{
\IfNoValueTF{#4}
{()}
{\begin{vmatrix}#4\end{vmatrix}}
}
{
\begin{pmatrix}#3\end{pmatrix}
\IfNoValueTF{#4}{}{|#4|}
}
}
{
\begin{bmatrix}#2\end{bmatrix}
\IfNoValueTF{#3}{}{(#3)}
\IfNoValueTF{#4}{}{|#4|}
}
}
{
\begin{matrix}#1\end{matrix}
\IfNoValueTF{#2}{}{[#2]}
\IfNoValueTF{#3}{}{(#3)}
\IfNoValueTF{#4}{}{|#4|}
}
\ifnum\z@=`{\fi}
}
This macro works like an overloaded function with different argument delimiters {}
, []
, ()
, or ||
. There are probably many reasons why this is a terrible idea — so please, post your comments below. I would like to hear from those who know better than me.
Best Answer
You can do it, but I strongly recommend you not doing it. You gain nothing in using
[
and]
as delimiters for a mandatory argument.(Note: I have reduced the text width to shorten the output.)
When you understand the trick, you are allowed to use it. :) Hint: look for
\eegroup
in Appendix D of the TeXbook.Defining
\mat
to look for the next token in order to decide a delimiter is, in my opinion, wrong. I'd do like this:so that
would do even better, with minimum hassle and better readability.
Personally, I would stick with the long form, but it's a matter of taste.