2

I'm doing this:

\documentclass{article}
\begin{document}
\newcounter{bar}
\newcommand\checkit{
  \ifx\csname foo\romannumeral\the\value{bar}\endcsname\empty
    empty
  \fi
}
\newcommand\foovi{hello}
\setcounter{bar}{6}
\checkit
\renewcommand\foovi{}
\checkit
\end{document}

I'm getting an empty document, while a single word "empty" is expected. What's wrong?

4
  • @Mico can you please suggest how to rewrite this better? I'm not married to \ifx, any other options are welcome!
    – yegor256
    Aug 30 at 5:00
  • Have you consulted the posting How can I check in LaTeX (or plain TeX) whether a command exists, by name?
    – Mico
    Aug 30 at 5:08
  • Then you probably also saw Joseph Wright's warning, right? I'd give Joseph Wright's answer a try: \makeatletter \newcommand\checkit{The command foo\romannumeral\the\value{bar} \@ifundefined{foo\romannumeral\the\value{bar}}{ doesn't exist!}{ exists: \csname foo\romannumeral\the\value{bar}\endcsname{}}} \makeatother.
    – Mico
    Aug 30 at 5:18
  • @Mico you are right, I updated my question
    – yegor256
    Aug 30 at 5:21
5

There is an \expandafter missing. Beside this: there is a difference if a command is defined as long or as short:

\documentclass{article}
\begin{document}
\newcounter{bar}
\newcommand\checkit{%
  \expandafter\ifx\csname foo\romannumeral\value{bar}\endcsname\empty
    empty
  \fi
}
\newcommand\foovi{hello}
\setcounter{bar}{6}
1. \checkit

\renewcommand\foovi{}
2. \checkit

\renewcommand*\foovi{}
3. \checkit

\end{document}

enter image description here

4

There are a few issues with your code:

  • \ifx doesn't expand its arguments, but only compares the first two tokens following it, in your case \csname and f, which always yields false. You need to use \expandafter to build the \csname before \ifx does its job.

  • the macro \empty is short (meaning it doesn't use \long in its definition), whereas macros created with \newcommand are by default \long. You'll need to use \newcommand* and \renewcommand*, or after the first \newcommand* directly \def instead of \renewcommand*.

  • your macro's replacement text starts with a spurious space, you have to comment out the line ending after {, like so: \newcommand\checkit{%. You don't have to comment out line endings after macro names, so the line containing the \ifx and \fi are fine, another (possibly) unwanted space occures after the word empty.

I don't know what should happen in the case that \foovi isn't yet defined, so I decided to let this case throw the <false> branch. You can easily change that if you want.

I defined your macro \checkit to take two arguments (not immediately, but the used \@secondoftwo, \@secondofthree and possibly \@firstoftwo will take those arguments). So the macro will now behave as \checkit{<true>}{<false>} and execute the corresponding branch if the macro has the meaning \@empty (which is the same as \empty, but since we're in \makeatletter we could as well use the less likely to be redefined macro \@empty).

\documentclass[]{article}

\newcounter{bar}

\makeatletter
\providecommand\@secondofthree[3]{#2}
\newcommand\checkit
  {%
    \@ifundefined{foo\romannumeral\value{bar}}%
      {%
        % undefined
        \@secondoftwo % should result in <false>
        %\@firstoftwo % should result in <true>
      }
      {%
        \expandafter\ifx\csname foo\romannumeral\value{bar}\endcsname\@empty
          \expandafter\@secondofthree
        \fi
        \@secondoftwo
      }%
  }
\makeatother

\begin{document}
\setcounter{bar}{6}
\checkit{empty}{not empty}

\newcommand*\foovi{hello}
\checkit{empty}{not empty}

\renewcommand*\foovi{}
\checkit{empty}{not empty}
\end{document}

Result:

enter image description here

1

You've been bitten by \long status. The macro \empty is no \long, equivalent to \newcommand*\empty{}. However, you are using \renewcommand for \foovi, so it's \long and not \ifx equal to \empty. If you use \renewcommand*\foovi then all will be well.

1
  • The other answers also mention the \expandafter needed for \ifx.
    – Teepeemm
    Aug 30 at 15:15

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.