I am trying to learn the LaTeX3 syntax. One of the questions I have come up with is how to define a variable, i. e. a macro without arguments in TeX parlance, with local scope within a group.

In TeX a \def'ed macro is local to the group where it was defined. If \tl_new:Nn is the LaTeX3 counterpart of \def\...{...}, I expect the variable \world to be local to the group as well, but the following code compiles without error:




hello \world

Why is \world visible outside the group?

  • Note for future readers: \tl_new:Nn has been deprecated for some months (but was not when the question was asked). Now, use \tl_new:N to declare the variable, then later on \tl_set:Nn to set the variable locally (or \tl_gset:Nn for a global assignment). – Bruno Le Floch Jul 19 '14 at 15:42

\tl_new:XXXX is not like \def but more like \newcommand: it declares a new command to hold content. The content is filled with \tl_set and there a local and a global variants exist: eg. \tl_gset:Nn and \tl_set:Nn.

Btw: Your example doesn't work for me, I get

! Undefined control sequence.
l.10 \begin_group

with a recent expl3 from miktex updated 2 days ago.

  • I see. Distinction between local and global scope is made during setting the variable's value, not on its declaration. Thanks, this is sufficient as an answer. – AlexG Mar 28 '11 at 10:38

To answer the implicit question here (‘why is this the case?’), all of the \«variable»_new:N commands create global registers or macros. So for consistency so does \tl_new:Nn. We discussed adding also \«variable»_new_local:N (see etex.sty for an example of local registers in TeX) but decided that the benefits didn't outweigh the downsides:


  • Nice to have local registers (but not necessary)


  • Complicates the syntax and documentation, since we'd then need to explain when/why you'd want to use them.

I liked the idea of writing

  \int_new:N \l_track_loop_int
  « do stuff with \l_track_loop_int »

but in the end the big problem was:

  • Local macros behave differently from local registers, which would kill consistency between the tl datatype and all others like int, dim, etc. (And we weren't about to write an allocation system for macros, since efficiency would suffer for very little upside.)

As an example, if the \«var»_new_local:N allocators existed:


  \tl_new_local:N \foo
  \tl_gset:Nn \foo {hello}

  \dim_new_local:N \baz
  \dim_gset:Nn \baz {1pt}


In such a construction, \foo would still be available after the group, whereas \baz would not. (Note that globally setting a local variable is perfectly valid.) This was a sufficiently major edge case (in my mind) to definitively decide against the idea.

So the recommended system is to formally declare all variables you intend on using (either lumped together at the beginning of the package or interleaved as you first use them). There's no technical problem, however, with using \tl_set:Nn within a group to create a scratch macro if you need.

  • Thanks for your explanations! I am beginning to understand. +1 – AlexG Mar 28 '11 at 10:56
  • could you please elaborate a bit on the differences between registers and macros that led to this decision? – Philipp Mar 28 '11 at 17:25
  • 1
    @Philipp Sorry I missed that detail originally. See the update above. – Will Robertson Mar 29 '11 at 5:15

\tl_new:Nn expands to \chk_if_free_cs:N#1\cs_gset_nopar:Npn#1{#2} and \cs_gset_nopar:Npn is \gdef. So it gives you a global definition.

  • Thanks! So why isn't there a local form as for functions? Are local variables deprecated in LaTeX3? Do I have to resort to \def in case I want local variables? – AlexG Mar 28 '11 at 10:06
  • 1
    Why not simply \tl_set:Nn\world{world!} ? Btw: I just checked, \begin_group and \end_group should be this: \group_begin: and \group_end: – Ulrike Fischer Mar 28 '11 at 10:15
  • @ulrike. I see, \tl_set:Nn does not require a prior \tl_new:Nn and \tl_set:Nn is local to its group. – AlexG Mar 28 '11 at 10:33

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.