Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sometimes I'd like a macro to depend on a boolean argument but I don't know about the best way to implement this. So far, I end up introducing a global (say) \newif\ifextra that is used inside the macro but that needs to be set each time before the macro is called.

\documentclass{minimal}

\newif\ifextra
\def\showcase{Show a sentence. \ifextra And a little more if asked to. \fi}

\begin{document}
        \extratrue\showcase 
        \extrafalse\showcase
\end{document}

From a programming perspective it would be better to pass the flag as an argument rather than relying on a global flag. What is the best practice here?

Addendum: egreg's answer highlights that this can also be understood as implementing two variants of a macro, like \showcase and \showcase*, where the flag is encoded into the name (technically it's not, but that is how it looks).

share|improve this question
add comment

2 Answers 2

up vote 13 down vote accepted

You can use a *-variant:

\usepackage{xparse}
\NewDocumentCommand{\showcase}{s}{%
  Show a sentence.%
  \IfBooleanT{#1}{ And a little more if asked to.}%
}

Now \showcase will produce the short version and \showcase* the long one. Just change \IfBooleanT into \IfBooleanF for the reverse. There's also \IfBooleanTF that accepts two texts.

The variant indicator can be different: if you say

\NewDocumentCommand{\showcase}{t+}{...}

then the variant will be \showcase+.


The "classical" method

Using "pure LaTeX" one can say

\makeatletter
\newcommand{\showcase}{%
  \@ifstar
    {\@showcase{ And a little more if asked to.}}
    {\@showcase{}}%
}
\newcommand{\@showcase}[1]{Show a sentence.#1}
\makeatother

This version of \showcase would be fragile and \DeclareRobustCommand would be needed for defining it in case it's supposed to appear in moving arguments (or it should be preceded by \protect). So two macros must be defined (three in case \DeclareRobustCommand is used), instead of the only one with xparse.

In this case, to be honest, a simpler method would work:

\makeatletter
\newcommand{\showcase}{Show a sentence.%
  \@ifstar{ And a little more if asked to.}{}}
\makeatother

because you don't want to grab arguments. But this would fail if you want something like

 \showcase{b}
 \showcase*{b}

to produce

Show b sentence.
Show b sentence. And a little more if asked to.

respectively. You'll have to do with the auxiliary macro:

\makeatletter
\newcommand{\showcase}{%
  \@ifstar
    {\@showcase{ And a little more if asked to.}}
    {\@showcase{}}%
}
\newcommand{\@showcase}[2]{Show #2 sentence.#1}
\makeatother

To work properly, \@ifstar{...}{...} must be last in a replacement text.

With xparse you'd do

\NewDocumentCommand{\showcase}{sm}{%
  Show #2 sentence.%
  \IfBooleanT{#1}{ And a little more if asked to.}%
}

Other methods

There are other packages that allow for defining macros with variants, for instance suffix:

\usepackage{suffix}
\newcommand{\showcase}{Show a sentence.}
\WithSuffix\def\showcase*{%
  \csname\NoSuffixName\showcase\endcsname{} And a little more if asked to.}

The syntax is not very friendly in either case.

share|improve this answer
    
You could of course do the * variant without xparse/LaTeX3. –  StrongBad Jun 7 '12 at 8:41
    
@DanielE.Shub Yes, but I believe that this is the most practical way. I'll add something. –  egreg Jun 7 '12 at 8:43
    
Could the classical method be simplified to \def\showcase{Show a sentence. \@ifstar{And show some more.}{}}? Or does \@ifstar has to come at the beginning of the macro being star'ed? A first test suggests this works but I wonder about the general case. –  Christian Lindig Jun 7 '12 at 13:21
    
@ChristianLindig In this case you can do that simplification, because you don't have to grab arguments for \showcase. The important thing is that \@ifstar{}{} comes last in the replacement text. I'll show it with an example. –  egreg Jun 7 '12 at 13:26
    
@egreg Thanks for continuously extending your answer! (In your updated example there is no \@ifstar any more which is just a bug, I assume.) –  Christian Lindig Jun 7 '12 at 16:23
show 1 more comment

You can try this:

\documentclass{minimal}
\newif\ifextra
\newcommand\showcase[1][1]{Show a sentence.
   \ifnum#1=1 \extratrue\else\extrafalse\fi
   \ifextra And a little more if asked to. \fi}
\begin{document}
        \showcase[0] \\
        \showcase[1]
\end{document}

I have used 1 as true and any other number as false for providing a condensed syntax.

As noted in the comments, if the switch \ifextra is not used outside a macro you can drop it.

\documentclass{minimal}
\newif\ifextra
\newcommand\showcase[1][0]{Show a sentence.
   \ifnum#1=1 And a little more if asked to. \fi}
\begin{document}
   \showcase\\
   \showcase[1]
\end{document}
share|improve this answer
    
Why not use \ifnum .. \else ..\fi directly and drop \ifextra? Any drawback? My takeaway is that you are using numbers as argument because they work well together with \ifnum. –  Christian Lindig Jun 7 '12 at 7:17
1  
@ChristianLindig You can do that as well. I kept it as close to your original syntax as possible in case you using the boolean outside macros. –  Yiannis Lazarides Jun 7 '12 at 7:21
    
\extra is only global because I didn't know of a better way. So there is no use of it outside the macro and I'd now use \ifnum directly. –  Christian Lindig Jun 7 '12 at 7:24
    
@ChristianLindig Thanks for the clarification, I added a note as well to the answer to make it clearer. –  Yiannis Lazarides Jun 7 '12 at 7:27
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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