16

I understand what \@gobble, \@gobbletwo etc. do, but I don't understand why \@gobble allows for an argument.

I believe that the definition of the macro is \long\def\@gobble#1{}. Why is this argument needed?

In this answer for instance David Carlisle defines \global\advance\rowc\@ne\@gobble{##}&&%. Does it mean that only ## are gobbled?

3
  • 11
    The purpose of \@gobble is precisely to gobble one argument.
    – egreg
    Commented Dec 6, 2012 at 15:11
  • Davids answer is within table constructions, they are a very special beast. In general, see egregs answer
    – daleif
    Commented Dec 6, 2012 at 15:13
  • 6
    the meaning of ## is strange, not the command \@gobble.
    – yo'
    Commented Dec 6, 2012 at 15:27

1 Answer 1

32

The definition of \@gobble is equivalent to

\newcommand{\@gobble}[1]{}

so, when used, it will simply throw away its argument. When you say something like

\let\macro\@gobble

you're telling TeX that \macro will throw away its argument. Instead

\@gobble{something}

throws away {something} as soon as TeX finds it.


Let's see the code you're referring to:

\long\def\savedata#1{%
  \setbox0\vbox\bgroup
  \let\\\cr
  \let\midrule\@empty
  \let\multicolumn\@gobbletwo
  \everyeof{\noexpand}%
  \halign\bgroup
  \global\colc\z@
  \global\advance\rowc\@ne\@gobble{##}&&%
  \global\advance\colc\@ne
  \expandafter\xdef\csname data-#1(\the\rowc,\the\colc)\endcsname
  {\zap@space## \@empty}\cr
  \@@input #1 
  \crcr\egroup\egroup}

Its purpose is to load a file (the argument to \savedata) which contains what usually would go between \begin{tabular}{l...} and \end{tabular}, in order to gather data from it.

The table is typeset inside a box, which will not be used afterwards (\setbox0=\vbox\bgroup) and in this box, which forms a group, some macros are redefined: \let\\\cr and \let\midrule\@empty. The first is to make \\ into the simple table line terminator, the second is because \midrule is meaningless for the purpose. Also \multicolumn is redefined:

\let\multicolumn\@gobbletwo

so that, when TeX will see \multicolumn{1}{c}{(1)} it will leave only {(1)} in the input stream, because \@gobbletwo looks for two arguments and doesn't do anything with them, so they simply disappear. Probably

\let\multicolumn\@thirdofthree

would be theoretically better, but in the end the result is just the same. Can you see now why? Your input file will possibly contain \multicolumn, but in this context we are only interested in the third argument, because we are not really typesetting a table, but only storing its contents (cell by cell) in macros.

A technically important \everyeof{\noexpand} is issued (I won't discuss it) and then a \halign is opened.

The syntax for the primitive \halign is quite interesting; I'm not going into the details, but basically it is

\halign{<template>\cr
  <table row>\cr
  ...
  <table row>\cr
}

where <template> is a collection of specifications for each table column in the form <before>#<after> and separated by &. The # represents the cell contents. A && sequence means that the following specifications are repeated as many times as the table needs.

In this case the template is

  \global\colc\z@
  \global\advance\rowc\@ne\@gobble{##}&&%
  \global\advance\colc\@ne
  \expandafter\xdef\csname data-#1(\the\rowc,\the\colc)\endcsname
  {\zap@space## \@empty}\cr

which specifies a first column where the counter representing the columns is set to 0 and the one representing rows is advanced by one. Then the cell contents is passed to \@gobble, so it will vanish, as we don't need it.

The rest of the table is a sequence of columns with the following specification: the column counter is stepped and macros of the form

\data-<argument>(i,j)

(<argument> is the argument to \savedata, in parentheses are the row and column indices, as numbers; the macro name can't be written with ordinary means, but \csname...\endcsname allows for those strange characters in the name). The replacement text for this macro provides eventually the cell contents with leading and trailing spaces removed (\zap@space## \@empty). The \cr ends the template.

As Ahmed Musa remarks, the \zap@space macro should be used with care, because it zaps all spaces; in this case it's unimportant, because the significant entries don't contain spaces.

Finally the table contents is input so that the macros will be defined; \\ will be translated into the primitive \cr to provide line terminations (the more complex job that \\ does in LaTeX tabular environments is not needed here) and \multicol{1}{c}{(1)} will leave only {(1)}.

The table is terminated by \crcr which will not add a line if the code ends with \\. The first \egroup matches the \bgroup after \halign and the second one the \bgroup after \vbox.

Note that here the "cell contents placeholder", ordinarily #, has to be doubled because we are inside a definition.

7
  • "The replacement text for this macro is the cell contents with leading and trailing spaces removed." \zap@space is invasive. Try \edef\x{\zap@space a b c d \@empty}. And use \zap@space, not \zap@spaces.
    – Ahmed Musa
    Commented Dec 6, 2012 at 20:40
  • @AhmedMusa I was commenting David's code; you find the link to the original answer.
    – egreg
    Commented Dec 6, 2012 at 20:46
  • @AhmedMusa The code uses zap@space there is just a little typo in the answer above.
    – Jörg
    Commented Dec 7, 2012 at 13:41
  • @egreg I wish I could upvote this answer several times. It's really helpful, thanks a lot!
    – Jörg
    Commented Dec 7, 2012 at 13:41
  • 16
    I always wondered what that code was doing, good to see some documentation for it. Commented Dec 20, 2012 at 20:10

You must log in to answer this question.

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