4

The following definition, from How to continue a piece of text so it is aligned with the last line of an inline multiline box?, allows splitting a math set-builder expression across two lines:

\newcommand\setst[2]{\{#1 : 
   \begin{array}[t]{@{}l@{}}#2 \}\end{array}}

I want:

  1. to change \{ and \} to \left\{ and \right\}, respectively. The following attempt generates an error of a missing `\right. ; and
  2. not to have symbols that would normally be tall in display math, such as integral signs, get squashed down by the array environment.

    What's wrong with my syntax?

    \newcommand\Setst2{\left{#1 : \right. % \begin{array}[t]{@{}l@{}}\left.#2 \right}\end{array}}

And how fix the issue of squashed normally-tall symbols retain their noraml display-math height? (See 2nd source file below.)

Example source (modified from above-cited link):

\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}

\newcommand\setst[2]{\{#1 : 
  \begin{array}[t]{@{}l@{}}#2 \}\end{array}}

% my attempted mod
\newcommand\Setst[2]{\left\{#1 : \right. %
  \begin{array}[t]{@{}l@{}}\left.#2 \right\}\end{array}}

\begin{document}

Braces OK:
\[
\setst{x}{ x \in S_1 \land {} \\
          (x \in S_2 \lor x \in S_3) }
\]

Error:
\[
\Setst{x}{ x \in S_1 \land {} \\
          (x \in S_2 \lor x \in S_3) }
\]

\end{document}

Here's the printed output from just the "OK" version, using the original command \setst:

Split-line set-builder

The aim is to replace the { and the } in the output with the coresponding large versions — assuming, of course, that the math expression within causes those braces to expand. But each brace should not expand so as to encompass both lines of the printed output!

Here's a more realistic example, where larger braces are really needed:

\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}

\newcommand\setst[2]{\{#1 : 
  \begin{array}[t]{@{}l@{}}#2 \}\end{array}}

% my attempted mod
\newcommand\Setst[2]{\left\{#1 : \right. %
  \begin{array}[t]{@{}l@{}}\left.#2 \right\}\end{array}}

\begin{document}

Works, but integral sign and absolute value get squashed down smaller than they ought to appear in display math:
\[
\setst{f}{f(t) > 0 \text{ for all $t$ with } 0 < t < 1\\
    \text{and }\left|\int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t) dt\right| \leq 1 }
\]

\end{document}

And the output from that, with the two braces indicated:

Split-line set-builder #2

  • So what should be the span of the brackets in your example? Should \left\{ and \right\} span from the top of x to the bottom of S_3 (say)? Or should they have differing heights? – Werner Feb 22 '17 at 20:26
  • The error occurs because the argument #2 contains a double backslash, which ends the array line before processing reaches \right. I'm not sure what result you want, so I don't know what fix to suggest. – Ian Thompson Feb 22 '17 at 20:28
  • @Werner: Ideally, the \left\{ and \right\} should span from the initial x to the final S_3. I tried to do that directly, but think there may be an issue with putting a single \left\{ before the array but then a single \right\} inside the array. – murray Feb 22 '17 at 20:29
  • I want essentially the same result as with the unmodified \setstexcept that the printed braces should be proportionately larger, as in the usual situation with \left\{ and \right\}. – murray Feb 22 '17 at 20:31
  • Why not just use something like \bigl\{ ... \bigr\}. Will the expected expansion be larger than that? – Werner Feb 22 '17 at 20:49
5

I suggest pursuing a less-than-fully-automatic approach to sizing the outer curly braces. In the code below the default size of the outer curly braces is \big, but this may be changed by specifying an optional sizing-related parameter, which may take on values Bigg, bigg, Big (and, of course, big). I favor a minimum size of big (rather than normalsize) as IMNSHO, the curly braces simply need to "look" a bit more prominent.

In the following screenshot, the curly braces in the first example are of size \big (the default); they are of size \bigg in the second, where \displaystyle is in effect for the second row.

enter image description here

\documentclass{article}
\usepackage{mathtools} % for '\DeclarePairedDelimiter' macro
\DeclarePairedDelimiter{\abs}{\lvert}{\rvert} % "absolute value" macro

\newcommand\Setst[3][big]{\csname #1l\endcsname\{ #2 : 
  \begin{array}[t]{@{}l@{}}#3\csname #1r\endcsname \}\end{array}}

\begin{document}
\[
\Setst{f}{\text{$f(t)>0$ for all $t$ with $0<t<1$}\\
          \text{and }\abs[\big]{\int_0^1 e^{-\frac{1}{2}t^2}\!f(t)\,dt}\leq1}
\]

\[ % use \displaystyle directive in second row; hence, use "bigg" curly braces
\Setst[bigg]{f}{\text{$f(t)>0$ for all $t$ with $0<t<1$}\\
  \displaystyle \text{and }\abs[\bigg]{\int_0^1 e^{-\frac{1}{2}t^2}\!f(t)\,dt}\leq1}
\] 
\end{document}
  • With both big and bigg, the integral sign (and enclosing absolute value) is getting squashed down to be much smaller than it would normally appear in display math. That happens, unfortunately, even with the original macro \setst of my original post. (I'll add that there.) – murray Feb 23 '17 at 1:29
  • @murray - I've updated the example code to provide a better motivation for using bigg curly braces in the second equation: \displaystyle is now in effect in the second row of the array. (The default style in an array is text style, not display style.) The updated code also features and "absolute value" macro, which makes the code more "LaTeX-y" since it provides more of a distinction between the intended meaning on the one hand and the underlying TeX code on the other. – Mico Feb 23 '17 at 2:38
  • If you prefer to have display math style be the default in the array contained in the \Setst macro, I suggest you load the array package in the preamble and change the setup of the array from {@{}l@{}} to {@{}>{\displaystyle}l@{}}. Then, as you may see fit, you can still revert to text style by issuing the directive \textstyle at the start of a row. – Mico Feb 23 '17 at 5:58
4

I'd set the components slightly differently to allow for \left-\right to be used to span the entire construction:

enter image description here

\documentclass{article}

\usepackage{amsmath,amssymb}

\newcommand\setst[2]{\{#1 : 
  \begin{array}[t]{@{}l@{}}#2 \}\end{array}}

% my attempted mod
\newcommand\Setst[2]{%
  \expandafter\setsttopandbottom#2\relax
  \begin{array}{@{}l @{\ } l@{}}
    \left\{#1 :\vphantom{\setsttop}\vphantom{\setstbottom}\right.\kern-\nulldelimiterspace & 
    \begin{array}[t]{@{}l@{}}
      \setsttop \\ \kern-\nulldelimiterspace\left.\setstbottom\vphantom{\setsttop}\right\}
    \end{array}
  \end{array}
  }

\def\setsttopandbottom#1\\#2\relax{\def\setsttop{#1}\def\setstbottom{#2}}

\begin{document}

OK:
\[
  \setst{f}{f(t) > 0 \text{ for all $t$ with } 0 < t < 1 \\
      \text{and }\left|\int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t) dt\right| \leq 1 }
\]

Modified:
\[
  \Setst{f}{f(t) > 0 \text{ for all $t$ with } 0 < t < 1\\
      \text{and }\left|\int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t) dt\right| \leq 1 }
\]

\end{document}

In particular, the top and bottom part of the construction in the second argument is extracted and used in measurements for the first row (for the opening \{) as well as the last row (for the closing \}).

The above solution assumes that you will always use a \\ inside your construction and therefore have two lines. A separate macro would have to be constructed for a single-line application.


Using

\usepackage{array}

\newcommand\Setst[2]{%
  \expandafter\setsttopandbottom#2\relax
  \begin{array}{@{}>{\displaystyle}l @{\ } l@{}}
    \left\{#1 :\vphantom{\setsttop}\vphantom{\setstbottom}\right.\kern-\nulldelimiterspace & 
    \begin{array}[t]{@{}>{\displaystyle}l@{}}
      \setsttop \\ \kern-\nulldelimiterspace\left.\setstbottom\vphantom{\setsttop}\right\}
    \end{array}
  \end{array}
  }

you can always ensure that the cells within the array construction will be set using \displaystyle.

  • No, I do not want each brace to expand to enclose both of the printed lines. – murray Feb 22 '17 at 20:45
  • @murray: I've updated my answer based on you mentioning that there will be exactly two lines within the construction. – Werner Feb 22 '17 at 22:43
  • @murray: But do you really want the two braces (opening and closing) to have different sizes? Have you tried, instead, something along the lines of Sebastien Gouezel’s trick reported on p. 29 of the manual of the mathtools package? In the present case, it would be, on hand, easier to implement it, since there are no & tokens occurring, and hence no need to re-assign category codes with \scantokens; but on the other, you need to redefine \array to do nothing, yet absorb its arguments. – GuM Feb 22 '17 at 22:57
  • 1
    @murray: I've updated my answer to use some more \vphantom content. For future reference, please think about all the use cases for your question and supply that information from the start. Asking good questions are difficult, I understand; keep you audience in mind when doing so. – Werner Feb 23 '17 at 1:34
  • 1
    @murray: This is the default behaviour. Within an array, the default placement of content uses \textstyle. If you want content to be set "normally", use \displaystyle. – Werner Feb 23 '17 at 2:00
4

This answer is just a draft intended to explain what I had in mind when I posted my comment.

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\usepackage{amsmath}

\makeatletter

\newcommand*{\SetSt}[2]{%
    \setbox\z@ \hbox{%
        % Inside this box, the "\\" command is `turned off'. 
        % BEWARE: WE ASSUME THAT "&" IS **NOT** USED INSIDE #2!
        \let\\\relax
        $#2$%
    }%
    \dimen@   \ht\z@
    \dimen@ii \dp\z@
    % Now typesetting begins:
    \left\{\,#1%
    % select one of the two following alternatives:
    % {}:{}% colon as separator
    \,\middle|\,% vertical bar as separator
    \vrule \@height\dimen@ \@depth\dimen@ii \@width\z@
    \right.\kern-\nulldelimiterspace
    \begin{array}[t]{@{}l@{}}%
        #2%
        \left.\kern-\nulldelimiterspace
        \vrule \@height\dimen@ \@depth\dimen@ii \@width\z@
        \right\}%
    \end{array}%
}

\makeatother



\begin{document}

With tall symbols:
\[
    \SetSt{f}{f(t) > 0 \text{ for all $t$ with } 0 < t < 1\\
        \text{and }\left|\int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t) dt\right| \leq 1 }
\]

WIthout tall symbols:
\[ \SetSt{x}{x\in A \land x\in B\\x\in C \land x\in D\\x\in E \land x\in F} \]
As you can see, no restriction is imposed on the number of lines.  Even a 
single line is OK\@:
\[ \SetSt{x}{\int_{0}^{x} f(t)\,dt > 0} \]

Another example with two lines:
\[
    \SetSt{x}{\int_{0}^{x} f(t)\,dt > 0\\\int_{0}^{x} g(t)\,dt > 0}
\]

\end{document}

It can be refined in at least two respects:

  • the \\ command shouldn’t be simply redefined as \relax, it should gobble a star and an optional argument, if present;

  • the \SetSt command should take the current math style into account; this is easily achived with a routine application of \mathpalette.

I’m sorry, but now I’m too tired to make these refinements…

Edit

I’m now able to post an amended version of the code:

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\usepackage{amsmath}
\usepackage{array}

\makeatletter

\newcommand*\SetSt[2]{\mathpalette{\@SetSt{#1}}{#2}}
\newcommand*\@SetSt[3]{%
    % #1 := 1st argument of "\SetSt"
    % #2 := style selector (e.g., "\displaystyle")
    % #3 := 2nd argument of "\SetSt"
    \setbox\z@ \hbox{%
        % Inside this box, the "\\" command is `turned off'. 
        % BEWARE: WE ASSUME THAT "&" IS **NOT** USED INSIDE #3!
        \let\\\@Murray@NoopCR
        $#2#3$%
    }%
    \dimen@   \ht\z@
    \dimen@ii \dp\z@
    % Now typesetting begins:
    \left\{\@nonscript@thinspace #2% style selector
    % The following group protects the value of "\dimen@" and "\dimen@ii":
    \begingroup #1\endgroup
    % select one of the two following alternatives:
    % {}:{}% colon as separator
    \@nonscript@thinspace\middle|\@nonscript@thinspace % vertical bar as separator
    \@Murray@mathstrut
    \right.\kern-\nulldelimiterspace
    % The group around the cells allows this macro to be nested;
    % it is important only for the last row, but we cannot avoid specifying it 
    % for every entry.
    \begin{array}[t]{@{}>{#2\begingroup}l<{\endgroup}@{}}%
        #3\endgroup % end the group to restore the values of "\dimen@" and 
                    % "dimen@ii"
        \left.\kern-\nulldelimiterspace
        \@Murray@mathstrut
        \right\}%
        \begingroup % to balance the "\endgroup" at the end of the entry
    \end{array}%
}
\newcommand*\@Murray@NoopCR{\@ifstar\x@Murray@NoopCR\x@Murray@NoopCR}
\newcommand*\x@Murray@NoopCR{\@ifnextchar[\y@Murray@NoopCR {}}
\@ifdefinable\y@Murray@NoopCR{\def\y@Murray@NoopCR[#1]{}}
\newcommand*\@nonscript@thinspace{\nonscript\mskip\thinmuskip}
\newcommand*\@Murray@mathstrut{%
    \vrule \@height\dimen@ \@depth\dimen@ii \@width\z@
}

\makeatother



\begin{document}

With tall symbols:
\[
    \SetSt{f}{f(t) > 0 \text{ for all $t$ with } 0 < t < 1\\[\medskipamount]
        \text{and }\left|\int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t) dt\right| \leq 1 }
\]

WIthout tall symbols:
\[ \SetSt{x}{x\in A \land x\in B\\x\in C \land x\in D\\x\in E \land x\in F} \]
As you can see, no restriction is imposed on the number of lines.  Even a 
single line is OK\@:
\[ \SetSt{x}{\int_{0}^{x} f(t)\,dt > 0} \]

Another example with two lines:
\[
    \SetSt{x}{\int_{0}^{x} f(t)\,dt > 0
    \\*[\bigskipamount]% the star serves no purpose, we just want to check that 
                       % it is handled correctly
    \int_{0}^{x} g(t)\,dt > 0}
\]

An example of nesting:
\[
    \SetSt{x}{x\in A\\x\in B\\x\in\SetSt{y}{y<-1\\y>1}}
\]
This last example clearly shows the limits of the algorithm.

\end{document}

And here is the output it produces:

Output of the amended code

  • In the 1st, 3rd, and 4th examples, the integral sign is getting squashed down to be much smaller than it would normally appear in display math. – murray Feb 23 '17 at 1:21
  • @murray - The size of the integrals is determined by the math "style" that's in use: For an array environment, the default style is text style. To override this setting (say, to get larger integral symbols), insert the directive \displaystyle. – Mico Feb 23 '17 at 2:45
  • I don't understand the 3-argument version of your amended version: where is it that I specify the display style? alreadyt your first example (the "tall version" already sems to be using \displaystyle. – murray Feb 23 '17 at 20:16
  • @murray: \displaystyle (or other style selectors as appropriate) is supplied by the \mathpalette macro as the 2nd argument of \@SetSt; that’s precisely the way \mathpalette works, and the reason for using it. For an explanation, see, for example, The mysteries of \mathpalette, or Understanding expansion of \mathpalette (the latter, to understand where the 3rd argument of \@SetSt comes from). – GuM Feb 25 '17 at 0:13
  • @Gustavo Mezzetti: Got it! (I had a hard time deciding between answers that met my original specification of using \left and \right, on the one hand, the one that suggested the optional argument to indicate \bigx, \biggx, etc. – murray Feb 26 '17 at 1:02
2

I propose another layout for this set builder notation, with a simple solution based on delarray and stackengine. In addition, I defined an \abs command with \DeclarePairedDelimiterX from mathtools, and a diffrential symbol with a correct spacing in integrals:

\documentclass{article}
\usepackage{mathtools}
\usepackage{amssymb, delarray}
\usepackage[usestackEOL]{stackengine}

\DeclarePairedDelimiterX{\abs}[1]{\lvert}{\rvert}{\ifblank{#1}{\:\cdot\:}{#1}}%%

\newcommand\mySetst[2]{ \begin{array}\{{@{}>{\everymath{\displaystyle}}c@{\::\:}>{\everymath{\displaystyle}}l@{}}\}
#1 & \stackMath\Shortunderstack[l]{#2}
 \end{array}}

\newcommand\dd[1]{\,\mathrm{d}\mkern 1mu#1} %% differential symbol for integrals

\begin{document}

 \[ \mySetst{f}{f(t)>0 \text{ for all $t$ with } 0<t<1\\\text{and }\abs*{int_{0}^{1}e^{-\frac{1}{2} t^{2}}f(t)\dd t} \leq 1} \]%
\
\end{document} 

enter image description here

  • @Mico: Ah! I understood exactly the contrary. I should remove it then, but maybe this code might be of interest for someone else? – Bernard Feb 23 '17 at 3:09
  • I guess you're right. I'll add some words. Anyway, I don't see what the difficulty was to get the other look. – Bernard Feb 23 '17 at 3:13

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.