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.

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]?
share|improve this question
4  
This may help: tex.stackexchange.com/questions/8351/… –  Andrey Vihrov Sep 7 '11 at 19:56
add comment

3 Answers

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.

share|improve this answer
    
Beautifully explained. I've learned a lot from this essay! –  Mico Sep 7 '11 at 21:25
    
Thanks Joseph for the wonderfully detailed answer !! I needed a paradigm shift and I think I have it now.. –  Abhinav Sep 8 '11 at 6:20
add comment

Although this does not answer your bullets in order, it does provides some guidance as to what's going on with the code [1]-[4] you presented.

@ in LaTeX is a reserved symbol, and therefore not treated in the same way as other letters are. Executing \makeatletter reverses this reservation, "making @ a letter", so it can be used in regular variables. Of course, \makeatother restores this change. Therefore \newif\if@addpoints specifies a new boolean called @addpoints. Executing \@addpointstrue/\@addpointsfalse sets it to true/false.

In a similar sense \newif\ifcancelspace provides a boolean cancelspace that can be modified in a similar way (\cancelspacetrue or \cancelspacefalse). I think the motivation behind using @ in variables adds a depth-layer to the macro-programmer. For example, it allows the programmer to (say) prefix all variables with a package name using something like \newif\myfunc@dothis. If dothis was a very common yet descriptive variable, other packages may conflict with such a redefinition. However, with the prefix this is avoided. So, in some sense, with a multitude of packages out there and very different programming styles (and use of variables/macros) it is good programming practice to add this layer of specificity.

The default scope of variables in LaTeX is local to the group within which they are declared/modified. Prefixing an assignment with \global makes the change global and therefore exist outside the group that the assignment was made. For example, consider \def\addpoints{\global\@addpointstrue}. This defines a macro called \addpoints (by means of using \def, and the macro executes \global\@addpointstrue. From the above discussion it should be clear that this sets the boolean @addpoints to true. However, since the macro definition is encompassed by braces { }, it defines a group that starts with { and ends with }. Any changes/assignments made within this group is void outside of it. Since you used \global, this overrides the scope to extend beyond the group. That is, \@addpointstrue is not "made global". Instead, the scope of the modification is extended globally.

Specific to the last bullet: \newif\@addpoints is the definition of the boolean @addpoints, while \global adjusts the scope (as mentioned before). From a programming point of view, the use of global may be relevant at variable declaration. However, in LaTeX that is not exclusively the case. It can, in fact, be used at variable declaration (in order to make the declaration global like in \global\def\mycommand{...}, which is equivalent to \gdef\mycommand{...}, by the way) or during some variable modification.

share|improve this answer
4  
The \global is not used to escape from the group created by \def (this is not a group in that sense, but a definition extent), but to escape from groups at point-of-use. –  Joseph Wright Sep 7 '11 at 20:20
add comment

The @ symbol is frequently (though not exclusively) used in LaTeX as a "special character", meaning (mostly) that any macros that incorporate commands that include this character have to be in a "special mode" (OK, this is starting to sound circular!) in order to work. The "special mode" is entered with the command \makeatletter and is exited with the command \makeatother. The LaTeX kernel and many LaTeX packages define commands for internal use that should not ever be accessed directly in ordinary programming, i.e., by users. To help avoid accidental use of these internal commands, they're often given one or more @ symbols; the theory is that for a user to access such commands, they have to explicitly provide the command \makeatletter before they can do so, in which case (so the theory goes) they know what they're doing...

The examples you provide are illustrative of this point: The instruction \newif\if@addpoints creates a boolean variable named, what else, @addpoints; this is an internal variable and should (in general) not be manipulated directly; its default value is "false" by the statement \@addpointsfalse. The command \addpoints, on the other hand, is a user-level command which lets you change the state of this variable to "true".

Of course, this programming convention isn't entirely bullet-proof, but experience has shown that code that follows this convention is a lot more robust.

share|improve this answer
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.