12

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}.

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

4 Answers 4

15

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

8
  • 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. Jul 7, 2015 at 16:37
  • @SeanAllred: Yes, I had it in mind right from the start. And you added the comment anyway :-P
    – user31729
    Jul 7, 2015 at 16:37
  • If that's the order, why is it better with []?
    – Manuel
    Jul 7, 2015 at 17:37
  • @Manuel: The usual order is []{} ... I explicitly wanted to reverse this
    – user31729
    Jul 7, 2015 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, 2015 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

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

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}
6
  • There is no package required. This is good!
    – Say OL
    Jul 7, 2015 at 17:24
  • @SayOL that's why i add it
    – touhami
    Jul 7, 2015 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, 2015 at 17:42
  • @egreg what about \newcommand{\set}[2][\relax]{\left\lbrace\ifx #1\relax?
    – touhami
    Jul 7, 2015 at 20:43
  • 1
    @touhami Try \set[aa]{xx}
    – egreg
    Jul 7, 2015 at 20:52
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

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