10

This question already has an answer here:

I want to define a new command that serves two slightly different purposes. Can I define a new command called \set such that it's definition is chosen according to the number of argument(s) is(are) filled? I want {1,2,3} when I use \set{1,2,3} and I want {x | x>0} when I use \set{x}{x>0}.

marked as duplicate by touhami, user13907, Gonzalo Medina, Jesse, Andrew Jul 8 '15 at 2:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    I've removed the latex3 tag here -- it's not related to it. – user31729 Jul 7 '15 at 16:36
  • 1
    @ChristianHupfer But thank heavens, the answers use it. :) – Sean Allred Jul 7 '15 at 16:38
  • @SeanAllred: xparse uses LaTeX3? Oh my.... :-P – user31729 Jul 7 '15 at 16:39
  • @ChristianHupfer Well I'm sure you know that xparse is part of the '3 in 2e' effort – Sean Allred Jul 7 '15 at 16:40
  • @SeanAllred: I know of course – user31729 Jul 7 '15 at 16:41
14

Yes, this is possible, using \NewDocumentCommand from xparse for example, making the second argument with {} behave like an optional argument then, i.e. using the g argument modifier.

Please note, that there is already a \set{} macro in the braket package, which provides for typesetting of sets, so I called the macro \myset instead and use \set{...} inside.

In principle, this could be done with an trailing optional argument with [] too, which is perhaps even better, because this enforces you to distinguish between the list version and the conditional version of the set notation.

Edit I've added the \mybetterset{}[] command as a variant to \myset, using the [] as 2nd optional argument.

\documentclass{article}

\usepackage{braket}
\usepackage{mathtools}
\usepackage{xparse}

\NewDocumentCommand{\myset}{mg}{%
  \IfValueTF{#2}{%
    \set{#1\;\vert\;#2}
  }{%
    \set{#1}%
  }%
}

%% The better command with [] as optional argument

   \NewDocumentCommand{\mybetterset}{mo}{%
  \IfValueTF{#2}{%
    \set{#1\;\vert\;#2}
  }{%
    \set{#1}%
  }%
}

\usepackage{hyperref}

\begin{document}
$\myset{1,2,3}$

$\myset{x}{x > 0}$

$\mybetterset{1,2,3}$

$\mybetterset{x}[x>0]$


\end{document}

enter image description here

  • I was going to add a comment about the [] until you edited it in :) That's the approach I use in my documents and it works out much better, I think. – Sean Allred Jul 7 '15 at 16:37
  • @SeanAllred: Yes, I had it in mind right from the start. And you added the comment anyway :-P – user31729 Jul 7 '15 at 16:37
  • If that's the order, why is it better with []? – Manuel Jul 7 '15 at 17:37
  • @Manuel: The usual order is []{} ... I explicitly wanted to reverse this – user31729 Jul 7 '15 at 19:02
  • @ChristianHupfer I mean, if you said better \set[..]{..} than \set{..}{..} I would think “well, that's okey” but if you say \set{..}[..] is better than \set{..}{..}, well, I don't understand why (and I don't think so, at least at this moment I don't see any reason why it would be better). – Manuel Jul 7 '15 at 19:05
9

You can do it, but I discourage you to. Better defining a command that distinguishes between \set{1,2,3} and \set{x|<condition>}.

You can find perhaps better methods in the documentation of mathtools.

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\set}{>{\SplitArgument{1}{|}}m}{\printset#1}

\NewDocumentCommand{\printset}{mm}{%
  \IfNoValueTF{#2}
   {% no |
    \{#1\}%
   }
   {% |
    \{\,#1\mid#2\,\}%
   }%
}

\begin{document}

$\set{1,2,3}=\set{x | 1\le x\le 3}$

\end{document}

enter image description here

  • Took the idea right from my mind :) – Sean Allred Jul 7 '15 at 16:34
  • @egreg: You forgot x to be a natural number :-P – user31729 Jul 7 '15 at 16:40
  • @ChristianHupfer That's obvious from the context, isn't it? ;-) – egreg Jul 7 '15 at 16:41
  • @egreg: In the context yes, but having the RHS as a standalone ... – user31729 Jul 7 '15 at 16:42
5

A variant solution, also with mathtools and xparse. When used for a set defined by a property, the separator between elements and properties is a semicolon, because it is easy to type, and rarely used in maths (except for sets defined by a property). The resulting sign in the .pdf file will be a vertical bar, with a correct spacing. If for some reason you really need a semi-colon, you just enclose it between a pair of braces. Thus the syntax is very close to what one writes by hand: \set{x;P(x)}.

The size of the braces and the the vertical bar will adjust automatically to the size of the contents with the star version of the \set command, or manually for fine-tining, with optional arguments: \big, \Big, \bigg,\Bigg`.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{fourier, erewhon}

\usepackage{xparse}
\usepackage{mathtools, nccmath}

\DeclarePairedDelimiterX{\set}[1]\{\}{\setargs{#1}}
\NewDocumentCommand{\setargs}{>{\SplitArgument{1}{;}}m}
{\setargsaux#1}
\NewDocumentCommand{\setargsaux}{mm}
{\IfNoValueTF{#2}{#1}{\nonscript\,#1\nonscript\;\delimsize\vert\nonscript\:\allowbreak #2\nonscript\,}}
%
% %% The following makes \big the default for the \set command
% \let\oldset\set
% \def\set{\futurelet\testchar\MaybeOptArgSet}
% \def\MaybeOptArgSet{\ifx[\testchar \let\next\OptArgSet
% \else \let\next\NoOptArgSet \fi \next}
% \def\OptArgSet[#1]#2{\oldset[#1]{#2}}
% \def\NoOptArgSet#1{\OptArgSet[\big]{#1}}
%
% \def\Set{\oldset*}%

%%% Syntax: \set{x ; P(x)})
\begin{document}

\begin{align*}
    & \set[\big]{x ; x > 5} & & \set*{x ; x > 5} \\[4pt]
    & \set[\bigg]{ \frac{x}{2} ; x > 5} & & \set*{ \frac{x}{2} ; x > 5} \\[4pt]
    & \set[\Bigg]{ \frac{1}{2},\frac{1}{3},\frac{1}{4},\dotsm} & & \set*{ \mfrac{1}{2},\mfrac{1}{3},\mfrac{1}{4},\dotsm}
\end{align*}

\end{document} 

In the above code I commented out some lines that result in the default implicit use of the \big optional argument (which looks better, in my opinion). The \set* command is the replaced with a new Set command.

enter image description here

5

Here is another soultion, with optional argument

\documentclass{article}
\newcommand{\set}[2][]{\left\lbrace\if\relax\detokenize{#1}\relax\else#1\mid\fi#2\right\rbrace}

\begin{document}
bla bla
\[\set{a,b,c},\set[x]{x>0}\]
$\set{a,b,c},\set[x]{x>0}$
\end{document}

Classical method

\documentclass{article}

\makeatletter
\newcommand{\set}{\@ifnextchar[{\@@set}{\@set}}
\def\@set#1{\left\lbrace#1\right\rbrace}
\def\@@set[#1]#2{\@set{#1\mid#2}}
\makeatother

\begin{document}
bla bla
\[\set{a,b,c},\set[x]{x>0}\]
$\set{a,b,c},\set[x]{x>0}$
\end{document}
  • There is no package required. This is good! – Say OL Jul 7 '15 at 17:24
  • @SayOL that's why i add it – touhami Jul 7 '15 at 17:26
  • 3
    \ifx#1\empty is conceptually wrong. \ifx#1\empty\relax would be a little better; \if\relax\detokenize{#1}\relax is the right one. – egreg Jul 7 '15 at 17:42
  • @egreg what about \newcommand{\set}[2][\relax]{\left\lbrace\ifx #1\relax? – touhami Jul 7 '15 at 20:43
  • 1
    @touhami Try \set[aa]{xx} – egreg Jul 7 '15 at 20:52

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