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 would like to use \foreach to replace the next code :

\def\x{0}
\edef\y{\x}     
\xdef\z{(b\y)}       

\def\x{1}
\edef\y{\x}
\xdef\w{\z(b\y)}     

\def\x{2}
\edef\y{\x}
\xdef\z{\w(b\y)}  

\def\x{3}
\edef\y{\x}
\xdef\w{\z(b\y)}     
\w 

The aim is to get this result : (b0)(b1)(b2)(b3) with a macro

I got the result with \toks but perhaps it's possible to avoid this.

\documentclass{article}
\usepackage{tikz}

\begin{document}

\makeatletter
\toksdef\toks@=0 %  ?
\toksdef\toks@@=1 % 
\xdef\tmp{}%

\foreach \x in {0,1,2,3}{%
    \toks@\expandafter{\x}%
    \toks@@\expandafter{\tmp}%
    \xdef\tmp{\the\toks@@(b\the\toks@)}%
 }
\makeatother 
\tmp
\end{document} 

I think this code is not nice. What is the better way to get the result without an extern package ?

share|improve this question

3 Answers 3

up vote 7 down vote accepted

The LaTeX kernel provides \@for that doesn't work in groups like \foreach:

\def\tmp{}
\@for\next:=0,1,2,3\do{\edef\tmp{\tmp(b\next)}}

In your code there's no need for \toks:

\foreach \x in {0,1,2,3}{%
    \xdef\tmp{\tmp(b\x)}%
 }

would work as well.

However, if the items are "dangerous" in the sense that they don't survive \edef (like \textbf or other similar tokens), using token registers is necessary for avoiding complete expansion and your way is good. It's better to use \toks2 and not \toks1 for local assignments, so you should do

\toksdef\toks@@=2
share|improve this answer
    
yes I know that but I would like to use \foreach because I used often \foreach and I like some options of this macro. –  Alain Matthes Apr 7 '13 at 17:59
    
@AlainMatthes If you don't want to use an external package you don't have \foreach. –  egreg Apr 7 '13 at 18:02
    
:) ! I wanted to say only pgffor and not another package. I load always tikz in my works also I can work with pggfor and pgfkeys. –  Alain Matthes Apr 7 '13 at 18:20

Using a big package loop structure is really overkill for this, as a single \def is enough

\def\x#1{\ifnum\numexpr#1\relax>0 \x{#1-1}\fi(b\the\numexpr#1\relax)}

\typeout{\x{3}}

produces

(b0)(b1)(b2)(b3)
share|improve this answer
    
Very interesting and efficient but the loop structure (here foreach ) is useful for other tasks. –  Alain Matthes Apr 7 '13 at 19:20
5  
@AlainMatthes usefulness is a very over-rated concept:-) –  David Carlisle Apr 7 '13 at 19:27
    
I can share this point of view :) –  Alain Matthes Apr 7 '13 at 20:20

If you are using pgfkeys and pgffor (which is internally used by the .list handler), you can simply use the .list handler.

If you only need the sequence (b0)(b…)b(3) typeset, you can set up one .code key and use that key with the .list handler. (→ do)

However, if you want to have an expandable macro, this macro has to be fixed (→ doo, equivalent to \foreach \x in {0,...,3}{\xdef\tmp{\tmp(b\x)}}) or you need more than one key (→ dooo, more flexible).

Code

\documentclass{article}
\usepackage{pgfkeys,pgffor}
\makeatletter
\pgfkeys{/alain/do/.code=(b#1)}
\pgfkeys{/alain/doo/.code=\edef\tmp{\tmp(b#1)}}
\pgfkeys{/alain/dooo ini/.code=\let\qrr@doo@temp\pgfutil@empty,
         /alain/dooo/.code=\edef\qrr@doo@temp{\qrr@doo@temp(b#1)},
         /alain/dooo set/.code=\let#1\qrr@doo@temp}
\makeatletter
\begin{document}
\pgfkeys{/alain/do/.list={0,...,3}}

\def\tmp{}
\pgfkeys{/alain/doo/.list={0,...,3}}
\tmp

\pgfkeys{/alain/.cd,
         dooo ini,
         dooo/.list={0,...,3},
         dooo set=\myTemp}
\myTemp
\end{document}
share|improve this answer
    
I like very much this code. Awesome ! I need to learn more profoundly pgfkeys –  Alain Matthes Apr 7 '13 at 18:11

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.