nsajko
Taking a look at expl3.pdf and interface3.pdf, I don't understand when are "local" variables supposed to be used, or how to declare a local variable at all.

As far as I understand expl3.pdf, global variables have the g_ prefix in their names, and shouldn't be assigned to *locally*, i.e., they should never be assigned to with the set functions, but gset assignments are fine. Local variables, on the other hand, have the l_ prefix, and shouldn't be assigned to with gset functions:

> **g** variables whose value should only be set globally

> **l** variables whose value should only be set locally

On the other hand, expl3.pdf says that each variable should be declared before it being assigned to:

> In well-formed expl3 code, variables should always be declared before assignment is attempted. This is true even for variable types where the underlying TEX implementation
will allow direct assignment.

However, taking a look at interface3.pdf, it seems that there's no way to declare a local variable?! It seems that all types have the _new:N function, which is documented as creating a *global* declaration. Take dim, for example:

> \dim_new:N ⟨dimension⟩
>
> Creates a new *⟨dimension⟩* or raises an error if the name is already taken. The declaration
is global. The *⟨dimension⟩* is initially equal to 0 pt.

Can anyone resolve this confusion, and give examples of correct usage of local variables, if possible?

EDIT:

Looking at the TeX Stack Exchange, it seems that the the \dim_new:N declaration is good for both local and global variables, but, confusingly, the declaration itself is global in *another* sense. The docs should really be clarified somehow.

One further thing that's confusing me is how do the functions \group_begin: and \group_end: tie into this topic, if at all? Is their purpose to give scope to local variables, or is it something completely different? EDIT: found the answer here: https://www.texdev.net/2011/12/26/programming-latex3-token-list-variables/
Joseph Wright
As the documentation says, variables should be either _assigned_ locally or globally. However, expl3 _declares_ all variables globally. I suspect the confusion arises as you are seeing \<thing>_new:N as an assignment, which while true at the underlying engine level is not what we mean in the documentation when we talk about the _programmer_ making an assignment.

Thus the expectation is that variables are declared using <thing>_new:N _in all cases_. They are then assigned using gset or set as appropriate to their scope behaviour. Indeed, I would expect that most variables are declared at the top level, which is global automatically and where the fact that \<thing>_new:N acts globally is not important.

----

To understand the approach taken in expl3, it's best to start by remembering that scope in TeX is created explicitly by { ... } or \begingroup ... \endgroup primitives, or by a small number of built-in contexts (like \halign cells). Assignments are then _within_ the scope that surrounds them, but not restricted to one group level:
latex
\def\foo{a}
\begingroup
\show\foo
\def\foo{b}
\begingroup
\show\foo

will show \foo is a then b.

At the same time, intermixing local and global assignments leads to what is called 'save stack buildup'. Thus it is best to use a macro or register as always-local or always-global.

The team did experiment with 'local new' variable declaration, which is technically feasible (other than the very minor wrinkle that entries to the hash table cannot be removed). However, as this suggested a more 'functional language' local/global split than exists in TeX, we decided against it.

(Save stack buildup is not an issue as the only time a global assignment happens to a local variable is at point-of-declaration.)
nsajko
I'd say the answer here is basically such: local variables respect scopes, while global variables don't. But:

1. The programmer is responsible for making local variables respect scope, in that the programmer must correctly choose not to use the gset version of an assignment. The expl3 debugging functionality is there to help.

2. The programmer is also responsible for setting up each scope. The scopes are not syntactically determined, like in other programming languages, rather a scope lies between the commands \group_begin: and \group_end:.

Each declaration, for both local and global variables, is global, i.e. a variable exists globally whether it respects scopes or not.