3

What does \csnumgdef do? From code examples, it appears to take two arguments, and one is led to believe that it defines a number var and assigns to it the value val, as in \csnumgdef{var}{val}. If var is being used as a simple counter, what are the advantages/disadvantages of this syntax over something like:

\newcounter{var}
\setcounter{var}{val}

Lastly, what is the etymology of csnumgdef, in particular the cs and the g? I have noticed other commands that appear to be in the cs family, such as \csname, \csuse, and \csdef, but am not familiar with what unites them.

  • What package is \csnumgdef from? (cs stands for "control sequence". \csname, \csnumgdef, \documentclass, \begin, are all examples of control sequences. g possibly means "global", for a global assignment) – Phelype Oleinik Nov 19 at 23:44
  • @PhelypeOleinik: I believe it's not part of any package, but rather is part of the TeX core. For example, it is used here, which uses only two packages (biblatex, filecontents), neither of which mentions csnumgdef in their manuals. Thanks for the explanation of cs and g. – user001 Nov 19 at 23:48
  • 1
    no it is a macro from a package not anything built in to tex – David Carlisle Nov 20 at 0:02
  • 1
    From the three you mentioned (\csname, \csuse, and \csdef), only \csname is a TeX primitive (\csname something\endcsname expands to \something). The other two (and possibly more \cs<whatever> are macros which (usually) use \csname to make a control sequence of the argument. \csuse{<arg>} is just \csname <arg>\endcsname. \csdef{<name>}{<definition>} does \def\<name>{<definition>}. – Phelype Oleinik Nov 20 at 0:11
  • 1
    One more note: If you are not sure if something is a TeX primitive or a macro, you can use \show. If you do \show\csname, TeX will print > \csname=\csname to the terminal, meaning it's a primitive. If you do \show\csdef, TeX will print: > \csdef=\protected macro: #1->\expandafter \def \csname #1\endcsname. – Phelype Oleinik Nov 20 at 0:40
8

\csnumgdef, from the etoolbox package (for you, loaded by biblatex) is defined as:

\newrobustcmd*{\csnumgdef}[1]{%
  \expandafter\numgdef\csname#1\endcsname}

in terms of \numgdef which, in turn, is defined as:

\newrobustcmd*{\numgdef}[2]{%
  \ifundef#1{\let#1\z@}{}%
  \xdef#1{\the\numexpr#2}}

Let's walk an example step by step. Suppose you do \csnumgdef{foo}{1+1}. First, \csnumgdef takes one argument, foo, and does (the {1+1} is still there from the previous step, untouched):

\expandafter\numgdef\csname foo\endcsname{1+1}

The \expandafter skips over \numgdef and expands \csname. \csname builds a control sequence (thus the cs in the name of \csnumgdef) out of everything until the matching \endcsname, which is the argument foo. This becomes:

\numgdef\foo{1+1}

so you can conclude that \csnumgdef{foo} and \numgdef\foo are equivalent.

Now \numgdef expands, grabbing two arguments, \foo and 1+1:

\ifundef\foo{\let\foo\z@}{}%
\xdef\foo{\the\numexpr 1+1}

The \ifundef test checks if \foo is undefined, and does \let\foo\z@ if so, otherwise it does nothing.

Now for the good part: \xdef is equivalent to \global\edef (and now you see that the g in (cs)numgdef stands for \global), which will make a global assignment, and \edef will expand everything inside the definition. It will expand \the, which will trigger \numexpr. \numexpr will then evaluate the integer expression following it (1+1) and leave the result there. After the expansion, you have (sort of):

\global\def\foo{2}

and now things go as usual, and now \foo expands to 2.


In short, \csnumgdef{<name>}{<intexpr>} will evaluate the integer expression <intexpr> and will store it in \<name>. The version without cs in the name takes a control sequence as argument (as opposed to a control sequence name): \numgdef\<name>{<intexpr>}, and the version without g does a local assignment.


These naming conventions are useful (especially when followed correctly ;-) because you don't need to look up the definition of some command to find ouy what it does. If you know that \numdef\foo{1+1} does, then it's not hard to deduce what \csnumdef or \numgdef do (given, of course, you know these conventions).

expl3's conventions define that a function that contains set in its name does an assignment (much like the def in \numdef). If the function is gset then such assignment is global. Knowing that, it's fairly easy to guess what \int_set:Nn do: it's (almost1) the same as \numdef :-)
If you know that, then \int_gset:Nn is easy.

But what about the cs version, you ask. This one is denoted in the argument specification. Instead of a single Normal argument, the argument is a csname. \int_set:cn (equivalent of \csnumdef) and \int_gset:cn (equivalent of \csnumgdef) do exactly that :-)

1 \numdef stores the number in a macro, while \int_set:Nn stores it in a count register.

  • The walkthrough and especially the comparison between \csnumgdef{foo}{val} and \numgdef\foo{val} were most illuminating. – user001 Nov 20 at 0:24
  • 1
    @user001 Glad it helped :-) See the note I added a note on naming conventions – Phelype Oleinik Nov 20 at 0:30
  • 1
    Let's mention that \let#1\z@ within the definition of \numgdef makes it possible to do \csnumgdef{foo}{\csuse{foo}+1} without defining/initializing \foo as in case \foo is undefined, this will define/initialize \foo to be equal to 0. – Ulrich Diez Nov 20 at 11:35
6

\csnumgdef is defined within the etoolbox package. This package "is a toolbox of programming tools geared primarily towards LaTeX class and package authors. It provides LaTeX frontends to some of the new primitives provided by e-TeX as well as some generic tools which are not related to e-TeX but match the profile of this package." (from the etoolbox documentation.

The cs, g and def nomenclature is used through the documentation, roughly defined as

  • cs = <csname>
  • g = global
  • def = \def

Another interpretation is that gdef is similar to \gdef or \global\def (or, possible \xdef - an expanded version of \gdef).


In some contexts, its convenient to just consider the control sequence name (say, foo), rather than the control sequence itself (say, \foo). For example, perhaps you want to define an auxiliary control sequence that should accompany some definition and, for the sake of coding, you use the same basic definition. Here's an example:

\makeatletter
\newcommand{\foo}{foo}
\newcommand{\foo@bar}{bar}
\newcommand{\print}[1]{\csname #1\endcsname: \csname #1@bar\endcsname}
\makeatother

\print{foo}

which prints

foo: bar

It's easy to pass foo to \print and then have access to \foo@bar. However, if you have passed \foo to \print, you'd have to remove the backslash \ in order to string add the suffix @bar and have access to \foo@bar. So, depending on the user (package author), it might be more convenient to work with control sequence names rather than the control sequences themselves.


etoolbox explicitly defines some of these functions in order to force a specific use. \csnumgdef{<var>}{<val>} is not the same a

\newcounter{<var>}
\setcounter{<var>}{<val>}

since <var> in \csnumgdef is not a counter. Instead, it's a regular control sequence. However, since <val> is evaluated using \numexpr, only arguments that are valid in that context is accepted. So, it may seem similar to using a counter, but internally it's different. Since it uses \numexpr, you can do something like \csnumgdef{foo}{5+2} and have 7 stored in \foo. You don't need \thefoo to print the number if you'd gone the route of defining a counter.

  • Thanks for explaining the nomenclature as well as for clarifying that the first argument of csnumgdef is a control sequence name rather than a variable. – user001 Nov 20 at 0:18

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.