3

I'm trying to write a write a simple implementation of a list of notation (more as a technical exercise than for actual use). I've run into a rather strange issue with numberings. The following is my implementation of the two relevant commands. The \notation command creates a custom macro which contains the "notation" and the current page number (this seems to work OK), and the \listofnotation command prints all defined notation into a list. The problem is that, calling \notation{one} defines the macro \notation@1 and \notation{two} creates \notation@2 as expected. However, when I call \listofnotation, the output is \notation@1 two 1 and not \notation@1 one 1\par\notation@2 two 1 as I expect. Changing the starting index of \loopingindex to 0 makes it work as expected, but the output is \notation@0 one 1\par\notation@1 two 1. This is quite peculiar.

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
\global\advance\notationcount by1%
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

\newcommand\listofnotation{%
\newcount\loopingindex%
\loopingindex=1%
\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax\else
\section*{List}%
\noindent%
\loop\expandafter\ifx%
\csname notation@\the\loopingindex\endcsname\relax%
\else%
\expandafter\string\csname notation@\the\loopingindex\endcsname~%
\csname notation@\the\loopingindex\endcsname\par\noindent%
\advance\loopingindex by1%
\repeat%
\fi%

}
\makeatother

\begin{document}

\notation{one}
\notation{two}

\listofnotation

\end{document} 

I notice that the implementation is similar to that in the second example of https://www.tug.org/tug2012/booklet/hendrickson/AmyTugProc.pdf

Disclaimer: I had a quick look for a duplicate, but I wasn't really sure what to search for.

Thanks.

1 Answer 1

2

You have a wrong % at the end of a line:

\newcommand\notation[1]{%
\global\advance\notationcount by1%
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

The % in excess is at the end of line 2; when TeX is doing the assignment to \notationcount, it expands tokens until something which cannot be interpreted as a digit is found. In your case it expands \expandafter that triggers \csname into making a token out of those it finds up to \endcsname, expanding as it goes, so \the\notationcount is expanded before the assignment to it has been performed, so to the previous value!

I use to call this the missing required space syndrome. ;-) Solution:

\newcommand\notation[1]{%
\global\advance\notationcount by1
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

A space after a numeric constant is ignored.

There are other glitches in your code; for instance,

\newcount\loopingindex

should go outside the definition of \listofnotation; not really important here, but better programming style nonetheless.

The \protect token is completely misplaced and its effect can be from doing nothing to making a disaster. You can just \protect just one token, not a braced list of them.

The main defect, though, is that using \thepage is not safe unless you're in the output routine or a page has just been started after \newpage, \clearpage or \cleardoublepage. How to solve this depends on how you intend to use your macros; passing through the .aux file is generally the safest way.

Here's a fixed version of your macros, with % in the appropriate places. I haven't tried to do the two pass approach which should be needed, though.

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
  \global\advance\notationcount by 1
  \expandafter\protected@xdef\csname notation@\the\notationcount\endcsname{%
    #1\hskip1em \thepage
  }%
  \texttt{\expandafter\string\csname notation@\the\notationcount\endcsname}%
}

\newcount\loopingindex % NOT inside the definition!

\newcommand\listofnotation{%
  \loopingindex=1
  \expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
  \else
    \section*{List}
    \noindent
    \loop\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \else
      \texttt{\expandafter\string\csname notation@\the\loopingindex\endcsname}~%
      \csname notation@\the\loopingindex\endcsname\par\noindent
    \advance\loopingindex by 1
    \repeat
  \fi
}
\makeatother

\begin{document}

\notation{one}
\notation{two}

\listofnotation

\end{document} 

enter image description here

An implementation that uses the .aux file, so giving precise page numbers under any circumstance (provided the list has not been modified in the previous run):

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
  \global\advance\notationcount by 1
  \protected@write{\@auxout}{}{%
    \string\stored@notation{\the\notationcount}{#1}{\thepage}%
  }%
  \texttt{\expandafter\string\csname notation@\the\notationcount\endcsname}%
}
\newcommand{\stored@notation}[3]{%
  \global\@namedef{notation@#1}{#2\quad#3}%
}

\newcount\loopingindex % NOT inside the definition!

\newcommand\listofnotation{%
  \loopingindex=1
  \expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \typeout{No notation defined; rerun LaTeX}%
  \else
    \section*{List}
    \noindent
    \loop\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \else
      \texttt{\expandafter\string\csname notation@\the\loopingindex\endcsname}~%
      \csname notation@\the\loopingindex\endcsname\par\noindent
    \advance\loopingindex by 1
    \repeat
  \fi
}
\makeatother

\begin{document}

\notation{one}
\newpage
\notation{two}
\newpage
\notation{thr\'ee}

\listofnotation

\end{document} 

enter image description here

4
  • Thanks, that sorted it. I did spend quite a lot of time trying to figure out how to correctly expand the \thepage so that the correct page number is output in the list. I eventually settled on using \edef, which then caused problems when fragile commands were used as the argument for the \notation macro. Thus the switch to \protected@edef. The purpose of these macros was to construct a list of notation from my thesis and print the list at the end. (Without appealing to glossary/indexing packages.)
    – SamM
    Commented Mar 14, 2016 at 14:12
  • @SamM I added an implementation using the .aux file in order to have correct page number references.
    – egreg
    Commented Mar 14, 2016 at 16:50
  • in the definition of notation@#1' do we not need #2\quad\thepage` (or similar), it looks like this prints the value of \notationcount?
    – SamM
    Commented Mar 14, 2016 at 16:57
  • @SamM Yes, you're right, sorry: there should be three parameters. I'll fix it in a moment.
    – egreg
    Commented Mar 14, 2016 at 17:03

You must log in to answer this question.

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