3

So a while ago I asked this question on doubled delimiters. I found this piece of code and adapted it into the following:

\documentclass{article}

\usepackage{mathtools}

\DeclarePairedDelimiterX{\dbrackets}[1]{\lbrack}{\rbrack}{
    \nhphantom{$\delimsize\lbrack$} \delimsize\lbrack \mathopen{} #1 \mathclose{} \delimsize\rbrack \nhphantom{$\delimsize\rbrack$}
}
\DeclarePairedDelimiterX{\dbraces}[1]{\lbrace}{\rbrace}{
    \nhphantom{$\delimsize\lbrace$} \delimsize\lbrace \mathopen{} #1 \mathclose{} \delimsize\rbrace \nhphantom{$\delimsize\rbrace$}
}
\DeclarePairedDelimiterX{\dparens}[1]{\lparen}{\rparen}{
    \nhphantom{$\delimsize\lparen$} \delimsize\lparen \mathopen{} #1 \mathclose{} \delimsize\rparen \nhphantom{$\delimsize\rparen$}
}


\newcommand{\nhphantom}[1]{\sbox0{#1}\hspace{-0.751\dimexpr\the\wd0 \relax}}


\begin{document}

$\dbrackets[\big]{\frac12}$
$\dbraces[\big]{\frac12}$
$\dparens[\big]{\frac12}$

%These don't work:

%$\dbrackets*{\frac12}$
%$\dbraces*{\frac12}$
%$\dparens*{\frac12}$

\end{document}

It does exactly what I wanted, but I don't really understand the code and there are many macros I have never seen. So I would really appreciate if someone could explain to me what is going on here:

  • What is the intention of the \nhphantom macro?
  • What does \sbox0 do?
  • What does \dimexpr\the\wd0 do?

I would also like to understand why the starred version of the mathtools commands don't work.

  • Just to start, -0.751\dimexpr\the\wd0\relax can be, much more simply, -0.751\wd0 (a fraction of the width of the current contents of \box0). – egreg Apr 13 '18 at 13:21
6

TeX has something called a box, which is what it uses to organize things in the document. Knuth's TeX has 256 box registers for you to use. Think of that as 256 actual boxes available for TeX to store things and then use them in the document.

The command \sbox0{#1} puts the contents of #1 in the box register n° 0.

Now that the box register 0 has #1 you can do things with this box, like measure its width with \wd, height with \ht, and depth with \dp, so \wd0 returns the with of the contents of the box 0.

So, breaking apart the \nhphantom macro:

% Store the contents of #1 into box register 0
\sbox0{#1}%
% Go back -0.751 times the \wd of the box register 0
\hspace{-0.751\dimexpr\the\wd0 \relax}

Also, as egreg said in the comments, -0.751\dimexpr\the\wd0 is redundant. The \the will get the text representation of \wd0, then the \dimexpr will read this text back into a number. You can skip this back-and-forth with -0.751\wd0, so you can simplify to:

\newcommand{\nhphantom}[1]{\sbox0{#1}\hspace{-0.751\wd0}}

This register principle is what makes up TeX's memory. TeX has:

  • \count registers to hold counters (integers);
  • \dimen registers to hold lengths;
  • \skip registers to hold glue (one dimen plus another minus one more);
  • \muskip registers to hold muglue (for maths);
  • \box registers to hold boxes; and
  • \toks registers to hold lists of tokens.

As for your question about the starred versions (which I saw only now, sorry)...

The \sbox0{#1} in the \nhphantom macro saves the contents of #1 in an \hbox, which is not in math mode, thus you have to call \nhphantom with $...$ to enforce math mode. But this creates a math mode in text mode in math mode thing, which makes TeX "forget" about the rest of the equation it is in.

When you use a starred version of a delimiter created by \DeclarePairedDelimiterX, you make the outer delimiters be \left<delim> and \right<delim>, and the \delimsize becomes \middle to be used safely between \left and \right. The problem is that the math-in-text-in-math thing makes TeX forget about the surrounding \left and \right and the argument of \nhphantom is $\middle\lbrack$, which is invalid because you cannot use \middle without an enclosing \left...\right.

To workaround this issue I changed the \nhphantom macro a little. It now has two arguments: the delimiter and the content in between. The \nhphantom macro then measures the width of \left<delim>\vphantom{#1}\right., which is valid.

Here is the complete working code:

\documentclass{article}

\usepackage{mathtools}

\DeclarePairedDelimiterX{\dbrackets}[1]{\lbrack}{\rbrack}{
    \nhphantom{\lbrack}{#1} \delimsize\lbrack \mathopen{} #1 \mathclose{} \delimsize\rbrack \nhphantom{\rbrack}{#1}
}
\DeclarePairedDelimiterX{\dbraces}[1]{\lbrace}{\rbrace}{
    \nhphantom{\lbrace}{#1} \delimsize\lbrace \mathopen{} #1 \mathclose{} \delimsize\rbrace \nhphantom{\rbrace}{#1}
}
\DeclarePairedDelimiterX{\dparens}[1]{\lparen}{\rparen}{
    \nhphantom{\lparen}{#1} \delimsize\lparen \mathopen{} #1 \mathclose{} \delimsize\rparen \nhphantom{\rparen}{#1}
}

\newcommand{\nhphantom}[2]{\sbox0{$\left#1\vphantom{#2}\right.$}\hspace{-0.58\wd0}}

\begin{document}

$\dbrackets[\big]{\frac12}$
$\dbraces[\big]{\frac12}$
$\dparens[\big]{\frac12}$

%These do work :)

$\dbrackets*{\frac12}$
$\dbraces*{\frac12}$
$\dparens*{\frac12}$

\end{document}

enter image description here

  • 3
    \the is redundant, because \wd0 is a dimension. But then also \dimexpr and \relax are. – egreg Apr 13 '18 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.