21

I see the code

\begingroup\edef\x{\endgroup

in the answer to this question.

I want to understand the purpose of this method. In which cases should it be used?

Alain Matthes
  • 95,075

3 Answers3

23

The idea here is to carry out \edef expansion using a macro (\x) which we don't want to change 'elsewhere': you never know who else might be using \x. So the definition of \x needs to be done inside a group. The aim is then to get the result of the \edef outside of the group without making any assumptions about the number of tokens it contains. The \begingroup and \endgroup primitives are not expandable, and so

\edef\x{%
  \endgroup
  <tokens>%
}

defines \x as

> \x=macro:
->\endgroup <expansion of tokens> .

The end of the 'magic' construction is then just \x:

\begingroup
\edef\x{%
  \endgroup
  ....
 }\x

This inserts the definition of \x into the input stream. The first token of that is \endgroup, which therefore restores the previous definition of \x before the expanded tokens. So the net result is to carry out the expansion without affecting \x at all. (\x is 'traditionally' used here, but any macro name will of course work.)

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
12

The usage is usually \begingroup\edef\x{\endgroup<code>}\x. This fully expands the <code> (normally some parts are protected using \noexpand) and then processes it. The \begingroup and \endgroup keep the definition of \x local, i.e. afterwards the previous definition of \x is still in effect. So \x is simply used as temporary storage.

Mico
  • 506,678
Martin Scharrer
  • 262,582
  • If you could add some explanation on the finer scoping issues involved the answer would get even better. For instance, if some <code1> is inserted before \edef then it can do some local assignments inside the group which are accessible inside <code>. But assignments inside of <code> will be local outside the group. – Stephan Lehmke Jun 26 '12 at 11:19
11

if you have something like

\def\XXX#1#2{%
  \begingroup
    % replace with some other important local code
    \global#2=#1
  \endgroup
}

then \XXX{1.1pt}\bar will set \bar globally to the value of 1.1pt. Sometimes it makes more sense to set the value inside the current group and not globally, but some other code needs still to be inside a deeper group then you can do

\def\YYY#1#2{%
  \begingroup
    % replace with some other important local code
    \edef\x{\endgroup\noexpand#2\number#1}\x
} 

Now \YYY{1.1pt}\bar will set \bar not globally to the value of 1.1pt and the % replace with some other important local code part is still hold local.