# loop macro fails if wrapped in conditional

The following code is a subset of the answer in this question. The code provided in the answer works fine, but fails if I add a conditional \IfPackageLoaded. I post this error as a new question, because it has not necessarily to do with the original question.

The problem has to do with the sequence \xpretobibmacro although I have no idea why. The failure message is below.

\documentclass{article}

\usepackage{filecontents}
\usepackage{ltxcmds}
\makeatletter
\makeatother

\usepackage{biblatex}
\usepackage{xpatch}

% \boldnames: etoolbox-list of names to typeset bold in \printbibiliography
\newcommand*{\boldnames}{}

\newbibmacro*{name:bold}[2]{%
\def\do##1{\ifstrequal{#1, #2}{##1}{\bfseries\listbreak}{}}%
\dolistloop{\boldnames}}

\xpretobibmacro{name:last-first}{\begingroup\usebibmacro{name:bold}{#1}{#2}}{}{}
\xapptobibmacro{name:last-first}{\endgroup}{}{}

%
\DeclareNameAlias{default}{last-first/first-last}

\begin{document}

\begin{filecontents*}{publications.bib}
@Article{Pospiech2010,
Title                    = {Single-sweep laser writing of 3D-waveguide devices},
Author                   = {Matthias Pospiech and Moritz Emons and Benjamin V\"{a}ckenstedt and Guido Palmer and Uwe Morgner},
Journal                  = {Opt. Express},
Year                     = {2010},
Number                   = {7},
Pages                    = {6994--7001},
Volume                   = {18},
}
\end{filecontents*}

\begin{refsection}%
\nocite{*}
\end{refsection}

\end{document}


The error is

! Undefined control sequence.
<argument> \blx@do
{Pospiech2009}\blx@listloop@i


When using xpatch (or the original commands in etoolbox) for patching macros, it's recommended to use the builtin diagnostics, that is \tracingpatches and the “fail” argument.

If you add \tracingpatches to the preamble, before your usage of \IfPackageLoaded, you'll get the message

[debug] tracing \pretocmd on input line 26
[debug] analyzing '\abx@macro@name:last-first'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] ++ control sequence is a macro with parameters
[debug] -- nested patching command and parameters in patch
[debug] -> the patching command seems to be nested in the
[debug]    argument to some other command
[debug] -> the patch text seems to contain # characters
[debug] -> either avoid nesting or use # characters with
[debug]    category code 12 in the patch text
[debug] -> simply doubling the # characters will not work


and if you add \ddt to the “fail” argument (or any undefined control sequence), TeX will stop, meaning that the patch has failed. The message explains what goes wrong: one can't use the # token in the arguments of \patchcmd, \pretocmd or \apptocmd and the derived xpatch commands when the patching appears in the argument to another command, in this case \IfPackageLoaded.

In this case etoolbox suggests a workaround: use # with category code 12:

\IfPackageLoaded{biblatex}{%
% \boldnames: etoolbox-list of names to typeset bold in \printbibiliography
\newcommand*{\boldnames}{}
\newbibmacro*{name:bold}[2]{%
\def\do##1{\ifstrequal{#1, #2}{##1}{\bfseries\listbreak}{}}%
\dolistloop{\boldnames}}
\begingroup\lccode~=#\lowercase{\endgroup
\xpretobibmacro{name:last-first}{\begingroup\usebibmacro{name:bold}{?1}{?2}}{}{}%
}
\xapptobibmacro{name:last-first}{\endgroup}{}{}
%
\DeclareNameAlias{default}{last-first/first-last}
}


Using the \lowercase trick works because, happily, all the character tokens in the arguments to \xpretobibmacro command are lowercase. Uppercase characters would need appropriate declarations such as

\lccodeA=A


next to \lccode?=#.

By the way, I find misnamed the \IfPackageLoaded command: All \@if... or \If... commands I know of have arguments both for the “true” and “false” cases. Probably \DoIfPackageLoaded would be a better name.

• Thanks, it works now. BTW: My package templatetools defines several commands that work that way. – Matthias Pospiech Jul 6 '14 at 12:42
• @MatthiasPospiech You're not giving users the chance of doing "something else" if the package is not loaded. – egreg Jul 6 '14 at 13:00