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?


\@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}

\ie) test

\ie] test

\ie. test

\ie, test

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, 2014 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, 2014 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. Sep 22, 2014 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. Sep 22, 2014 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. Sep 22, 2014 at 20:34

1 Answer 1


The syntax of \@ifnextchar is


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




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.


    {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.