# What is Algorithm2e's problem with the letter Q?

No, seriously.

The following LaTeX document is typeset with no issues:

\documentclass{article}
\usepackage{algorithm2e}

\begin{document}

\begin{minipage}{\textwidth}
\begin{algorithm}[H]
\Begin(F){
}
\end{algorithm}
\end{minipage}

\end{document}


I'd like to focus on the \Begin(F) line. Here are the results of my experiments:

1. If I replace it with \Begin(Q), there are no problems.

2. If I replace it with \Begin([x]), there are still no problems.

3. If I replace it with \Begin([Q]), however, weird things happen. I end up with an algorithm starting with beginQ [Q], as in this screenshot:

4. If I replace it with \Begin($[Q]$), pdflatex starts complaining and doesn't know how to typeset the document.

5. If I replace it with \Begin($[x,Q]$) pdflatex still fails.

6. If I replace it with \Begin($[Q,x,r]$), pdflatex produces an algorithm starting with beginx [Q,x,r].

None of these issues arise if I use a letter other than Q. What on earth is happening?

Edit: I use TeX Live 2013 and the lastest version (2013/01/06 v5.00) of algorithm2e.

-
Qriouser and Qriouser... Could you edit your question to add a screenshot of the output? – Jubobs May 18 '14 at 18:15
@Jubobs, there you go. – ymbirtt May 18 '14 at 18:26

I just had a look at the algorithm2e source code. The behaviour you report can be traced to the definition of a macro called \ifArgumentEmpty (defined in algorithm2e.sty), which changes (or, rather, attempts to change) the catcode of the uppercase letter Q:

\long\def\ifArgumentEmpty#1{\bgroup
\catcode\Q=3
\catcode\T=3
\long\def\@tempa##1##2Q##3##4##5T{##4}%
\xdef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
\egroup\@tempa}


If you change the definition of that macro by replacing all instances of Q by another character (A in my code below), the problem will then occur with that other character but no longer with the letter Q.

I'm not familiar enough with the algorithm2e source code to come up with anything better than this explanation. You should probably get in touch with the maintainer about this issue with Q.

\documentclass{article}
\usepackage{algorithm2e}

\makeatletter
\long\def\ifArgumentEmpty#1{\bgroup
\catcode\A=3
\catcode\B=3
\long\def\@tempa##1##2A##3##4##5B{##4}%
\xdef\@tempa{\@tempa#1AA{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}B}%
\egroup\@tempa}
\makeatother

\begin{document}

\begin{minipage}{\textwidth}
\begin{algorithm}[H]
\Begin([A]){
}
\end{algorithm}
\begin{algorithm}[H]
\Begin([Q]){
}
\end{algorithm}
\end{minipage}

\end{document}

-

As Jubobs correctly diagnosed, the problem is in \ifArgumentEmpty. Credits for pinpointing the issue should go to him. Here's an analysis of the problem and a couple of workarounds.

Let's see what \ifArgumentEmpty should do, at least in the intentions of the package author. The argument is absorbed and a temporary macro is defined:

\long\def\@tempa#1#2Q#3#4#5T{#4}


The # becomes ## because we're in a definition. Then the argument to \ifArgumentEmpty is passed to

\xdef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}


Note that #1 will be what's inside the pair of parentheses when \Begin is involved. So, let's see the case when the argument is empty or just spaces (spaces will be ignored because the first argument to \@tempa is undelimited).

If #1 is empty, TeX sees

\@tempa QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T


so the first argument to \@tempa is Q, the second argument is empty, the third argument is \noexpand\@secondoftwo and the fourth argument is \noexpand\@firstoftwo; the fifth argument is empty.

If #1 is nonempty, its first token is the first argument to \@tempa, the (possibly zero) remaining tokens are the second argument, the third argument is Q, the fourth argument is \noexpand\@secondoftwo and the fifth one is \noexpand\@firstoftwo.

So \@tempa is expanded, leaving \noexpand\@firstoftwo in the empty case, \noexpand\@secondoftwo in the nonempty case.

This in theory; the change of the category code of Q and T should ensure that these tokens are not contained in the argument to \ifArgumentEmpty. But in this code they don't have category code 3 as the programmer thinks. The category code is fixed at the moment of the definition and when the macro is defined the two tokens are letters. The instructions \catcodeQ=3 and \catcodeT=3 simply do nothing.

Let's see what happens when the argument is [Q]: TeX sees

\@tempa [Q]QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T


The first argument to \@tempa is [; the second argument is empty, the third argument is ], the fourth argument is Q and the fifth argument is all that remains up to T. Thus \@tempa is defined to be Q and the second and third (apparent) arguments to \ifArgumentEmpty also remain in the input stream, because there's no \@firstoftwo or \@secondoftwo that takes care of them.

The same problem arises whenever the second token of the argument to \ifArgumentEmpty is Q.

Here's a correct definition:

\makeatletter
\begingroup
\catcode\Q=3
\catcode\T=3
\long\gdef\ifArgumentEmpty#1{%
\long\def\@tempa##1##2Q##3##4##5T{##4}%
\edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
\@tempa
}
\endgroup
\makeatother


There's no need of a group inside the macro, nor of \xdef.

Note that we have to use \gdef for defining \ifArgumentEmpty, in order to localize the change in category codes.

Test example.

\documentclass{article}
\usepackage{algorithm2e}

\begin{document}

\textbf{Original definition}

Empty: \ifArgumentEmpty{}{Empty}{Non empty}

Spaces: \ifArgumentEmpty{ }{Empty}{Non empty}

ABC: \ifArgumentEmpty{ABC}{Empty}{Non empty}

Q: \ifArgumentEmpty{Q}{Empty}{Non empty}

[Q]: \ifArgumentEmpty{[Q]}{Empty}{Non empty}

\bigskip

\makeatletter
\begingroup
\catcode\Q=3
\catcode\T=3
\long\gdef\ifArgumentEmpty#1{%
\long\def\@tempa##1##2Q##3##4##5T{##4}%
\edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
\@tempa
}
\endgroup
\makeatother

\textbf{Fixed definition}

Empty: \ifArgumentEmpty{}{Empty}{Non empty}

Spaces: \ifArgumentEmpty{ }{Empty}{Non empty}

ABC: \ifArgumentEmpty{ABC}{Empty}{Non empty}

Q: \ifArgumentEmpty{Q}{Empty}{Non empty}

[Q]: \ifArgumentEmpty{[Q]}{Empty}{Non empty}

\end{document}


Note that in the [Q] line with the original definition the result is what I predicted: Q is typeset and then also Empty and Non empty. This also proves, if still not clear, that the Q in the parameter text of \@tempa doesn't have category code 3.

## Workarounds

File a bug report and do, until a fix is issued,

\usepackage{algorithm2e}
\makeatletter
\begingroup
\catcode\Q=3
\catcode\T=3
\long\gdef\ifArgumentEmpty#1{%
\long\def\@tempa##1##2Q##3##4##5T{##4}%
\long\edef\@tempa{\@tempa#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T}%
\@tempa
}
\endgroup
\makeatother


An easier workaround is to say

\usepackage{algorithm2e}
\usepackage{etoolbox}
\let\ifArgumentEmpty\ifblank


A possibly better fix to suggest to the package developer:

\makeatletter
\begingroup
\catcode\Q=3
\catcode\T=3
\long\gdef\ALGOCF@argemptyaux#1#2Q#3#4#5T{#4}
\long\gdef\ifArgumentEmpty#1{%
\begingroup\long\edef\@tempa{\endgroup
\ALGOCF@argemptyaux#1QQ{\noexpand\@secondoftwo}{\noexpand\@firstoftwo}T%
}\@tempa
}
\endgroup
\makeatother


The auxiliary macro is defined once for all, since it's going to always receive the same definition; with the

\begingroup\edef\@tempa{\endgroup...}\@tempa


trick, \@tempa is only set temporarily and doesn't pollute the hash memory. No global definition necessary.

-
The cavalry has arrived! :) – Jubobs May 18 '14 at 21:39
@Jubobs Just in time: Mrs. Mallory is praying, Hatfield has been killed a moment before killing her with his last bullet; Ringo Kid and the marshal don't have any more shells. Buck and Mr. Peacock are wounded, Dallas is keeping care of the baby and Mr. Gatewood does nothing. Doc Boone drinks. ;-) – egreg May 18 '14 at 21:51
Your detective work is worthy of a bounty. The root of the problem is definitely a recurring misunderstanding: so many TeX users (incl. I) misunderstand/overlook that "TeX absorbs tokens and catcode assignments are permanent"... – Jubobs May 18 '14 at 21:53
Alas, I'm not well versed in Western movies. I had to look up the Stagecoach reference... I might give it a shot (pun intended). A more recent one I can recommend is True Grit (2010). – Jubobs May 18 '14 at 21:56
@Jubobs Would you compare True Grit (2010) with the true True Grit (1969)? I definitely wouldn't (putting off my hat, because John Wayne has been evoked twice). ;-) – egreg May 18 '14 at 22:00