My first bet would be on
\newcommand\createrefmacro[1]{%
\expandafter\newcommand\csname ref#1\endcsname[2][]{#1~\ref{##2}}}
If I load xpatch
for looking at the real meaning of \refFigure
after
\createrefmacro{Figure}
I get the following answer:
> \\refFigure=\long macro:
[#1]#2->Figure~\ref {#2}.
that is exactly what you wish to obtain with the (non working) code you proposed. A working version would be
\makeatletter
\def\createrefmacro#1{%
\expandafter\def\csname ref#1\expandafter\endcsname\expandafter{%
\expandafter\@testopt\csname ref#1@i\endcsname{}%
}%
\expandafter\def\csname ref#1@i\endcsname[##1]##2{#1~\ref{##2}}%
}
\makeatother
In this way \createrefmacro
would first execute
\expandafter\def\csname refFigure\expandafter\endcsname\expandafter{\expandafter\@testopt\csname refFigure@i\endcsname{}}
where the \expandafter
at the end of the first \csname...\endcsname
pair would trigger the formation of the token \refFigure@i
and so this would bring you
\def\refFigure{\@testopt\refFigure@i{}}
Then
\expandafter\def\csname refFigure@i\endcsname[#1]#2{Figure~\ref{#2}}
would be equivalent to
\def\refFigure@i[#1]#2{Figure~\ref{#2}}
But the first solution is obviously cleaner.
Analysis
Let's see where your code fails:
\def\createrefmacro#1{%
\edef\macro{\csname ref#1\endcsname}%
\edef\macro@i{\csname ref#1@i\endcsname}%
\expandafter\gdef\macro{%
\expandafter\@testopt\macro@i{}%
}%
\expandafter\gdef\macro@i[##1]##2{#1~\ref{##2}}%
}
First of all, \gdef
is useless, as probably you won't issue \createrefmacro
inside a group, but it does no harm. Assume that you give
\createrefmacro{Figure}
Then
\edef\macro{\csname refFigure\endcsname}
will be equivalent to
\def\macro{\refFigure}
(because \refFigure
is still undefined, so it will be equivalent to \relax
and stop expansion). Similarly
\edef\macro@i{\csname refFigure@i\endcsname}
will be the same as
\def\macro@i{\refFigure@i}
Now TeX will see
\expandafter\gdef\macro{\expandafter\@testopt\macro@i{}}
that would become
\gdef\refFigure{\expandafter\@testopt\macro@i{}}
and here is the main problem: the \expandafter
will not come into action. So, with a subsequent \createrefmacro{Table}
, the meaning of \macro@i
would be \refTable@i
! There is a possibility with \expandafter
, let's look at it:
\expandafter\expandafter\expandafter\gdef\expandafter\macro\expandafter{%
\expandafter\@testopt\macro@i{}}
Can you see it? The first \expandafter
will expand the third, thus the fourth, the fifth and the sixth, leaving
\expandafter\gdef\macro{\@testopt\refFigure@i{}}
which eventually becomes
\gdef\refFigure{\@testopt\refFigure@i{}}
as desired. The last job would become
\expandafter\gdef\macro@i[#1]#2{Figure~\ref{#2}}
(because #1
is replaced by Figure
and ##
becomes #
), so this would do the correct
\gdef\refFigure@i[#1]#2{Figure~\ref{#2}}
Of course, what #1
should do remains unexplained in your code (but you did say this). However, using directly \csname...\endcsname
is much handier and doesn't require \macro
and \macro@i
.
Best Answer
The error message you mention is triggered by a missing closing brace in
\dfrac
(or one of its variants), as the following simple example illustrates:Processing the above document yields
The solution is to add the missing brace: