12

Is there a command that creates a counter or, if it already exists, redefines it? Thing is that I'm working with nested loops. The second loop is however in a command. This means if I want to use a second counter for the second loop, I need to define it before the first loop and give it as an argument in the command which seems a bit cumbersome.

As example:

\newcommand\recursiveloop[2]{% do loop with counter #2, #1 times
  \setcounter{#2}{0}
  {\loop\unless\ifnum\value{#2}=#1
    \stepcounter{#2}
    % do something
  \repeat}
}

\newcounter{loop}     % counter for first loop
\newcounter{recloop}  % counter for recursive loop

\loop\unless\ifnum\theloop=4  % start the first loop
  \stepcounter{loop}  % counter loop +1
  % do something
  \recursiveloop{3}{recloop}  % call command to run second loop
\repeat

In this example it's of course not a big deal. But my command has already 3 arguments and more will be added.. Isn't there a way of (1) check if the counter exists to run the appropriate command: \setcounter or \newcounter or (2) a command that can do it by himself.

6
  • 2
    What if the counter already exists and its value is important in other places? You'd change it and the old value wouldn't be available any more.
    – egreg
    Jul 20, 2012 at 8:25
  • 2
    you could do \ifx\c@recloop\@undefined \newcounter{recloop} \fi but it's generally inadvisable to do that. The assignment to the csname c@recloop would be local but the allocation of the register would be global. It is better to do as latex lists do and just allocate a fixed number of counters (your maximum depth) in the preamble. allocating mid-document is always a suspect practice. Jul 20, 2012 at 8:28
  • @egreg: If I had a good way of defining names it wouldn't be any problem, but I see what you mean. Still it is cumbersome in my opinion...
    – Didii
    Jul 20, 2012 at 8:33
  • @DavidCarlisle: I'll try that, but what are the consequences of the allocation? Could it be possible to overwrite the value without LaTeX knowing about it you mean?
    – Didii
    Jul 20, 2012 at 8:35
  • 1
    you may overwrite something or you may run out of registers if you keep allocating new register for the same name. (classic tex only has 255 of them and around half are already used typically) Jul 20, 2012 at 8:43

2 Answers 2

8

No, \renewcounter and \providecounter don't exist and they shouldn't.

By way of example, suppose you say

\providecounter{page}

\loop\unless\ifnum\value{loop}=4  % start the first loop
  \stepcounter{loop}  % counter loop +1
  % do something
  \recursiveloop{3}{page}  % call command to run second loop
\repeat

and \recursiveloop does \stepcounter{page}: chaos will ensue even if the loop is in a group, because \stepcounter, \addtocounter and \setcounter always act globally.

Of course you'd not use page, but what would happen if you choose a name already referring to some counter that's defined in a package you load and stores some important value?

Always allocate your own counters in the preamble or use the scratch counters provided by LaTeX (\@tempcnta and \@tempcntb).

By the way, don't use \theloop for numeric tests, but \value{loop}, which stores the value in a form which is independent from the value's representation.

2

If you really need \renewcounter then writing it is really simple: \def\renewcounter#1{\expandafter\ifcsname c@#1\endcsname\else\newcounter{#1}\fi \setcounter{#1}{0}. However, its use cases are indeed quite rare. The previous answer claims that it should “never” be used, which is, as quite often for such claims, an exaggeration; an example of a specific use case is an exam file, which includes some exercise files, each of which may define (through \renewcounter) their own, independent question counters.

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.