2

I have an volatile integer variable (counter) and at some point I wish to save its value to a token list (saved_counter).
If I save it with just \tl_set, as soon as counter changes the value, this also changes the value of saved_counter, which is undesirable.

Example:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse}

\ExplSyntaxOn
\int_zero_new:N \counter    % Set counter to 0.
\tl_new:N \saved_counter
\ExplSyntaxOff

\begin{document}
\ExplSyntaxOn
    % Save C_0 in "saved_counter"
    \tl_set:Nn \saved_counter {C \textsubscript {\the\counter}}

    % Print the value of saved counter -> C_0
    \saved_counter

    % Change the value of counter for whatever the reason.
    \int_incr:N \counter

    % Print the value of saved counter again -> C_1
    \saved_counter
\ExplSyntaxOff
\end{document}

I understand that there are no real variables in LaTeX and that everything's a macro, therefore, I understand why this is happening.

However, this seems like a common problem and there must be some convenient solution, like expanding/converting the value of counter to string and then assigning it to saved_counter.
Unfortunately, I am new to LaTeX and couldn't figure it out by myself.

  • You don't say, but do we just want the counter value or the 'extras' (the C, etc.). The answer by frougon assumes you do want the extras .... but if you don't, you can save the value directly. – Joseph Wright May 4 at 19:02
  • The same problem occurs when saving just the value. I added 'extras' because those 'extras' are my real use case and I wanted to be sure that offered answers work with it, not just with plain number. – Iskustvo May 4 at 19:10
4

The problem with your code is that when you do:

\tl_set:Nn \saved_counter {C \textsubscript {\the\counter}}

the token list variable contains:

  • the C character token;
  • the \textsubscript control sequence token;
  • an opening brace character token;
  • the \the control sequence token;
  • the \counter control sequence token;
  • a closing brace character token.

In particular, \the\counter is not expanded in your saved token list. It gets expanded later, when you use the token list and it is absorbed by TeX token by token. This is why it reflects the value of the counter when your \saved_counter is expanded—at the last moment.

The solution is to expand \the\counter when you want to save the token list (I used a LaTeX3-ish way to print the counter using decimal notation as with LaTeX2e's \arabic or TeX's \number):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse}

\ExplSyntaxOn

\int_zero_new:N \g_my_counter_int    % Set counter to 0.
\tl_new:N \g_my_saved_tl

\cs_new_protected:Npn \my_update_token_list:n #1
  {
    \tl_gset:Nn \g_my_saved_tl { C \textsubscript {#1} }
  }

\cs_generate_variant:Nn \my_update_token_list:n { x }

\NewDocumentCommand \myUpdateTokenList { m }
  {
    % The x-form eXpands the argument first
    \my_update_token_list:x { \int_to_arabic:n {#1} }
  }

\ExplSyntaxOff

\begin{document}
\ExplSyntaxOn
    % Save the token list using the current counter value -> C_0
    \myUpdateTokenList{\g_my_counter_int}

    % Print the saved token list
    \tl_use:N \g_my_saved_tl

    % Change the counter value for whatever the reason.
    \int_gincr:N \g_my_counter_int

    % This is still the token list saved by \myUpdateTokenList above, where
    % the value 0 had been used.
    \tl_use:N \g_my_saved_tl
\ExplSyntaxOff
\end{document}

I also adapted your code to be more LaTeX3-conventional (variable names) and used global incr/set functions for the counter and token list (depends on your application, but is more straightforward this way). I believe it would be cleaner to put \ExplSyntaxOn stuff only inside the preamble. For this, you'd have to wrap all the LaTeX3 code inside user-oriented commands, as I did for \myUpdateTokenList. This makes the LaTeX3 things accessible to LaTeX2e: via arguments passed to commands that you implement in the preamble under \ExplSyntaxOn regime.

  • 1
    I updated my code because \myUpdateTokenList was always using \g_my_counter_int instead of its argument. Of course, if the same counter should always be used, \myUpdateTokenList could be made parameterless and hardcode \g_my_counter_int in its definition. – frougon May 4 at 21:22
2

The answer by frogon covers the approach best if you want to save not only the value itself but also additional material. There are however other ways.

I would probably just save the value in a second int:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\int_new:N \counter    % Set counter to 0.
\int_new:N \l__iskustvo_saved_counter_int
\ExplSyntaxOff

\begin{document}
\ExplSyntaxOn
    % Save C_0 in "saved_counter"
    \int_set_eq:NN \l__iskustvo_saved_counter_int \counter

    % Print the value of saved counter -> C_0
    \int_use:N \l__iskustvo_saved_counter_int

    % Change the value of counter for whatever the reason.
    \int_incr:N \counter

    % Print the value of saved counter again -> C_1
    \int_use:N \l__iskustvo_saved_counter_int
\ExplSyntaxOff
\end{document}

If you want to use a tl, you can save the value using V-type expansion

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\int_new:N \counter    % Set counter to 0.
\tl_new:N \l__iskustvo_saved_counter_tl
\ExplSyntaxOff

\begin{document}
\ExplSyntaxOn
    % Save C_0 in "saved_counter"
    \tl_set:NV \l__iskustvo_saved_counter_tl \counter

    % Print the value of saved counter -> C_0
    \l__iskustvo_saved_counter_tl

    % Change the value of counter for whatever the reason.
    \int_incr:N \counter

    % Print the value of saved counter again -> C_1
    \l__iskustvo_saved_counter_tl
\ExplSyntaxOff
\end{document}

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.