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.

For writing my own TeX code, grouping (\begingroup, \endgroup) helps on automatically saving and restoring TeX "variables".

(La)TeX "variables" are either macros or registers. The registers can be counters (integers), dimensions, skips (both fractional numbers with units) or read/write handlers etc. Note that you can change them inside a group, i.e. either { .. } or \begingroup ... \endgroup or a LaTeX environment, then their old value is restored at the end of the group automatically. (Martin Scharrer, How to save variables)

On the other hand, grouping is not expandable (since the primitives \begingroup and \endgroup are not expandable).

  1. How is TeX treating grouping? Does TeX only save and restore a specific variable when an assignment to it occurs? It seems when a global assignment (e.g. font assignment: \fontdimen, \hyphenchar, \skewchar; hyphenation assignment: \hyphenation, \patterns; box size assignment: \ht, \dp, \wd; ...) occurs that TeX omits saving and restoring.

  2. (EDIT) Considering a TeX command using 5 to 10 "variables". In other words, it is temporarily assigning different values to them, for example \baselineskip=30pt. Is there any good reason to avoid grouping in this situation? Or should grouping be used here because of above advantage?

share|improve this question
    
Assignments are already non expandable, so it's unclear why "blocking expansion" should be a factor. –  egreg Jan 24 '13 at 17:48
add comment

3 Answers

up vote 4 down vote accepted

Just to add a bit on the other answers and to try and answer the title of the question:

When to use or avoid grouping

As David mentioned it mostly depends on your use case but here are some typical areas where using grouping is advisable:

  1. When setting the \@elt in lists.

    \def\alist{\@elt a\@elt b\@elt c}
    \begingroup
      \let \@elt\@gobble  \alist
    \endgroup
    \begingroup
      \def\@elt#1{-#1- }  \alist
    \endgroup
    
  2. When defining macros that affect paragraph(s) of text.

    \def\startlines{%
    \begingroup
      \obeylines\obeyspaces
      \leavevmode
    }
    \def\endlines{\endgroup}
    
    \startlines
    
    This is a test 
    ...   ......         ....... test and another test
    
    This is a test 
    ...   ......         ....... test and another test
    
    \endlines
    
  3. When you want to split a command into two parts, for example:

     \def\index{\@bsphack\begingroup \@sanitize\@index}
     \def\@index#1{\endgroup\@esphack}
    
  4. When changing catcodes:

      \def\MyCatcodeMagic#1{%
        \begingroup
        \catcode`\ 10 %
        \ifnum \endlinechar<256 %
           ...
        \endgroup
       }
    
  5. In math commands to avoid `leaking out' of style changes

When to avoid grouping is mostly a matter of programming style. Good programming practice dictates that globals are an evil, however, is very hard to achieve this with TeX/LaTeX. The LaTeX source2e tends to use grouping for most of the important macros, even in cases such as:

       \def\frac#1#2{{\begingroup#1\endgroup\over#2}}

Can you guess why?

share|improve this answer
    
I think the grouping at \frac prevents usage mistakes and, hence, unexpected output. If the second { } group or the \begingroup - \endgroup group is missing, one can use $\frac{\mathtt}{2}$ or $\frac{1}{1\mathtt}=1$ without getting an error message about the missing argument to \mathtt. –  e-birk Jan 25 '13 at 23:01
add comment

Some assignments do not respect grouping:

\hyphenation{<words>}
\patterns{<balanced tokens>}
\batchmode|\nonstopmode|\scrollmode|\errorstopmode|\interactionmode=<2 bit number

\hyphenchar<font>=<number>
\skewchar<font>=<number>
\spacefactor|\prevgraf|\deadcycles|\insertpenalties=<number>

Box dimension setting is special. When TeX acts on a box register it does respect grouping, but with respect to the last incarnation of the box. Example:

\setbox0=\hbox{\hskip 10pt}{\wd0=0pt}

will result in box 0 having width 0pt even if the assignment has been performed on a group. To the contrary,

\setbox0=\hbox{\hskip 10pt}{\setbox0=\hbox{def}\wd0=0pt}

will result in box register 0 having width 10pt, as it's readily verifiable.

This is similar to what happens when a box register is used:

\setbox0=\hbox{abc}{\box0}

will result in printing abc and the box register 0 to be empty also after closing the group. With

\setbox0=\hbox{abc}{\setbox0=\hbox{def}\box0}

"def" will be printed and the box register 0 will contain \hbox{abc} after closing the group.

Another special case is that of font loading: if one says

{\font\foo=somefont}

then \foo won't be accessible outside the group, but the font information will already have been stored in the font memory and not released.


What values does TeX store in the stack? Only those that are changed inside a group. There is the risk that the stack is exhausted when doing local assignments, but modern TeX implementations reserve at least 50000 words of stack memory, which is sufficient for most applications, provided programming is good, in the sense that the same "variable" is always acted upon locally or globally (so the save stack doesn't retain values it cannot release back).

Every environment in LaTeX forms a group, with the exception of the document environment: it would be absurd to do every assignment in the document proper inside a group, with nefarious effects on the save stack. But, apart from very special applications, it's quite difficult to imagine exhausting the save size.

Working with groups is in many cases easier, because it doesn't require storing the values to put back at the end. As to expandability, no assignment is expandable, so the fact that { and } or \begingroup and \endgroup are not expandable is completely irrelevant for the discussion.

So, if you have to completely change the \lccode vector for the whole Unicode range (in XeTeX or LuaTeX), then don't do it in a group, since you'd be doing 2^21 assignments. If you have to keep something into memory till the end of processing, then use global assignments that will survive the group structure and not pollute the save stack. If you want to change the margins for a list environment, use the already provided group structure.

share|improve this answer
add comment

For any non-global assignment TeX saves the old value on the "save stack" and restores it at the end of the current group. You can see how much save stack you have used in the log file

23i,4n,21p,148b,149s stack positions out of 5000i,500n,10000p,200000b,50000s
                 ^^^                                                  ^^^^^^

Your second question isn't clear, no assignment is expandable \let \def and register assignments are all non-expandable operations


The question about whether to use grouping or not isn't really answerable in that generality, whether or not you use a group depends mostly on whether you want to use a group or not, not on the details of which assignments are made.

In

\begin{empty}
....
\end{empty}

For environment is implemented by \empty which expands to nothing so doesn't do any assignments but the fact that the environment is a group means that any user code that goes in the ... is scoped by the group.

One time that I have needed to use global assignments and explicitly save and restore values in a privately implemented stack at the macro layer rather than use TeX grouping is in blockarray where the syntax

\begin{block}
....

\end{block}

is used but in reality the begin and end code are in different table cells so in different groups, unlike a real environment there is no group that starts at the beginning of the block and ends at the end. The comments in the code say

 \subsection{`Local' Variables}

 Most of {\tt blockarray} happens inside a "\halign" which means that
 the different parts have to make global assignments if they need to
 communicate. However many of these assignments are logically local to
 {\tt blockarray}, or a sub-environment like {\tt block}. This means
 that I have to manage the saving and restoring of local values `by
 hand'.

 Three different mechanisms occurred to me, I have used all of them in
 this style, mainly just to try them out!

You can look at the blockarray package document ion for the gory details.

share|improve this answer
    
Please see EDIT for my second question. I see now, expansion cannot be a reason. Can there be any different reason to avoid grouping except using too much stack? –  e-birk Jan 24 '13 at 18:41
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.