TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to learn how to use expl3 and am a little confused and could use some direction.

I'm trying to figure out this whole naming scheme for variables and functions as addressed in the expl3 documentation, and cannot figure it out. There is quite a lot of text dedicated to talking about name space, but are there actually global variables and functions? Or is it simply an artificial creation using a strict naming scheme.

Second, can I get an example of a function that would do the following without using any extra packages other than expl3? Or is that something that would be out of the expl3 scope. What I am trying to get out of this is a way to program essentially in a c or java like manner.

void myexamplefunction(int count, string[] line){
    for(int k = 0; k > count; k = k + 1){
        print k;
        print line[k];
    }
}

The function takes in an integer called count and a string array called line. It will then using a for loop iterate k from 0 to count, printing the number k (the current iteration number) followed by the string from line associated with k.

Thanks a bunch.

share|improve this question
    
The idea of namespaces is absolutely contrived in expl3. As a general rule, all definitions are global (to the current group). For some interesting stuff with pure expl3, check out my termmenu package on CTAN. – Sean Allred Jan 28 at 22:14
    
@SeanAllred I'm not sure what you mean 'global to the current group'. Either they are global or they are local (restricted to the current group). (OK, some box stuff is a bit weird ...) – Joseph Wright Jan 28 at 22:24
    
typo: k > count. you mean k < count, right? – Mark Jan 28 at 23:47
    
@JosephWright I picture TeX groups like layers of an onion: 'local to the current group' is existing only in one layer; 'global…' would be existing in that layer and all outer layers. – Sean Allred Jan 29 at 0:07

There are no functions or variables as you would think of them in another language like perl or java or most any other programming language you might like. LaTeX works by expanding control sequences into tokens and then further expanding those tokens. On the surface, it may look like you have variables and functions, but that's not at all what's happening.

Beginners of LaTeX can perhaps get away moderately harmlessly thinking in terms of functions and variables. But in the long run, this sort of thinking will frustrate you and get in the way of writing the code you want to accomplish what you want.

You need to keep in mind what LaTeX (and ultimately TeX) was designed to do: format text. As such, it doesn't really have data structures. What's nice about Expl3 is that it creates the feel of having a variety of data structures to choose from (and, if it creates that feel is that really any different from actually having them?). Nevertheless, Expl3 provides a variety of tools for managing and manipulating textual content, but at heart it's still inhabiting the same world as LaTeX/TeX where it is tokens and their content that your are working with. Ultimately, if you're going to write code in LaTeX, you will have to come to understand what's happening under the hood.

So when we write

\newcommand\mycommand[1]{do something with `#1'}

all that \mycommand is really doing when it is used is expanding into whatever was placed between its defining brackets. And when we use it, it just expands as:

\mycommand{stuff}->do something with `stuff'

A lot of the functionality (pun intended) of some very nicely written packages such as pgf is how this expansion process is taken advantage of so that on the surface the code is easy to write. But underneath the hood, there's a lot going on.

Likewise, when you get to Expl3, things are really no different. Expl3 is providing control sequences that have been carefully defined to give the appearance of functioning in a particular way.

\tl_new:N \l_ae_variable_tl

may look like variable declaration, but it's just priming things for a later

\tl_set:Nn \l_ae_variable_tl {content}

And I think the idea is that at some point there will be bells and whistles built into \tl_set:Nn to make sure that the following control sequences has already been primed. But currently, this is really nothing more than

\let\l_ae_variable_tl

and then later

\def\l_ae_variable_tl{content}

I may be wrong in the particulars of whether \tl_new:N is essentially letting to \relax, but my point is that it's still operating under the same principals of LaTeX/TeX.

Here's an approach to create the sort of functionality you want. I've taken a slightly different approach than Manual (and I think his use of \int_step_inline:nnnn is cleaner and perhaps clearer)

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn

\int_new:N \l_ae_count_value_int

\cs_new_protected:Nn \__ae_space: { ~ }

\cs_new_protected:Npn \myexamplefunction #1#2 {
  \int_set:Nn \l_ae_count_value_int {0}
  \noindent
  \tl_set:Nn \l_ae_string_tl {#2}
  %% make sure that spaces in the user passed string don't
  %% get obliterated by the inline map
  \tl_replace_all:Nnn \l_ae_string_tl {~}{\__ae_space:}
  \tl_map_inline:Nn \l_ae_string_tl
    {
      \int_use:N \l_ae_count_value_int
      ##1
      \newline
      \int_incr:N \l_ae_count_value_int
      \int_compare:nT
        { \l_ae_count_value_int > #1 }  
        { \tl_map_break: }
    }
}

\ExplSyntaxOff

\begin{document}

\myexamplefunction{5}{this is my string}

\end{document}
share|improve this answer
    
Very precisely written -- Being a C(++) programmer myself it's completely different to program with LaTeX/TeX etc. compared to most languages -- something I had to learn in the transition from a regular user to a (La)TeX 'programmer' – Christian Hupfer Jan 28 at 21:53
    
Isnt the relation of LaTeX to TeX analogous to that of C and assembly? While I do understand that the main purpose is to format text I want to be able to create high-level functions to use in class files that can be repeatedly used to generate formatted text from multiple variables. – Bob Jan 28 at 21:57
    
@Bob Perhaps that was in the back of Leslie Lamport's mind when creating LaTeX. But in practice, people mix LaTeX and TeX coding in a way that I've never seen done with C and assembly. But that could just be due to my lack of coding experience with C. – A.Ellett Jan 28 at 21:59
    
@A.Ellett When Lamport was writing LaTeX it really wasn't possible (memory-wise) to provide a programming layer other than 'use TeX here'. – Joseph Wright Jan 28 at 22:05

It's important to start by remembering that expl3 is a language ultimately written in TeX primitives, which means it is a a macro expansion language. Whilst expl3 provides various abstractions and as far as possible is intended to be understood/documented 'on its own terms', that is not yet complete and there is sometimes a need to know some 'raw' TeX. That's particularly true where there are still things to be worked out, and complex data structures are such an area.


In terms of variable scope, TeX and thus expl3 works on the basis of explicit begin/end group markers

\tl_set:Nn  \l_tmpa_tl { abc }
\tl_gset:Nn \g_tmpa_tl { abc }
\group_begin:
  \tl_set:Nn  \l_tmpa_tl { 123 }
  \tl_gset:Nn \g_tmpa_tl { 123 }  
\group_end:
\tl_show:N \l_tmpa_tl % abc
\tl_show:N \g_tmpa_tl % 123

The difference in naming here is one of convention (e.g. \tl_gset:Nn \l_tmpa_tl will work, at least unless extra checking is set up). The reason for the convention is that TeX has to keep a track of local values for variables, and mixing local/global freely will lead to save-stack exhaustion ('bad news'). The approach that variables are set only locally or only globally helps to avoid that.

Note that \tl_new:N and so forth globally allocate the name even if for local variables. The team did explore alternative approaches in which variables can be declared locally, but these seemed to work poorly with the fact that TeX scoping is based on explicit groups.


Before tackling the requested 'function translation', it's worth noting what relevant data structures are currently available. The most basic data structure is the token list (tl): a load of tokens with no defined internals at all (TeX and so expl3 deals with tokens). We do have a string data type, which is a special form of the tl in which all characters are 'other' except spaces which are still normal spaces. It's not clear, but I don't think you actually want a TeX string.

Building on the tl we have sequences (seq) and property lists (prop). A seq is an ordered data type which is good for mapping but can also be accessed numerically (indexing from 1 for reasons that would be best I think in a separate question). A prop is a key-value data structure without any defined key order. Thus at present there is no 'array' in a general sense. To understand some of this requires some insight into implementation but also into why they've been implemented.

At present, both seq and prop structures are constructed with the data contained within a single tl. This is partly for historical reasons (TeX systems in the past were much more limited in terms of csnames than they are today), but partly as this approach makes certain use cases easier. Copying a single tl is easy (a one-step process) and it is trivial to implement mappings. On the other hand, this approach makes random access somewhat slower, particularly when expandable. As detailed in How to implement (low-level) arrays in TeX, the fastest approach to making an array-like structure in TeX is to use a series of names and rely on the hash table for access. That though makes operations such as mapping harder, and also ultimately may make it more likely that name storage will be exhausted.

The team have had various discussions and attempts focussed on creating new data types. However, these have not progressed as we are mindful of the need to cover some extensible form (for example, nesting arrays in arrays, etc.). At the same time, the current data formats are there as they have concrete use cases for the team. Use cases for TeX/typesetting are what is important here. (One can implement all sorts of things in TeX but that does not necessarily make it a good idea!) The net result of this is that at present there is not a single 'array' data structure that does everything which might be wanted.

As indicated by the other answers, there are various formulations one might use to implement the request. It's not clear for example exactly what other uses the data is for, whether expandability is required, whether the lists may be large (performance considerations), etc. One possible approach is

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\seq_new:N \l__bob_tmp_seq
\int_new:N \l__bob_tmp_int
\cs_new_protected:Npn \bob_print:nn #1#2
  {
    \group_begin:
      \seq_set_split:Nnn \l__bob_tmp_seq { \n } {#1} 
      \int_zero:N \l__bob_tmp_int
      \seq_map_inline:Nn \l__bob_tmp_seq
        {
          \int_incr:N \l__bob_tmp_int
          \int_compare:nNnT \l__bob_tmp_int > {#2}
            { \seq_map_break: }
          ##1
          \c_space_tl
          \tl_use:N \l__bob_tmp_tl
          \par
        }
    \group_end:
  }
\bob_print:nn { a \n b \n c \n d \n e } { 3 }
\ExplSyntaxOff
\end{document}

whilst others (particularly faster ones) would feature a hash table based appraoch (at the cost of being very much low-level TeX 'dressed up'). In the above, I've used a mapping rather than \seq_item:Nn (index loop-up) for performance reasons. The latter approach has to read through the sequence at each step (at least with the current implementation) so will be poor for long sequences. On the other hand, the mapping approach already has the items available with a fast int operation keeping track of position. (Using a hash table array we can do direct access quickly.)

share|improve this answer
    
I'm going to miss out a few very 'TeXnical' points unless people really want them in (e.g. TeX registers which are always global, clever ways the save stack can be exhausted, ...) – Joseph Wright Jan 28 at 22:00
    
In case this influences your decision I know very little plain Tex. That said it is probably something I should learn (but If I can stick to high level expl3 things for now that might be best) you decide. – Bob Jan 28 at 22:14

I'm not official, but I would answer are there actually global variables and functions? with a NO. The only flexibility you have is that you can set a macro in the current group so the definition “ends” at the end of group, or you can set it globally, but there's no special behaviour. Disclaimer: non-programmer talking here.

About the function:

\documentclass{scrartcl}

\usepackage{expl3}

\begin{document}

\ExplSyntaxOn
\cs_new_protected:Npn \bob_examplefunction:nn #1 #2
 {
  \int_step_inline:nnnn { 0 } { 1 } {#1}
   { Iteration ~ ##1 ~ results ~ in ~ ``\tl_item:nn {#2} { ##1 + 1 }''.\par }
 }
\bob_examplefunction:nn {5} {Whatever}
\ExplSyntaxOff

\end{document}

Plus, if you need an interface, load xparse and

\NewDocumentCommand \printfirstnitems { m m }
 { \bob_examplecommand:nn {#1} {#2} }

and then

\printfirstnitems{5}{Whatever}

Okey, so you don't want a string (tl = token list) but an array, sorry for the misunderstandment. The nextmost thing to an array is a seq

\seq_new:N \l_bob_array_seq % you need to declare it, l_ shows it's local, `_seq` shows it's a seq
\cs_new_protected:Npn \bob_examplefunction:nn #1 #2
 {
  \seq_set_split:Nnn \l_bob_array_seq { , } {#2}
  \int_step_inline:nnnn { 0 } { 1 } {#1}
   { Iteration ~ ##1 ~ results ~ in ~ ``\seq_item:Nn \l_bob_array_seq { ##1 + 1 }''.\par }
 }

The problem is that spaces matter in TeX after all, so you would get unwanted spaces. You could use clist type that is similar to a seq but it's oriented more to user usage, and, apart from other things, it does ignore spaces around commas (plus, in this case, you can avoid the need to declare a _clist altough it would be probably better).

\cs_new_protected:Npn \bob_examplefunction:nn #1 #2
 {
  \int_step_inline:nnnn { 0 } { 1 } {#1}
   { Iteration ~ ##1 ~ results ~ in ~ ``\clist_item:nn {#2} { ##1 + 1 }''.\par }
 }
share|improve this answer
    
Can you make it work to use a string array? For example instead you could call \bob_examplefunction:nn {5}{One, Two, Three, Four, Five, Six}, and it would print the first 5 numbers. And to clarify, I am just using that syntax as an example. I dont know how to define an array in latex yet. – Bob Jan 28 at 21:17
1  
@Bob That's a comma list! – Joseph Wright Jan 28 at 21:19
    
Oops I just edited the last comment before I saw your reply Joseph, I am not sure how to actually make an array in LaTeX yet, how can I? (Be it an integer array, string array, boolean array, or whatever.) – Bob Jan 28 at 21:22
    
@Bob I thought you wanted the items from a string. Just replace \tl_item:nn to \clist_item:nn. The nextmost thing to an array is a seq in expl3. – Manuel Jan 28 at 21:27
    
Can you explain the difference between a seqand a tl? – Bob Jan 28 at 21:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.