%% \texttt =\long macro:
%% #1->\ifmmode
%%       \nfss@text{\ttfamily#1}
%%     \else
%%       \hmode@bgroup\text@command{#1}\ttfamily\check@icl#1\check@icr\expandafter\egroup
%%     \fi


Processing this minimal example with pdflatex results in a rather nasty Incomplete \ifmmode error during the expansion of \texttt{\string\iftrue}. It seems to me that \string does not totally prevent TeX from taking account of \iftrue as a conditional. (The same is true for \detokenize, by the way.)

Can anybody explain what is precisely going on?

Addendum: Note that the error would disappear if \texttt stored its argument in an auxiliary macro before processing it.




On seeing the \iffalse TeX scans ahead matching tokens with definitions \if (or the other primitive if tokens such as \ifx \iftrue etc) \else and \fi to get to a matching \fi when normal operation re-starts. In particular it does not execute any assignments or expand any tokens. So \string is simply skipped over but the inner \iftrue is seen so the \fi matches the \iftrue and things go wrong.

Depending what you want to do

 \textbackslash iftrue


\csname iftrue\endcsname


\expandafter\string\csname iftrue\endcsname

are all safe. (Or similarly and more usefully perhaps the same with \iftrue as the first token.)

  • OK, I think I understand: The key point is that TeX parses conditionals in a totally context-free manner. – mhp Jun 29 '12 at 7:53

You need to bear in mind that TeX is a macro expansion language. Thus


expands the definition of \texttt with an argument containing two tokens, \string and \iftrue. That leads to


(formatting mine). TeX then scans the conditional, finds more tokens which start \if... statements than end them, and complains.

What you presumably want to do is pass the string \iftrue to \texttt:

  • Or the easier \texttt{\char`\\iftrue}. – egreg Jun 28 '12 at 17:41
  • 2
    @egreg That's not a string: iftrue is made of catcode 11 tokens :-) – Joseph Wright Jun 28 '12 at 17:46
  • (Of course, that might be important in some contexts, but not here) – Joseph Wright Jun 28 '12 at 17:58
  • @JosephWright: Expanding the argument in advance is definitely a useful remedy. Is there, actually, a more general argument processor capable of expanding an arbitrary brace-delimited argument such as {text \string\iftrue text}? – mhp Jun 29 '12 at 8:41
  • @mhp Depending on the context, you could either \edef everything into a temporary variable or use \romannumeral to force expansion; the latter method is itself expandable. – Joseph Wright Jun 29 '12 at 8:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.