# alignment mark inside box can't be seen from outside this box

I didn't really know how to write the title, hope it's clear enough (I'm willing to change it if anyone suggests anything better).

My problem is the following: I want to align different items with respect to each other, but with the anchor inside an already aligned environment (this of course fails as it isn't seen outside this environment). Typically I'm giving several definitions of functions, and I'd like to have a pleasing horizontal and vertical alignment between them: horizontal with respect to the column and vertical with respect to the base of first line. Here's a MWE:

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{amsfonts}

\newcommand*\Rset{\mathbb{R}}

\newcommand*\mapping[5]{%
\begingroup
\setlength\arraycolsep{0.2em}%
\begin{array}{ccccc}%
{#1}&\colon&{#2}&\longrightarrow&{#3}\\
&&{#4}&\longmapsto&{#5}%
\end{array}%
\endgroup
}%

\begin{document}
\begin{align*}
&\mapping f\Rset\Rset x{x^2,}&
&\mapping M\Rset\Rset x{x^{42},}\\*[2ex]
&\mapping{\mathrm{Function}}XYx{\dfrac1{1+\dfrac1{1+x^2}},}&
&\mapping U\Rset\Rset x{x.}
\end{align*}
\end{document}


So far my only option is to put the & for the align* environment in front of the \mapping command, so the horizontal alignment is from the beginning of the name of the function. How can I somehow put the & inside the array environment so that it is not seen by the array environment but by the outer align* environment?

Not mentioning the awful vertical alignment!

Maybe you'll have an altogether different (and better) method to achieve this, but anyways, I'd like to know if it is at all possible (in an easy way) or not.

-
For the vertical alignment use \begin{array}[t]{*{5}{c}}. Are you meaning that "f" should be center aligned with respect to "Function"? –  egreg Oct 2 '12 at 17:54
@egreg I would like all 4 functions to be aligned, vertically and horizontally wrt the colons. This would imply to have somehow an ampersand (for the align* environment) inside the array environment. –  gniourf_gniourf Oct 2 '12 at 17:56
What do you mean with "vertically"? –  egreg Oct 2 '12 at 17:59
@egreg Vertically: I would like Function and U to be on a same line. Horizontally: I would like the colons for f and Function to be on a same column (similarly for M and U). –  gniourf_gniourf Oct 2 '12 at 18:03
The first requirement is obtained by \begin{array}[t]{ccccc}. The second is unclear with respect to the relative position of f and Function. –  egreg Oct 2 '12 at 18:08
show 1 more comment

If I understand correctly you just want to move the & into your definition, after the first argument:

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{amsfonts}

\newcommand*\Rset{\mathbb{R}}

\newcommand*\mapping[5]{%
#1&%
\begingroup
\setlength\arraycolsep{0.2em}%
\begin{array}[t]{cccc}%
\colon&#2&\longrightarrow&#3\\
&#4&\longmapsto&#5%
\end{array}%
\endgroup
}

\begin{document}
\begin{align*}
\mapping f\Rset\Rset x{x^2,}&
\mapping M\Rset\Rset x{x^{42},}\\*[2ex]
\mapping{\mathrm{Function}}XYx{\dfrac1{1+\dfrac1{1+x^2}},}&
\mapping U\Rset\Rset x{x.}
\end{align*}
\end{document}

-
Of course this \mapping can't be used anywhere other than in an align. –  egreg Oct 2 '12 at 22:46
@egreg, yes true of course, if that is a requirement the & could be made conditional on the current environment being align –  David Carlisle Oct 2 '12 at 23:53
Thanks for your answer. Of course, this works very well in this case! And with egreg's prescription I'll have a cool \mapping macro. The horizontal spacing between the function name and the colon is though not too good but I'll adjust that. Hence I now believe that each time I have boxes to be aligned wrt an anchor inside the box, I'll have to figure out, depending on the case, how to achieve the alignment (there's no way that the & be seen by the outer environment). –  gniourf_gniourf Oct 3 '12 at 6:39
At the primitive TeX level it is correct to say that a box layer hides all the inner alignment, but it is of course possible to design a data structure that passes on the box and various measurements so alignments can be reconstructed. that is what LaTeX 3 coffins are "boxes with handles" See the documentation of the xcoffin package. However you can't simply drop xcoffin code into an existing alignment as the whole thing has to be coffin based so it passes on the handles from inner structures to outer structures. Only really the lowest level code is there so far. –  David Carlisle Oct 3 '12 at 8:22

One way to stick with the way you are doing is to add an optional first parameter to the \mapping macro which specifies the widest element that is to go before the colon and use \makebox to ensure that that element takes up the appropriate amount of space:

## Notes:

• As per egreg's comment, specifying [t] as the optional first parameter to array provides the desired vertically alignment.
• The first parameter to \mapping is optional and defaults to the first mandatory parameter if not specified. \IfStrEq from the xstring package was used to test that the first parameter is empty. If you do not wish to use an additional package, this comparison can be done without it.
• The \widthof macro is from the calc package.
• The macros \makebox and \widthof expect text parmaters hence the nede to go into math mode within the parameters to those macros.

## Code:

\documentclass{article}

\usepackage{xstring}
\usepackage{calc}
\usepackage{amsmath}
\usepackage{amsfonts}

\newcommand*\Rset{\mathbb{R}}

\newcommand*{\WidestElement}{}%
\newcommand*\mapping[6][]{%
\begingroup
\setlength\arraycolsep{0.2em}%
\IfStrEq{#1}{}{%
\def\WidestElement{#2}% default \WidestElement to same as #2
}{%
\def\WidestElement{#1}% \WidestElement was specified
}%
\begin{array}[t]{ccccc}%
\makebox[\widthof{$\WidestElement$}][r]{$#2$}&\colon&{#3}&\longrightarrow&{#4}\\
&&{#5}&\longmapsto&{#6}%
\end{array}%
\endgroup
}%

\begin{document}
\begin{align*}
&\mapping[\mathrm{Function}]{f}{\Rset}{\Rset}{x}{x^2,}&
&\mapping{M}{\Rset}{\Rset}{x}{x^{42},}\\*[2ex]
&\mapping{\mathrm{Function}}{X}{Y}{x}{\dfrac1{1+\dfrac1{1+x^2}},}&
&\mapping{U}{\Rset}{\Rset}{x}{x.}
\end{align*}
\end{document}

-
Thanks for your answer! I was thinking of a solution that would be similar (but maybe more uselessly complicated), yet hoping to having a solution for an ampersand seen by the outside, not by the inside, if that makes sense. I'll probably adopt your solution. –  gniourf_gniourf Oct 2 '12 at 19:50
@gniourf_gniourf: My original thought was to totally re write this within an alignat environment, but that would have been a radical change to the way you were doing things, so decided against it. While what you are describing is probably doable (beyond my skill set), it might be more work than using a simpler solution such as this. I recall a posting (not sure if it was just in a chat session though) where specific alignment points were remembered and used outside upon a subsequent run, but not sure if that would work in this case. –  Peter Grill Oct 2 '12 at 19:56