6

How can I test for a not defined boolean?

I want to have

\usepackage{xr-hyper}
\usepackage{hyperref}

\providebool{is_single_book}
\booltrue{is_single_book}

in my main.tex and in each of the chapter TeX files.

if not defined is_single_book
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]
fi

So when I compile the entire book, \externaldocument{volume1}[http://mybook.com/volume1.pdf] isn't executed.

It doesn't have to be a boolean if something else is simpler or doesn't require an extra package.

2
  • Why do you want "is not defined" rather than "true" and "false"? Does a package specify that boolean?
    – TeXnician
    Commented Aug 16, 2018 at 11:06
  • 3
    So you essentially want a three-way switch: boolean undefined, boolean true and boolean false? Or can you simplify this to a simple two-valued logic with a true and false boolean? Since you use etoolbox commands you can use \ifcsundef{ifis_single_book}{<undef>}{<def>} to check if the boolean is_single_book is undefined. Note that \providebool makes sure the boolean is defined, so \ifcsundef{ifis_single_book} will execute the false branch.
    – moewe
    Commented Aug 16, 2018 at 11:06

3 Answers 3

6

While you could check if a bool is defined by using \ifcsundef{if...} (see comment from moewe), it looks as if you actually want a boolean which is always false if you are in a chapter tex file.

This can be archived by using \providebool, which defines the bool as false, iff is is not defined already:

Use

\newbool{is_single_book}
\booltrue{is_single_book}

in your main file and

\providebool{is_single_book}
\ifbool{is_single_book}{}{%
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]%
}

in your chapter files.

Even better would be to use toggles. They are almost the same but avoid name clashes and provide slightly better performance:

To use them, insert

\newtoggle{is_single_book}
\toggletrue{is_single_book}

in your main file and

\providetoggle{is_single_book}
\iftoggle{is_single_book}{}{%
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]%
}

in the chapters.

2
  • Something seams to be wrong for the chapters part. \externaldocument{volume1}[http://mybook.com/volume1.pdf] isn't being executed. Is is_single_book true or fasle right after \providetoggle{is_single_book}? Commented Aug 16, 2018 at 12:34
  • \externaldocument{volume1}[http://mybook.com/volume1.pdf] should be executed if is_single_book is false or undefined. Commented Aug 16, 2018 at 12:37
9

\providebool and \booltrue makes me think you are using etoolbox.

etoolbox booleans are just a thin wrapper around TeX's \newif.

That means that \newbool{<name>} defines \if<name>, so you can check if a boolean is defined by checking if \if<name> is defined.

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{etoolbox}

\newcommand*{\ifboolundef}[1]{\ifcsundef{if#1}}

\newcommand*{\sabooleantest}[1]{%
  bool \ttfamily{#1} is
  \ifboolundef{#1}
    {undefined}
    {\ifbool{#1}
       {true}
       {false}}}

\begin{document}
\sabooleantest{flobbel}

\newbool{globbel}
\boolfalse{globbel}
\sabooleantest{globbel}

\newbool{hobbel}
\booltrue{hobbel}
\sabooleantest{hobbel}
\end{document}

bool flobbel is undefined

bool globbel is false

bool hobbel is true

The question is whether you really need something that comes down to a three-valued logic. Is a two-valued boolean not enough?

If you want to avoid problems in case the boolean is undefined, you could just check if a macro is undefined or defined. This also has two states, but unlike with booleans there are no errors if the thing is not defined.

\newcommand*{\mybool}{}
\ifundef{\mybool}
  {not defined}
  {defined}

You could also define 'permissive toggles' that are false if they don't exist

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{etoolbox}

\newcommand*{\permissivetoggletrue}[1]{\csletcs{sa@ptogl@#1}{@empty}}
\newcommand*{\permissivetogglefalse}[1]{\csundef{sa@ptogl@#1}}
\newcommand*{\ifpermissivetoggle}[1]{\ifcsdef{sa@ptogl@#1}}

\begin{document}
flobbel
\ifpermissivetoggle{flobbel}
  {true}
  {false}

\permissivetoggletrue{globbel}
globbel
\ifpermissivetoggle{globbel}
  {true}
  {false}
\end{document}

This can also be done without etoolbox if you like those sort of things

\makeatletter
\newcommand*{\permissivetoggletrue}[1]{%
  \expandafter\let\csname sa@ptogl@#1\endcsname\@empty}
\newcommand*{\permissivetogglefalse}[1]{%
  \expandafter\let\csname sa@ptogl@#1\endcsname\@sa@undef}% this assumes \@sa@undef is undefined
\newcommand*{\ifpermissivetoggle}[1]{%
  \ifcsname sa@ptogl@#1\endcsname
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\makeatother
3
  • I were only using etoolbox for this one thing, so if this package can be avoided, then it would be much appreciated. Commented Aug 16, 2018 at 11:34
  • 3
    @SandraSchlichting Theoretically especially in my last two examples we could do away with etoolbox, but I would end up essentially copying (a bit of) code from that package, so why not load it?
    – moewe
    Commented Aug 16, 2018 at 11:38
  • I see. Good point. Commented Aug 16, 2018 at 11:42
2

It doesn't have to be a boolean, if something else is simpler or doesn't require an extra package.

I think \ifdefined and \def provide what you're looking for. You don't need an extra package or any definition.

In your main document, write

\def\isSingleBook{}

or, alternatively, \newcommand{\isSingleBook}{} or \providecommand{\isSingleBook}{}.

Then you can check with:

\ifdefined\isSingleBook
  %% you're in the book
\else
  %% you're not in the book
\fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .