How to compare first letter of a word with other char both defined in macros (case-insensitively)?

The following MWE shows that how I get the first letter of a word and compare it with other character both defined in macros. In my case I need to perform it case-insensitively so I used \uppercase to make both characters uppercase; the latter one is uppercase too.

\documentclass{article}

\def\firstletter#1{\expandafter\justfirst#1\relax}
\def\justfirst#1#2\relax{#1}

\begin{document}
\def\data{abcde}
\uppercase{\edef\letter{\firstletter{\data}}}%
\def\A{A}
\ifx\A\letter Equal\else Not Equal\fi
\end{document}


I don't know why it doesn't work as I was expected! (getting Equal not Not Equal).

\uppercase doesn't expand the contents of its argument, so there's nothing there to be uppercased as far as it is concerned.

A couple of various possibilities to fix it:

\edef\letter{\firstletter{\data}}%
\uppercase\expandafter{\expandafter\edef\expandafter\letter\expandafter{\letter}}%


Or:

\edef\tmpa{\uppercase{\edef\noexpand\letter{\firstletter{\data}}}}%
\tmpa


There are probably other alternatives as well.

• Thanks, but why can't we use something like \edef\letter{\uppercase{\edef\noexpand\letter{\firstletter{\data}}}}? I mean without using any temporary macro, just expanding the original one. Dec 9 '17 at 7:25
• @javadr — write \show\letter to see why. \uppercase doesn't expand, so the temporary macro needs to be executed for \uppercase to finally perform its duty. Dec 10 '17 at 11:22

Assuming only string data (all macros to be tested expand to characters), you can do by switching arguments around. This assumes the first argument to \firstletterequalTF does not expand to an empty list.

\documentclass{article}

\makeatletter
\newcommand{\firstletterequalTF}[2]{% both can be macros
\expandafter\fle@i#1\@nil{#2}%
}
\def\fle@i#1#2\@nil#3{%
\expandafter\fle@ii\expandafter{#3}{#1}%
}
\def\fle@ii#1#2{%
\uppercase{\if#1#2}%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother

\newcommand\dataa{abcde}
\newcommand\dataA{Abcde}
\newcommand\datab{bcde}
\newcommand\fixedA{A}

\begin{document}

\firstletterequalTF{abcde}{A}{Equal}{Not Equal} /
\firstletterequalTF{\dataa}{A}{Equal}{Not Equal} /
\firstletterequalTF{abcde}{\fixedA}{Equal}{Not Equal} /
\firstletterequalTF{\dataa}{\fixedA}{Equal}{Not Equal}

\firstletterequalTF{\dataA}{\fixedA}{Equal}{Not Equal}

\firstletterequalTF{\datab}{\fixedA}{Equal}{Not Equal}

\end{document}


An implementation in expl3, where the ability to expandably compare strings is exploited, note the last command that shows that, contrary to macros using \uppercase, the function is expandable. Empty strings are not of a concern.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

{
% compare the two strings after full expansion:
% extract the first item from the the first string and uppercase it;
% uppercase the second string; f expansion is used so using explicit
% strings or macros is the same
\str_if_eq_x:nnTF
{ \str_upper_case:f { \str_head:f { #1 } } }
{ \str_upper_case:f { #2 } }
{ \prg_return_true: }
{ \prg_return_false: }
}

\NewExpandableDocumentCommand{\firstletterequalTF}{mmmm}
{
\javadr_firstletterequal:nnTF { #1 } { #2 } { #3 } { #4 }
}

\ExplSyntaxOff

\newcommand\dataa{abcde}
\newcommand\dataA{Abcde}
\newcommand\datab{bcde}
\newcommand\fixedA{A}

\begin{document}

\firstletterequalTF{abcde}{A}{Equal}{Not Equal} /
\firstletterequalTF{\dataa}{A}{Equal}{Not Equal} /
\firstletterequalTF{abcde}{\fixedA}{Equal}{Not Equal} /
\firstletterequalTF{\dataa}{\fixedA}{Equal}{Not Equal}

\firstletterequalTF{\dataA}{\fixedA}{Equal}{Not Equal}

\firstletterequalTF{\datab}{\fixedA}{Equal}{Not Equal}

\firstletterequalTF{}{}{Equal}{Not Equal}

\firstletterequalTF{}{\fixedA}{Equal}{Not Equal}

\edef\test{%
\firstletterequalTF{\dataa}{\fixedA}{Equal}{Not Equal}%
}
\texttt{\meaning\test}

\end{document}