4

I'd like to test whether \solflag is defined or whether \profflag is defined. I'd like to do so with a macro whose argument could be either "sol" or "prof" (or some other word).

My "minimal (non)working example" attempt at this is

\documentclass{article}
\RequirePackage{ifthen}
\newcommand{\solflag}{}
\newcommand{\mytest}[1]
   {\ifthenelse{\isundefined{\#1flag}} {UNDEFINED}{DEFINED}}

\begin{document}

Sol test: \mytest{sol}

Bar test: \mytest{bar}

2nd bar test: \ifthenelse{\isundefined{\barflag}} {UNDEFINED}{DEFINED}

\end{document}

The result, however, is this:

Sol test: DEFINED
Bar test: DEFINED
2nd bar test: UNDEFINED

My guess is that the first "Bar" test is checking whether \bar is defined, i.e., that the concatenation of \#1 and flag in the macro just isn't happening or something.

I suspect that the answer I need is somewhere in the LaTeX-Fu of this answer, but I simply cannot make head or tail of that.

Is it possible to do what I'm hoping to do?

  • your \mytest douesn't use #1 at all so it does not use its argument – David Carlisle Sep 23 '16 at 19:16
  • @DavidCarlisle He actually does use #1, but with the improper syntax \#1flag. To the OP, the proper way to convey \#1flag is \csname #1flag\endcsname. The sequence \#1flag gets expanded as #1flag where # is literally the pound sign. – Steven B. Segletes Sep 23 '16 at 19:28
  • @StevenB.Segletes no, that was my point #1 would be a reference to an argument \# is an instruction to typeset a # (a pound sign is £ :-) it does not expand to a # (it doesn't expand at all actually, it's a chardef token) – David Carlisle Sep 23 '16 at 20:11
  • 1
    cryptic is good sometimes:-) – David Carlisle Sep 23 '16 at 20:18
  • 1
    I'd like to thank all the folks who answered; each answer taught me something new. (And @DavidCarlisle's comment taught me to beware of his answer, because they might be more subtle than they seem...) – John Sep 23 '16 at 21:23
6

The etoolbox package has a lot of good stuff in it for these and other low level things.

\documentclass{article}
\RequirePackage{etoolbox}
\newcommand{\solflag}{}
\newcommand{\mytest}[1]{\ifcsdef{#1flag}{DEFINED}{UNDEFINED}}
\begin{document}
Sol test: \mytest{sol}

Bar test: \mytest{bar}
\end{document}

enter image description here

Other similar tests provided by the package include \ifdef, \ifundef, \ifcsundef, \ifdefmacro, \ifcsmacro and many more.

2

When you write

\#1flag

you have six tokens

\# • 1 • f • l • a • g

(I use for separating tokens by ease of reading). You may be better served with

\documentclass{article}
\usepackage{ifthen}
\newcommand{\solflag}{}
\newcommand{\mytest}[1]{%
  \ifthenelse{\expandafter\isundefined\expandafter{\csname #1flag\endcsname}}
    {UNDEFINED}{DEFINED}% 
}

\begin{document}

Sol test: \mytest{sol}

Bar test: \mytest{bar}

2nd bar test: \ifthenelse{\isundefined{\barflag}} {UNDEFINED}{DEFINED}

\end{document}

that prepares the token \barflag before being evaluated by \ifthenelse.

enter image description here

The LaTeX kernel has already a macro for this:

\documentclass{article}
\usepackage{ifthen}
\newcommand{\solflag}{}

\makeatletter
\newcommand{\mytest}[1]{%
  \@ifundefined{#1flag}{UNDEFINED}{DEFINED}%
}
\makeatother

\begin{document}

Sol test: \mytest{sol}

Bar test: \mytest{bar}

2nd bar test: \ifthenelse{\isundefined{\barflag}} {UNDEFINED}{DEFINED}

\end{document}

However, this has the consequence that the following test based on \isundefined returns true.

If you plan to use both kinds of test, use

\documentclass{article}
\usepackage{ifthen}
\newcommand{\solflag}{}
\makeatletter
\newcommand{\mytest}[1]{%
  \begingroup
  \@ifundefined{#1flag}{\endgroup\@firstoftwo}{\endgroup\@secondoftwo}%
  {UNDEFINED}%
  {DEFINED}%
}
\makeatother

\begin{document}

Sol test: \mytest{sol}

Bar test: \mytest{bar}

2nd bar test: \ifthenelse{\isundefined{\barflag}} {UNDEFINED}{DEFINED}

\end{document}

On a modern TeX system, LaTeX uses e-TeX, so you can do

\newcommand{\mytest}[1]{%
  \ifcsname #1flag\endcsname
    DEFINED%
  \else
    UNDEFINED%
  \fi
}
1

I wouldn't use ifthen for this, but if you do then you need to use #1 to construct the csname to test. Note \# is a command to produce # it is not a reference to an argument, so your definition does not use its argument at all.

\documentclass{article}

\usepackage{ifthen}


\newcommand{\solflag}{}
\newcommand{\mytest}[1]{%
  \ifthenelse{\expandafter\isundefined\csname#1flag\endcsname}{UNDEFINED}{DEFINED}}

\begin{document}

Sol test: \mytest{sol}

Bar test: \mytest{bar}

2nd bar test: \ifthenelse{\isundefined{\barflag}} {UNDEFINED}{DEFINED}

\end{document}

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.