Take the 2-minute tour ×
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.

I'm trying to create a package for drawing simple sequence diagrams using PGF/TikZ. Here is the basic idea I'm stuck at (not the whole idea to make it short):

Let's say we have 1 environment (say myseqdiag) & 1 command (say createobject) in this package.

The user would use these as follows:

\begin{myseqdiag}
\createobject{my name is A} 
\createobject{my name is B}
  %<here, other calls to createobject>
\end{myseqdiag}

Calling the command createobject causes a counter objcounter to be incremented, and would store #1 (hopefully) in a variable called obja (if there is such thing as "variable" in TeX/LaTeX).

At the environment end, the code should use the final count and use the stored "variables" ("my name is A", "my name is B"....) in drawing the objects (lifelines).

The problem is that I'm not able to store these parameters.

I tried

\def\obj\alph{objcounter}{#1}

inside the code of createobject, hoping that it would define obja, objb, ..., but it's not working.

I also tried other variations that did not work.

I'm newbie to LaTeX, and I'm missing the concept of variables & arrays as in programming languages. So is there a solution to my problem?

Thanks in advance for any help.

share|improve this question
    
@John: Welcome to tex.sx! It's not necessary to sign your questions (as there is already a box with your username below it) or to begin them with a greeting. –  lockstep Apr 28 '11 at 18:06
    
Such a thing is certainly possible but this may not be the easiest to implement. Can you give a link to such a "simple sequence diagram" that you're trying to recreate? –  Matthew Leingang Apr 28 '11 at 18:17
    
I'm low on time, sorry, but a quick answer is that you can build the name of a control sequence through \csname ...\endcsname. In your case, \expandafter\def\csname obj\alph{objcounter}\endcsname{#1}. –  Bruno Le Floch Apr 28 '11 at 18:20
    
Stefan, sorry I again have to post an answer not a comment because I didn't reach reputation of 50, and I don't see any means to add a comment to my own question, besides, I recently created an account (Open ID), so I'm not "me" any more :) Andrew, yes now I see that your answers goes one step further (didn't notice that before), and it works! I also tried Yiannis' one and it basically works too. –  John Kirollos May 1 '11 at 0:09
    
@John: I've converted your answer to a comment, and merged your accounts. –  Joseph Wright May 1 '11 at 6:27
show 1 more comment

3 Answers

up vote 7 down vote accepted

I'm missing the concept of variables & arrays as in programming languages...

TeX allows you to define your own data structures and associative arrays are sort of built-in. You can think of macros as associative arrays.

Normally a task like the one you are describing I would tackle it as a two step approach.

First you define a list for example \def\alist{foo,bar,beer}

Secondly when you define a command with one of the automatic ways described by the other posters you add the name onto the list as well.

This way you can iterate over the list and effectively you have created an array of objects. See the minimal below.

   \documentclass{article}
    \usepackage{pgfplots}
    \begin{document}
    \makeatletter
    \gdef\alist{john,}
    \def\addtolist#1#2{\g@addto@macro{#1}{#2,}}
    \def\CommandFactory#1#2{%
      \expandafter\def\csname#1\endcsname{#2}
      \addtolist{\alist}{#1}
    }
    \CommandFactory{George}{George's commands}
    \CommandFactory{Mary}{Mary's commands}
    \CommandFactory{foo}{foo commands}
    \CommandFactory{bar}{\tikzpicture
        \axis[stack plots=y]
        \addplot coordinates
            {(0,1) (1,1) (2,2) (3,2)};
        \addplot coordinates
            {(0,1) (1,1) (2,2) (3,2)};
        \addplot coordinates
            {(0,1) (1,1) (2,2) (3,2)};
        \endaxis
    \endtikzpicture}

    %loop through all the records
    \@for \i:=\alist \do{%
      \@nameuse{\i}

    }

    \makeatother
    \end{document}

I have kept the code to the bare minimum to make it more clear.

share|improve this answer
add comment

I see that you have multiple questions - I will try to answer some of them:

Let's start with the simple ones: TeX knows about variables (although they are different from what you know from other languages). But it does not really know anything about arrays, although there are packages around which simulate arrays by means of TeX arrays. This note applies to TeX as it was around for years -- the new LuaTeX project may change this.

Anyway, there is a solution to your problem:

\setcounter{objcounter}{1}
\def\createobj#1{%
    \expandafter\def\csname obj\alph{objcounter}\endcsname{#1}
}
\createobj{Something}

will do the job. The main point is the \expandafter: it changes the execution sequence such that when TeX sees the \expandafter, it will look after the immediately following token \def and expand what comes afterwards. In our case, there is \csname obj\alph{objcounter}\endcsname. This expands to a "Control Sequence Name", namely \obja (since \alph{objcounter} expands to a). Then, the \expandafter is removed from the input list and TeX sees only \def\obja{#1} which is precisely what you want.

You may want to read further literatur about all these commands (see below).

Note that you do not need \alph here. In fact, it might be more appropriate to use numerical indices (but that's up to you).

When I learned about TeX, I found it quite difficult to find good (free) resources. The best resource around is - in my humble opinion - the TeXbook of Donald Knuth (I believe its source code is available online under certain conditions?). I also found a free TeX book (but it was in german, unfortunately; its link is in the TeX-Programming-Notes.pdf listed below).

Since I have been working much more on programming (with TikZ/pgf as well) rather than typesetting, I startet a collection of TeX programming notes, especially about fine-grained expansion control (\expandafter is only one of the expansion control mechanisms of TeX). If you are interested, you may take a look at the "TeX-Programming-Notes.pdf" which is available on http://pgfplots.sourceforge.net .

share|improve this answer
    
Ok, there have been multiple concurrent answers or comments - funny :-) –  Christian Feuersänger Apr 28 '11 at 18:55
    
As Christian says, you can see the source for The TeXbook for free. I'd also recommend TeX by Topic, which is freely-available (try texdoc texbytopic at the Command Prompt/Terminal). –  Joseph Wright Apr 28 '11 at 19:50
    
@Christian: I skimmed through the programming notes, and they look like a good introduction to programming in TeX. A few typos that I noted: p.3, 1sp=2^{16}pt should be the opposite ; p.16, the \countingloop example should have a few more %, which are there to avoid spurious spaces or keep spaces at the end of numbers. –  Bruno Le Floch Apr 29 '11 at 2:31
    
@Bruno thank you for your feedback - I will adjust these things. –  Christian Feuersänger Apr 29 '11 at 15:50
    
@Christian: I'm thinking of writing a "dirty tricks" follow-up on expansion control (and by dirty tricks I mean much worse stuff than what Knuth mentions in the TeXbook's Appendix D... admittedly using eTeX). But first I must master expansion to the point of writing an expandable floating point expression parser. –  Bruno Le Floch Apr 29 '11 at 17:27
show 2 more comments

To answer the immediate problem, there is a way to define a command with a name that can change. The \csname primitive is for this sort of situation. You do something like:

\expandafter\def\csname obj\alph{objcounter}\endcsname{#1}

inside your command. When you want to use these commands, you use the same syntax:

\csname obj\alph{objcounter}\endcsname

Notes: the space after \csname is purely to mark the end of the \csname command, and there is no backslash before the obj - that's sort of implicitly put there by the \csname.

(But as Matthew said, this might not be the easiest way to do what you're trying to do ...)

share|improve this answer
    
(I see that Bruno's just posted the same thing as a comment.) –  Andrew Stacey Apr 28 '11 at 18:26
add comment

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.