[Tex/LaTex] When to use @ in an \if statement

conditionalsgroupingmacrosprogramming

I am new to LaTeX and so this question might come across as rather basic.
It might also reflect my biases/assumptions from my C/C++ programming days.

I was seeing the code of the 'exam' class and noticed that some \if<xyz>
had an @ while others didn't.

For example, below are a few lines of code from the class file (in order of appearance/execution)

  1. \newif\ifcancelspace
  2. \newif\if@addpoints
  3. \def\addpoints{\global\@addpointstrue}
  4. \@addpointsfalse

I can't understand the following:

  • Is the \if@addpoints in [2] evaluated (when it appears) using the value of @addpoints (declared in [4])

  • Is there a significance to prepending an @ to addpoints above?

    • Is it just good programming practice for naming variables in class/package files?
    • Or, was it necessary because there is another \def\addpoints in [3]
      and the @ was required to differentiate between the two?
  • What is the default scope for variables in LaTeX?

  • How can @addpoints be made global in [3] when it is not defined until [4]?

Best Answer

This question is about several things at once, which makes answering it somewhat interesting. others have taken one tack, I'll take a different one.

First, bear in mind that TeX is a macro expansion language, not a functional language. Secondly, note that TeX has very few built-in variable types. A lot of 'variables' are therefore macros with appropriate structure.

The \newif macro creates three new macros from the argument \if<name>:

  • \if<name>, a switch to be used in tests;
  • \<name>true, which sets the switch logically true;
  • \<name>false, which sets the switch logically false;

Typically, the \if<name> here is something like \if@myswitch or \ifmy@switch. Other answers have mentioned that @ here is a 'letter', which is used to namespace TeX macros. Thus the @ has no special meaning to TeX: it's there for the programmer. (The usual pattern is to use @ to make the names easier to read, so \if@<package>@<meaning> or \if<package>@<meaning> are common.)

So analysising the question, the two lines \newif\ifcancelspace and \newif\if@addpoints create the macros

  • \ifcancelspace
  • \cancelspacetrue
  • \cancelspacefalse
  • \if@addpoints
  • \@addpointstrue
  • \@addpointsfalse

The two switches can now be used in a constructions

\if@addpoints % or \ifcancelspace
  % Do stuff
\else
  % Do other stuff
\fi

Taking point [4] next, the macro \@addpointsfalse sets the \if@addpoints switch to logically false. So it means my test above would 'do other stuff'. Setting \@addpointstrue would mean that the test would 'do stuff'.

The last point to deal with is [3], for which you need to understand grouping in TeX, macro expansion and how the switches actually work. As TeX is a macro language, it does not have a concept of a variable being used 'within' a function. Thus groups are created by the constructs

{ ... }

or

\begingroup ... \endgroup

(A brace group is also used in places where TeX 'expects' grouping, and so it effectively disappears. That is the case, for example, with the group needed to use \def.)

An assignment will be trapped within such as group unless it made globally. Now, the definition \def\addpoints{\global\@addpointstrue} means that where we use \addpoints, TeX will replace it with \global\@addpointstrue (macro expansion). We'll come back to \global in a bit, but first note that \@addpointsture is a macro which expands to

\let\if@addpoints\iftrue

This is an assignment, and normally applies only within the current TeX group level. However, the \global prefix means that the assignment ignores grouping. So the result is that \addpoints will globally set the switch \if@addpoints to logically true.

Related Question