LaTeX3 provides the two modules seq and clist.

What is the difference?

The module clist is introduced by

Comma lists contain ordered data where items can be added to the left or right end of the list.

The module seq is introduced by

LaTeX3 implements a “sequence” data type, which contain an ordered list of entries which may contain any balanced text.

What are the benefits and drawbacks of the modules?

2 Answers 2


The two modules share a lot of features, and at there are many tasks which can in principle be tackled using either. To understand the reason for the existence of both, I'll first highlight what seq can do that clist cannot.

A comma-separated list looks something like


which means that most obviously the items cannot contain a comma (without brace protection). On the other hand, the seq data type is constructed such that an item may contain any balanced text. That includes not only commas, but also crucially empty entries.

The latter point occurs because a comma list is essentially a 'user facing' structure, whereas a sequence is meant for programmers. You'll also see this if you try adding a space to a comma list: spaces are trimmed from comma list items, and so something like

a, b , , c , d

is treated identically to


As sequences have an internal structure to support programmers, it's also possible to optimise the implementation rather more than it is for comma lists. That has consequences for performance in some cases.

So in terms of which is appropriate, I would favour comma lists when dealing with stuff toward the user level, for example where user input/output is required. On the other hand, totally arbitrary lists of items are better handled as sequences. There is an element of personal preference in the middle ground (where both will work).

In the past, I have suggested dropping clist functions entirely except for a conversion layer (so that we would have a single 'true way'). However, if cases where basically everything can be handled using a comma list there is a performance hit to this that is hard to justify.

  • I still don't understand what need there is for clist. From your answer it sounds like it's entirely redundant. You mentioned in the end that dropping clist would incur a performance hit, but then earlier in your answer you wrote that sequences have a more optimized implementation than comma lists. And a comma list literal can always be converted to a sequence with \seq_set_split:Nnn \l_my_seq {,} {<token list>}, and converted back to a comma separated list with \seq_use:Nn \l_my_seq {,}.
    – Evan Aad
    Sep 29, 2017 at 15:18
  • 1
    @EvanAad Comma lists are very common and handy as you can type them in directly (a lot of the time you don't need empty entries or the like). There's a performance hit to any conversion, so for example if we have a comma list input and then do a mapping, with no complex manipulation, we avoid the two-steps we'd need if we dropped clist functions entirely. There's also the case where both the input and the result are comma lists: two conversions would be somewhat over the top.
    – Joseph Wright
    Sep 29, 2017 at 15:49
  • @EvanAad I was the person suggesting we drop clist ('one true way'), and in the end it didn't feel that great a plan. Contrast the old toks module, which we dropped when we made tl general. (You might need to look a long way back in the SVN to see this, so tl might be called tlp!)
    – Joseph Wright
    Sep 29, 2017 at 15:50

According to interface3.pdf (texdoc interface3), seq is "safer", faster and provides more features than clist. Moreover, seq is used by the regex module. For all these reasons, there "is" no need to use clists at all.

In fact, this is not so obvious. To complete Joseph's answer focusing on what seq can do that clist cannot, here is the opposite.

First we have \clist_reverse:n, for which we can generate variants, whereas there is only \seq_reverse:N. Similarly, there is a handy \clist_map_inline:nn.

Most importantly is the management of the arguments:

\seq_put_left:Nn ⟨sequence⟩ {⟨item⟩}
\clist_put_left:Nn ⟨comma list⟩ {⟨item1⟩,...,⟨itemn⟩}

clist allows to add many items at once with a single instruction.

clist can be added as sequence items and property values, like token lists. Whether it is similarly possible for seq is not clear (it is de facto possible, but may not be supported)

\l_my_clist is a shortcut for \clist_use:Nn \l_my_clist {,}

In l3keys module, the tl variable used are in general clist, for example,

\keys_set_known:nnN {⟨module⟩} {⟨keyval list⟩} ⟨clist var⟩
  • 1
    I disagree on many respects. You can store something like a,b,c in a property list or a sequence, but this is not a clist: it can be interpreted as such, if used as the argument to a function that accepts it and transforms it into the “internal representation”. It just happens that the internal representation of a clist variable is quite similar to the “external” one. You can store in a property list the name of a clist variable, which is quite different from storing the clist.
    – egreg
    Mar 5, 2022 at 14:22
  • 1
    And \l_my_clist isn't a shortcut for \clist_use:Nn \l_my_clist{,}. With the current implementation of clist variables they do the same, that's true, but the reason is that we only have macros to store things and, currently, the internal structure of a clist variable is essentially like the external one. Running on a tapis roulant under a shower has essentially the same effect as running outside under the rain, but they're not the same thing.
    – egreg
    Mar 5, 2022 at 14:24
  • interface3.pdf, p170 first line: "Because comma list variables are token list variables, expanding them once yields their items separated by commas, [...].". As you can add tl to sequences and property lists, the same holds for clists. Mar 5, 2022 at 15:01
  • 1
    \clist_set:Nn \l_tmpa_clist {1,2} \seq_clear:N \l_tmpa_seq \seq_put_right:Nn \l_tmpa_seq { \l_tmpa_clist } \clist_set:Nn \l_tmpa_clist {a,b} What happens if you deliver \seq_item:Nn \l_tmpa_seq {1}? You get a,b and not 1,2. You can store in a sequence something that can be interpreted as a clist, with \seq_put_right:Nn \l_tmpa_seq { 1,2 }, but you haven't stored a clist variable.
    – egreg
    Mar 5, 2022 at 15:09
  • \seq_put_right:Nn stores the clist variable and not the clist. To store the clist, you can use \seq_put_right:No instead, or \seq_put_right:NV \l_tmpa_clist (without braces) Mar 5, 2022 at 15:26

You must log in to answer this question.

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