# Setting catcodes in a group

Can someone explain to my why \foo and \bar are not the same (in the \ifx sense) in this example:

\documentclass{article}
\begingroup
\catcode|=3\relax
\gdef\abc{|}
\endgroup
\makeatletter
\newcommand\foobar{
\begingroup
\catcode|=3\relax
\def\abc{|}
\@foobar
}
\newcommand\@foobar[1]{
\xdef\foo{#1}
\endgroup
}
\edef\bar{\abc}
\foobar{\abc}

\begin{document}
foo means \meaning\foo'' and bar means \meaning\bar'', but the meanings'' are
\ifx\foo\bar
same
\else
different
\fi
\end{document}


I included the \@foobar because I read somewhere that the catcode had to be changed before reading the macro parameter (I don't think it applies here, but I have no idea what I am doing).

The global definition of \abc (the one defined with \gdef) is | with catcode 3. I would like the local definition of \abc (the one defined with \def) to also be | with catcode 3. In my example the local \abc is | with catcode 12. Ultimately I would like to have \foobar{\abc} expand to | with catcode 3 without having \abc defined golbally.

-
You say you want to avoid the global definition of \abc but what do you want to define it to be? How do you want to use it? If you edit your question to give some higher level requirements, someone could suggest some code that would help – David Carlisle Mar 8 '12 at 17:04
@DavidCarlisle I tried to clarify the question. I hope it helps. – StrongBad Mar 8 '12 at 17:46
OK I added some code to my answer – David Carlisle Mar 8 '12 at 17:55

## 3 Answers

The problem lies here:

\newcommand\foobar{
\begingroup
\catcode|=3\relax
\def\abc{|}
\@foobar
}


The \def\abc{|} is read by \newcommand and its catcodes are fixed then. The \catcode|=3\relaxis executed when the\foobar macro is used not when it is defined.

You can use the following instead:

\begingroup
\newcommand\foobar{}% to get the name check
\catcode\|=3\relax
\gdef\foobar{%
\begingroup
\catcode\|=3\relax
\def\abc{|}%
\@foobar
}
\endgroup


This changes the catcode of | to 3 also for the definition. You onlt need to use \@foobar if the user should be allowed to add | with catcode 3 inside the argument. Otherwise you simply let \foobar read the argument and use \xdef\foo{#1} inside \foobar directly. Then you don't need the second, inner\catcode\|=3\relax line as well.

Also, you should place % at lines ending with { or } because otherwise the source code line breaks will be taken as a space which are inserted in the document.

-
I think there is an extra \begingroup in the definition of \foobar (left over from my awful example). I am not so confident to actually edit your answer. – StrongBad Mar 8 '12 at 17:49
@DanielE.Shub: No, I don't think so. The closing \endgroup is inside \@foobar. Keep in mind that the outer grouping commands are executed during the definition but the inner ones during the usage of the macro. – Martin Scharrer Mar 8 '12 at 18:22

I have no idea what you want to achieve. But the catcode of an input is assigned at the moment when TeX reads the input the first time. When the definition body of foobar is read the catcode of | is "other" and so your \foobar will always define "\abc = | with catcode other", regardless of the catcode value when you actually execute \foobar.

If you want to change the catcode of an input you can do it e.g. by writing it to an external file and then reinput it or by using \scantokens.

-

They are different because one holds a math-shift character and the other holds a punctuation character (catcodes 3 and 12) you can see this if you typeset

foo \foo 1*2*3 \foo

bar \bar 1*2*3 \bar


You can locally define \abc to be a \catcode 3 | with various idioms for example this one is used all over the place (usually with ~ to get an active character rather than $) for example the definition of \verb in latex.ltx. \begingroup\lccode$=\|\lowercase{\endgroup\def\abc{\$}}


defines \abc to be a math-shift |` without any global definition.

-