1

I am trying to use \l_tmpa_tl in the align environment. The requirements are to set the variable inside of align and use &. The current result shows x= leaving the right-hand side of the equal sign empty. In case the variable is assigned outside the align environment, or & is omitted, it works as expected. I kindly ask why this is occurring and how to fix?

\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\mycmd}{}{
    \begin{align}
    \tl_set:Nn \l_tmpa_tl {1}
        x &=\l_tmpa_tl
    \end{align}
}
\ExplSyntaxOff

\begin{document}
\mycmd
\end{document}
2
  • This suspiciously looks as an XY-question. Can you please be more detailed about your aim?
    – egreg
    May 6, 2023 at 22:22
  • @egreg, Of course! I am learning about LaTeX3 and trying to understand why the following doesn't work. The question is posted for the sake of knowledge. May 7, 2023 at 1:33

3 Answers 3

1

The instruction \tl_set:Nn \l_tmpa_tl {xyz} is an assignment, just like \int_incr:N \l_tmpa_int, \dim_set:Nn \l_tmpa_dim { 1pt }.

There are many kinds of assignments and it's actually mostly unimportant to know how expl3 deals with them. Of course, they'll be ultimately done with one of the primitive TeX assignments.

Assignments can be global or local and the programming guidelines for expl3 are quite fussy in requiring that variables are declared with a g or l prefix that specifies whether the variable is used in local or global assignments. But the name is just a name and it's the programmer who's in charge of using the correct assignment command.

The first three examples above are local assignments, but I'll add one more

\tl_set:Nn \l_tmpa_tl {xyz}
\int_incr:N \l_tmpa_int`
\dim_set:Nn \l_tmpa_dim { 1pt }
\tl_set_eq:NN \l_tmpa_tl \g_tmpb_tl

All the variables should have been declared before being set. I added the last example to show that a global variable \g_tmpb_tl may be used in the context of a local assignment: the variable \l_tmpa_tl is locally made equal to \g_tmpb_tl.

The corresponding global assignments would be

\tl_gset:Nn \g_tmpa_tl {xyz}
\int_gincr:N \g_tmpa_int`
\dim_gset:Nn \g_tmpa_dim { 1pt }
\tl_gset_eq:NN \g_tmpa_tl \g_tmpb_tl

But the question remains: what's the difference?

A local assignment will affect the variable's value only in the current group and the value will be reset to the previous one when the group ends. This doesn't happen with global assignments: the value will be set at all group levels.

What's a group? Well, this requires some knowledge on basic TeX concepts. A group can be initiated with { and will end at the matching } (but not when TeX is looking for the argument to a macro); or by \group_begin: (that's \begingroup in primitive form) and will end at the matching \group_end: (that's \endgroup); or by \left, ending at the matching \right (or \middle, which is basically implemented as \right.\left).

LaTeX environments start with \begin that will issue \group_begin:; the corresponding \end issues the matching \group_end:, so this is why LaTeX environments form groups.

But groups are initiated also in other situations, the most important being boxes. When you start collecting material to be set in a box, be it \hbox:n or \vbox:n or \vtop:n, but also when \hbox_set:Nn and similar functions, TeX will open a group, ending it when the } ending the collection is scanned. So with

\tl_set:Nn \l_tmpa_tl {a}
\hbox:n { \tl_set:Nn \l_tmpa_tl {b} \tl_use:N \l_tmpa_tl }
\tl_use:N \l_tmpa_tl

you'll get “ba”. The token list variable is set to “b” inside the box, but when the box ends, the previous value is restored. To the contrary, with

\tl_gset:Nn \g_tmpa_tl {a}
\hbox:n { \tl_gset:Nn \g_tmpa_tl {b} \tl_use:N \g_tmpa_tl }
\tl_use:N \g_tmpa_tl

you'll get “bb”, because the assignment inside the box is global.

But what's the connection with your problem? It has to do with alignments. You can think that, when TeX is collecting material for a cell in an alignment (be it tabular, array, align, split, aligned, cases and so on), it does a special operation

\hbox_set_ALIGNMENT:n { ... }

No, there is no such function: the real one is not accessible to the user and is only available at the deep TeX levels where typesetting is done. The made-up name is just to underline that each alignment cell is inside a group.

Now you see wher your problem lies: the material after \begin{align} up to & is inside a group and the assignment \tl_set:Nn \l_tmpa_tl {1} is forgotten as soon as & is scanned and the alignment box is built.

Additional bits

Also declaring a variable is an assignment. For instance

\tl_new:N \l_jumaily_foo_tl
\int_const:Nn \c_jumaily_foo_int { 42 }

You can think to the former as the creation of a pointer to a variable. The pointer and so the variable are created globally, so after the first declaration, the token list variable \l_jumaily_foo_tl will be available at all levels, but assignment of values to it should be local. The second instruction globally creates the constant and globally assigns a value to it.

1
  • I do appreciate the response. Thank you so much for your time and explanation! May 7, 2023 at 21:49
6

Your question is: why & breaks the pattern? The answer is here.

The align environment is based on \halign TeX primitive. Each item in the data part of \halign (separated by &) is packed into \hbox and \hbox opens TeX group, reads the horizontal list and closes TeX group. This is reason, why each part between & is processed in a single group. Each assignment (including \tl_set:Nn which is nothing else than \def primitive) is local, i.e. the value is set only in the scope of the group.

Note that \tl_gset:Nn is equal to \gdef primitive and this assignment is global, independent of the groups.

1
  • Thank you for the straight-to-the-point response. I definitely helps :). May 7, 2023 at 21:50
1

Something like this?

\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\mycmd}{}{
    \begin{align}
        \tl_gset:Nn \g_tmpa_tl {1+k^2}
        x &= \tl_use:N \g_tmpa_tl
    \end{align}
}
\ExplSyntaxOff

\begin{document}
\mycmd
\end{document}
3
  • Thank you for the response. One of the requirements is to not have the scratch variable set outside of the align environment. May 6, 2023 at 19:11
  • Answer updated: just use global variables.
    – projetmbc
    May 6, 2023 at 19:51
  • +1 Thank you for the answer! The next part of the question is why & breaks the pattern? May 6, 2023 at 20:49

You must log in to answer this question.

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