4

When I compile the below MWE the first \@ifnextchar, always evaluates to false, which is clearly wrong in the last case. However, the second one (within \punctuationcheck) works just fine. Why would the same conditional evaluate to False and then True?

\documentclass{article}

\makeatletter
\newcommand{\punctuationcheck}{%
\@ifnextchar){I see a parens\relax}{%
\@ifnextchar]{I see a square bracket\relax}{%
\@ifnextchar.{I see a period\relax}{%
\@ifnextchar,{I see a comma\relax}{I didn' t see anything\ }}}}%
}
\newcommand{\ie}{\textit{i.e.}\@ifnextchar,{I saw a comma\relax}{I didn't see a comma,}\punctuationcheck}
\makeatother

\begin{document}
\ie) test

\ie] test

\ie. test

\ie, test
\end{document}

What this produces when I compile it:

i.e.I didn’t see a comma,I see a parens) test

i.e.I didn’t see a comma,I see a square bracket] test

i.e.I didn’t see a comma,I see a period. test

i.e.I didn’t see a comma,I see a comma, test

  • 2
    The \@ifnextchar in \ie always sees \punctuationcheck; it has three arguments: (1) the character to check for; (2) the code to execute if the character is found; (3) the code to execute if the character is not found. The token immediately following the arguments is what's checked. – egreg Sep 22 '14 at 14:20
  • 1
    You need to put the \punctuationcheck macro as the last token in both branches of the first \@ifnextchar, i.e.: \def\ie{\textit{i.e.}\@ifnextchar,{I saw a comma,\punctuationcheck}{I didn't see a comma,\punctuationcheck}}. – wipet Sep 22 '14 at 15:48
  • @wipet Your solution worked, but since you posted it as a comment, I can't mark it as an accepted answer. Repost it as an answer and I'll mark it. – rpspringuel Sep 22 '14 at 19:18
  • @egreg Thanks for the explanation of what was going on, but I didn't really understand it until after playing with wipet's answer for a bit. It will help me avoid similar errors in the future, however. – rpspringuel Sep 22 '14 at 19:20
  • 1
    @wipet --- There's nothing wrong with a short answer; it will help to keep the unanswered lists from growing too quickly. – Ian Thompson Sep 22 '14 at 20:34
5

The syntax of \@ifnextchar is

\@ifnextchar<test-token>{<true>}{<false>}<token>

If <test-token> is the same as <token>, then the <true> code is inserted, otherwise <false> is inserted and the input stream will become either

<true><token>

or

<false><token>

Note that <token> is not removed at this stage. The correct way to use this is to have \@ifnextchar<test-token>{<true>}{<false>} as the trailing part of the macro code, so that <token> will be whatever follows the macro.

In your code, instead, <token> is already specified and it is \punctuationcheck, so TeX is right into always using the <false> code.

Solution:

\newcommand{\ie}{%
  \textit{i.e.}%
  \@ifnextchar,%
    {I saw a comma}%
    {I didn't see a comma,\punctuationcheck}%
}

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.