[Tex/LaTex] A more elegant version of the \ifnot macro

funmacrosprogrammingtex-core

A TUGboat article of 15 years ago mentions an \ifnot macro by David Kastrup whose implementation is:

\def\ifnot#1{#1\else
    \expandafter\expandafter\fi
    \iffalse\iftrue\fi}

However, this macro looks a bit weird when it is applied to an \ifSomething macro, i.e., \ifnot{\ifeof\stream}. For the purpose of making TeX code a bit more readable, it might be useful to have a macro which negates the "condition" itself, without the if prefix.

Here is a minimal example, which does not work.

\documentclass{standalone}
\makeatletter
\newif\if@to@be
\begin{document}
  \@to@be@true
  \if@not\@to@be@ Not to be! \fi
  \@to@be@false
  \if@not\@to@be@ Not to be! \fi
\end{document}

Best Answer

Possibly something like this? It preserves the OP's desired syntax \ifnot\tobe, while at the same time not demanding that \tobe be predefined. Additionally, for those who don't like using \tobe without defining it, it allows the alternate syntax \ifnot{tobe}, without any changes whatsoever.

\documentclass{article}
\makeatletter
% Following 3 lines thanks to Prof. Enrico Gregorio, from:
% http://tex.stackexchange.com/questions/42318/
% removing-a-backslash-from-a-character-sequence
\begingroup\lccode`\|=`\\
\lowercase{\endgroup\def\removebs#1{\if#1|\else#1\fi}}
\newcommand{\@macro@name}[1]{\expandafter\removebs\string#1}
%
\def\ifnot#1{%
  \edef\tmp{if\@macro@name{#1}}%
  \csname\tmp\endcsname\else
    \expandafter\expandafter\fi
    \iffalse\iftrue\fi}
\makeatother
\newif\iftobe
\begin{document}
  \tobetrue
  \ifnot\tobe Not to be! \else To be!\fi\par
  \tobefalse
  \ifnot\tobe Not to be! \else To be!\fi
\end{document}

enter image description here

Related Question