7

This code leaves an empty row at the bottom:

\documentclass{article}

\usepackage{etoolbox}

\def\somedef{foo}

\begin{document}

\begin{tabular}{|l|}
  \hline
  First row, not important \\ \hline
  \ifdefstring{\somedef}{bar}{never used \\ \hline}{}%
\end{tabular}

\end{document}

The resulting table looks like:

----------------------------
| First row, not important |
+--------------------------+
|                          |

It's that bogus empty row at the bottom that I want to get rid of.

I know I can make this work by replacing the \ifdefstring with something like:

\ifnum\pdfstrcmp{\somedef}{bar}=0 never used \\ \hline \else\fi

But I'm interested in sticking to etoolbox, which seems to be a fairly comprehensive package with many relatively easy to read macros (for programmers, my audience). I'm also interested in using the conditional inline within the table, as that seems easiest to read and maintain. (If there's a better package that is similarly comprehensive that I should be using instead and it doesn't have the above problem, I'm very interested in hearing about that, too.)

How can I use etoolbox's \ifdefstring here without adding the extra row?

I suspect etoolbox either (a) has a bug (missing some %), or (b) is inserting something like \relax. Is there some way to discard/eat \ifdefstring's seemingly invisible-yet-row-creating output?

3 Answers 3

5

It's not a bug in etoolbox. Your problem is that \ifdefstring does not completely expand in TeX's mouth (it can't, given what it needs to do), and expansion in TeX's mouth is necessary for a macro to do what you want it to.

It all boils down to how TeX parses the data for a \halign: To parse data for a column, it reads one token with macro expansion, then checks that token (in case it is a \span or some other token requiring special processing), then it scans tokens without macro expansion until the next & or \cr (\\ counts as \cr in this context), and then processes all the collected tokens as the data for the present column.

As a consequence, a macro that might or might not produce a row in the table needs to expand to nothing at all if it is not to produce a row, and \ifdefstring does not do that.

2
  • Thanks for the detailed answer. I only know of the "eyes, mouth, stomach, and bowels" of TeX, not how they work, but after reading this a couple of times it makes sense. (I could probably benefit from something like The TeXbook here.)
    – dsedivec
    Nov 10, 2010 at 23:48
  • I recently had a problem like this but came to the opposite conclusion. If \halign reads without macro expansion until finding the next \cr, then how is it possible to put e.g. \crcr in the "end" part of an environment wrapping around \halign and still to work right? From what you say it seems like the \end{env} will hide the carriage return. I figured that \halign expands the first token to check for \omit and the like, and, if all is normal, continues expanding down the line until it eventually hits \cr or &, when it is finished with the current entry.
    – Ryan Reich
    Nov 11, 2010 at 8:34
3

I see that Harald has covered some of this, but I hope this is also informative.

etoolbox uses e-TeX, but not any further extensions as far as I know. So \pdfsctrcmp is out here (for etoolbox). So if you read the code, there is an \edef inside \ifdefstring to carry out the comparison. That's non-expandable, and so it forces a new cell. You see the same with

\begin{tabular}{|l|}
  \hline
  First row, not important \\ \hline
  \edef\test{}%
\end{tabular}

So I'm not sure you can avoid the issue without defining \ifdefstring as you have, with \pdfstrcmp. (In LaTeX3, we've decided to require \pdfstrcmp as it helps out with lots of otherwise unexpandable tests.)

3
  • Thank you also for your answer. I was particularly interested to know that (1) \edef is "non-expandable," which might seem ironic to the uninformed reader (e.g. me) since I believe \edef's purpose is to "fully expand" before making the definition; and (2) that LaTeX3 requires \pdfstrcmp. Is it still called \pdfstrcmp in LaTeX3? ISTR elsewhere in the TeX universe there is simply \strcmp (which may be just an alias for \pdfstrcmp where available). Keeping the "pdf" in there seems odd to me.
    – dsedivec
    Nov 10, 2010 at 23:51
  • 1
    @dsedivec — \strcmp is the primitive used by XeTeX, and the \pdf prefix is standard for all new pdfTeX primitives. In LaTeX3 it's called \str_if_eq:nnTF with several variations, which all work indentically in pdfLaTeX, XeLaTeX, and LuaLaTeX. Nov 11, 2010 at 6:57
  • 1
    As Will knows but doesn't say, \str_if_eq:nnTF is a higher level wrapper around \pdfstrcmp. The idea here is that the primitives tend to be rather awkward to work with directly, so the official way to do it in LaTeX3 is via something more controlled, in this case \str_if_eq:nnTF. As Will says, this also hides the complexity of the primitive having a different name in pdfTeX and XeTeX, and being written as a short piece of Lua in LuaTeX.
    – Joseph Wright
    Nov 11, 2010 at 8:40
2

For the future reference of others (and probably myself), to explicitly demonstrate the comments left by Joseph Wright and Will Robertson, this works as well and is probably easier to read:

\documentclass{article}

\usepackage{expl3}

\def\somedef{foo}

\begin{document}

\ExplSyntaxNamesOn
\begin{tabular}{|l|}
  \hline
  First row, not important \\ \hline
  \str_if_eq:nnTF{\somedef}{bar}{never used \\ \hline}{}%
\end{tabular}
\ExplSyntaxNamesOff

\end{document}

\ExplSyntaxNamesOn makes _ and : "letters" so you can use them in csnames (or at least that's how I think of it). \ExplSyntaxNamesOff does the opposite. (Note: don't put those right in the tabular around the \str_if_eq:nnTF or else you'll still get the empty cell.)

All credit for this goes to Joseph and Will. Thanks!

You must log in to answer this question.

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