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?

7
  • your \mytest douesn't use #1 at all so it does not use its argument Sep 23, 2016 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. Sep 23, 2016 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) Sep 23, 2016 at 20:11
  • 1
    cryptic is good sometimes:-) Sep 23, 2016 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, 2016 at 21:23

3 Answers 3

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}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .