3

When proving theorem, I sometimes define arbitrary constants that I then reference. These constants are not really important and they do not need to be memorable beyond the proof. This is why I usually adopt a C_i notation that with index i that I increment every time I need to define a new constant.

I am wondering if I can automate this. Particularly because when I reorganise my proofs I have to go back and make sure that the indices are ordered throughout my manuscript.

My ideal setup would be to define two command \resetconstants and \const to do something like this

\resetconstants{D}
This is my first constant \const{name1} and my second constant \const{name2}
but I can also reference my first constant \const{name1}

\resetconstants{E}
New constants are here \const{name1}

\resetconstants{D}
Resetting constants means that previous ones are completely 
forgotten so that \const{name1} is a brand new constant.

The output would then be

This is my first constant D_1 and my second constant D_2
but I can also reference my first constant D_1.

New constants are here E_1.

Resetting constants means that previous ones are completely 
forgotten so that D_1 is a new constant.

How would I go about implementing this? I know how to define a counter, but I do not know how to define a key-value lookup table. Is there perhaps a package that makes implementing this easier?

2

Here's a bare latex approach. The typesetting is controlled by \rc@useconst whose first argument is the letter and whose second argument is the number associated to the current constant. If you want to change the way constants are displayed, you can just change the definition of this macro.

\documentclass{article}
\makeatletter

\newcount\rc@count
\rc@count=1\relax

% initialize list of constants
\let\rc@clearconstantlist\empty

% This command takes the name of a constant and undefines it.
\newcommand\rc@clearconstant[1]{\global\expandafter\let\csname rc@const@#1\endcsname\undefined}

% Iterate over the lists of
\newcommand\resetconstants[1]{%
    \def\rc@constname{#1}% Set the new base name of the constants to the argument
    \global\rc@count=1\relax % Reset the constant counter to 1
    \bgroup 
        \let\\\rc@clearconstant % map over the list of constants that have been defined, clearing each of them.
        \rc@clearconstantlist
        \global\let\rc@clearconstantlist\empty % Globally empty the list of constants.
    \egroup
}
\newcommand\const[1]{%
    \@ifundefined{rc@const@#1}{%
        % Globally store the expansion of the current constant in a macro
        \expandafter\xdef\csname rc@const@#1\endcsname{%
           \noexpand\rc@useconst{\rc@constname}{\the\rc@count}%
        }%
        % Add this macro to the list of things that need to be cleared.
        \g@addto@macro\rc@clearconstantlist{\\{#1}}%
        \global\advance\rc@count1\relax
    }{}%
    % Display the output
    \csname rc@const@#1\endcsname
}

% Redefine this command to change the way that the constants are typeset.
% #1 -- the letter, i.e., D or E
% #2 -- the number of the constant, i.e., 1, 2
\newcommand\rc@useconst[2]{{#1}\textsubscript{#2}}
\makeatother

\begin{document}

\resetconstants{D}
This is my first constant \const{name1} and my second constant \const{name2}
but I can also reference my first constant \const{name1}

\resetconstants{E}
New constants are here \const{name1}

\resetconstants{D}
Resetting constants means that previous ones are completely
forgotten so that \const{name1} is a brand new constant.

\end{document} 

I am using a standard tex list iteration technique, which is to store a list as a macro \mylist with body \\{first-entry}\\{second-entry}...\\{last-entry}. So an empty list is just a zero argument macro with empty expansion text. To initialize an empty list or to empty out a list I already have I just say \let\mylist\empty. To add an element to the list I use \g@addto@macro\mylist{\\{new-entry}}. The macro \g@addto@macro globally adds text to the body of a macro with no arguments.

In order to iterate over this list, we redefine \\ to be our iterator and then expand \mylist. The redefinition of \\ should be done locally because \\ already does something else.

\bgroup % ensure local scope
    \let\\\rc@clearconstant % The function I'm mapping over my list is \rc@clearconstant 
    \rc@clearconstantlist % Map over the list, clearing each constant
    \global\let\rc@clearconstantlist\empty % Globally empty the list of constants.
\egroup % This ends the scope and the value of `\\` is restored.
  • Thanks for your (and others) answers. I picked this one because I like a pure latex approach. – Tohiko Aug 23 '18 at 8:15
  • I am really trying to understand this script. But I have a few things that I couldn't understand. Namely the line \g@addto@macro\rc@clearconstantlist{\\{#1}}% and what's inside the \bgroup and \egroup pair. Can you please explain those? Or at least point me to a place where I can get introduced to these structures? – Tohiko Aug 23 '18 at 9:40
  • 1
    I'll add line by line explanations. – Hood Chatham Aug 23 '18 at 9:49
  • 1
    Let me know if you have further questions. – Hood Chatham Aug 23 '18 at 10:07
  • Thank you very much for the explanations. Everything is clear now. I wish I could upvote this answer more :) – Tohiko Aug 24 '18 at 8:45
3
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \g_tohi_const_int
\int_new:N \g_tohi_const_sub_int
\tl_new:N  \g_tohi_const_char_tl

\cs_new_protected:Nn \tohi_print_constant:nn 
{
  #1 \textsubscript {#2} 
} 

\NewDocumentCommand\resetconstants{m}
{
 \int_gincr:N \g_tohi_const_int
 \int_gzero:N \g_tohi_const_sub_int
 \tl_gset:Nn  \g_tohi_const_char_tl {#1}
}

\NewDocumentCommand\const{m}
{
  \tl_if_exist:cTF
   {
    c_tohi_const_\int_use:N\g_tohi_const_int _#1_tl
   }
   {
    \tl_use:c {c_tohi_const_\int_use:N\g_tohi_const_int _#1_tl }
   }
   {
    \int_gincr:N \g_tohi_const_sub_int
    \tl_const:cx {c_tohi_const_\int_use:N\g_tohi_const_int _#1_tl }
     { \exp_not:N\tohi_print_constant:nn {\g_tohi_const_char_tl }{\int_use:N \g_tohi_const_sub_int}}
    \tl_use:c {c_tohi_const_\int_use:N\g_tohi_const_int _#1_tl }
   }
}

\ExplSyntaxOff
\begin{document}

\resetconstants{D}
This is my first constant \const{name1} and my second constant \const{name2}
but I can also reference my first constant \const{name1}

\resetconstants{E}
New constants are here \const{name1}

\resetconstants{D}
Resetting constants means that previous ones are completely
forgotten so that \const{name1} is a brand new constant.
\end{document}

enter image description here

  • I think you should separate out the actual typesetting command into a separate macro, like what I did. There's a decent chance that the user might at some point want to change the typesetting of the output. If the typesetting is done in a separate clearly named macro, the person using it doesn't have to hunt through a bunch of code they can't comprehend to find the part they need to change. – Hood Chatham Aug 22 '18 at 16:46
  • @HoodChatham Yes, that would be better. I edited the answer. – Ulrike Fischer Aug 22 '18 at 16:57
2

You can use a property list that's cleared when \resetconstants is issued.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\const}{m}
 {
  \tohiko_constant_use:n { #1 }
 }
\NewDocumentCommand{\resetconstants}{m}
 {
  \tohiko_constant_reset:n { #1 }
 }

\int_new:N \g_tohiko_constant_count_int
\tl_new:N \g_tohiko_constant_name_tl
\prop_new:N \g_tohiko_constant_prop

\cs_new_protected:Nn \tohiko_constant_use:n
 {
  \prop_if_in:NnF \g_tohiko_constant_prop { #1 }
   {
    \int_gincr:N \g_tohiko_constant_count_int
    \prop_gput:Nnx \g_tohiko_constant_prop
     { #1 }
     { \int_to_arabic:n { \g_tohiko_constant_count_int } }
   }
  \ensuremath
   {
    \tl_use:N \g_tohiko_constant_name_tl
    \sb { \prop_item:Nn \g_tohiko_constant_prop { #1 } }
   }
 }
\cs_new_protected:Nn \tohiko_constant_reset:n
 {
  \tl_gset:Nn \g_tohiko_constant_name_tl { #1 }
  \prop_clear:N \g_tohiko_constant_prop
  \int_gzero:N \g_tohiko_constant_count_int
 }

\ExplSyntaxOff

\begin{document}

\resetconstants{D}
This is my first constant \const{name1} and my second constant \const{name2}
but I can also reference my first constant \const{name1}

\resetconstants{E}
New constants are here \const{name1}

\resetconstants{D}
Resetting constants means that previous ones are completely 
forgotten so that \const{name1} is a brand new constant.

\end{document}

enter image description here

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.