4

When I try to change a counter in an \edef using \stepcounter, I get a whole lot of error messages ("Missing \endcsname inserted"). When I try to do the same with \addtocoutner I get no error, but the counter remains unchanged within the \edef.

The following MWE produces "E, EE, F". If you remove the %, the errors will appear.

\documentclass{article}

\newcounter{testcount}
\setcounter{testcount}{5}

%\edef\foo{\Alph{testcount}\stepcounter{testcount}\Alph{testcount}}
\edef\bar{\Alph{testcount}\addtocounter{testcount}{1}\Alph{testcount}}

\begin{document}

\Alph{testcount}
,
\bar
,
\Alph{testcount}

\end{document}

Why is this and how can I achieve the effect that one would expect \foo and \bar to have?

  • 2
    you cannot make assignments (like \stepcounter or \addtocounter) in an \edef-like context. – clemens Apr 14 '16 at 14:11
  • \show\bar will show in the log: > \bar=macro: ->E\global \advance \c@testcount 1\relax E. – clemens Apr 14 '16 at 14:16
  • If \bar is defined it's fixed and there's no action be done anymore, since the definition is expanded already. \bar\bar\bar\bar will do nothing but print the result (regarding \addtocounter – user31729 Apr 14 '16 at 14:19
  • 1
    Maybe you could tell us why you want to do this with \edef in the first place? It seems really counterproductive, but perhaps you have reasons we can only guess at. – Harald Hanche-Olsen Apr 14 '16 at 14:20
  • 1
    @schtandard assignments never are expandable. That's just the way it is. – clemens Apr 14 '16 at 14:49
5

If you add \show\bar after doing the \edef, you're informed that

> \bar=macro:
->E\global \advance \c@testcount 1\relax E.

No assignment is performed inside \edef, only macro expansion. We also have

% latex.ltx, line 2099:
\def\addtocounter#1#2{%
  \@ifundefined{c@#1}%
    {\@nocounterr{#1}}%
    {\global\advance\csname c@#1\endcsname #2\relax}}

so the first expansion replaces \addtocounter{testcount}{1} with that replacement text; \@ifundefined is expandable and, since the test returns false (because \c@testcount is defined), you get

\global\advance\csname c@testcount\endcsname 1\relax

The tokens \global and \advance are unexpandable, so TeX expands \csname, forming the token \c@testcount, which in turn is not expandable. So, essentially, only \Alph{testcount} gets really expanded, to E in both cases.

You can't do assignments in “pure expansion” contexts. Depending on your aim, something else can be devised.

\documentclass{article}

\newcounter{testcount}
\setcounter{testcount}{5}

\makeatletter
\edef\baz{%
  \Alph{testcount}\@Alph{\numexpr\value{testcount}+1\relax}%
  \unexpanded{\stepcounter{testcount}}%
}
\makeatother

\begin{document}

\Alph{testcount}
,
\baz
,
\Alph{testcount}

\end{document}

enter image description here

4

This answer is based on this comment.

\bar can be defined in two steps. First the current value of the counter is used and the expanded form saved in \barI. Then the counter is increased, because the assignment does not work in expandable contexts like \edef. The increased counter value is saved in \barII. Finally macro \bar is composed from \barI and \barII. Then \bar is defined with fixed and expanded counter values and let the counter untouched, when used.

\documentclass{article}

\newcounter{testcount}
\setcounter{testcount}{5}

\edef\barI{\Alph{testcount}}
\stepcounter{testcount}
\edef\barII{\Alph{testcount}}
\edef\bar{\barI\barII}

\begin{document}

\setcounter{testcount}{1}

\Alph{testcount},
\bar,
\Alph{testcount},
\stepcounter{testcount}{\Alph{testcount}}

\end{document}

Result

1

This looks like a typical “ask X for Y” question. @egreg has already explained why your approach with \edef is conceptually wrong. While he was posting his answer, I was trying to write down a workaround for what you seem to indicate, in a comment, as your original problem. I was ready to post the following attempt when I saw @egreg’s answer, essentially based on the same principle.

\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
% \usepackage[ascii]{inputenc}

\makeatletter

\@ifdefinable\@schtandard@SavedSection{%
    \let \@schtandard@SavedSection \section
}
\newenvironment*{NonStandardSectionNumbering}{%
    \renewcommand*\thesection{%
        \@arabic{\numexpr\value{section}-\@ne\relax}
        and~\arabic{section}%
    }%
    \renewcommand*\section{%
        \stepcounter{section}%
        \@schtandard@SavedSection
    }%
}{}

\makeatother



\begin{document}

\section{Normal numbering}
\label{S:1}
This section has normal numbering.

\section{Another one}
\label{S:2}
This too.

\begin{NonStandardSectionNumbering}
    \section{Special numbering}
    \label{S:3&4}
    Inside the \texttt{NonStandardSectionNumbering} environment, however,
    sections are numbered in a different way.

    \section{And again}
    \label{S:5&6}
    Some random text.
\end{NonStandardSectionNumbering}

\section{Back to standard numbering}
\label{S:7}
This section is again numbered in the normal way.

\section{Yet another section}
\label{S:8}
Note that the progression of section numbers is correct.  The references are
correct too: section~\ref{S:1}, section~\ref{S:2}, sections \ref{S:3&4},
sections \ref{S:5&6}, section~\ref{S:7}, and section~\ref{S:8}.

\end{document}

Bear in mind that this is only an unfinished trial: you should specify more clearly what you want to achieve.

Edit: I’ve edited the code, adding a remark about references. I’m adding a picture that shows the output, too:

Output of hte code

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.