17

I would like to define a number of related commands by using the counter in a for-loop.

For example, I want to define 26 commands like this:

\newcommand{\calA}{{\cal A}}
\newcommand{\calB}{{\cal B}}
...

I've been searching for a while (and have in fact learned quite a bit), but have still not found the answer. Here's my latest attempt (it uses the forloop package):

\newcounter{ct}
\forLoop{1}{26}{ct}{
    \expandafter\newcommand\expandafter%
    {\csname cal\Alph{ct}\endcsname}%
    {{\cal \Alph{ct}}}
}

All 26 commands are created, but are all defined as {\cal Z}. I guess {\cal \Alph{ct}} is only expanded after the loop has completed.

How can I accomplish my goal? And how does it work?

1

6 Answers 6

15

You don't say which package you got your loop macro from. This just uses the \loop in LaTeX (originally from plain TeX)

> \calA=\long macro:
->\mathcal {A}.
l.18 \show\calA

? 
> \calZ=\long macro:
->\mathcal {Z}.
l.20 \show\calZ

produced from

\documentclass{article}

\makeatletter

\def\foo#1{%
\expandafter\newcommand\csname cal#1\endcsname{\mathcal{#1}}}

\count@=0
\loop
\advance\count@ 1
\edef\y{\@Alph\count@}%
\expandafter\foo\y
\ifnum\count@<26
\repeat



\show\calA

\show\calZ

\stop
4
  • I was using the forloop package. I aded this information to my question.
    – mhelvens
    Commented May 23, 2012 at 10:38
  • Your answer seems to work fine! But I'd like to know how it works, and why my code doesn't work (this sort of code is a bit new to me). Preferably I'd like to see it done with a more LaTeXy for-loop as well, if you'd be so kind. :-)
    – mhelvens
    Commented May 23, 2012 at 10:48
  • I've mixed your code and mine into a more LaTeXy solution, and put it down as a separate answer. Thanks!
    – mhelvens
    Commented May 23, 2012 at 11:04
  • well I can't say much about yours as I commented you didn't provide a MWE or say where the macro came from. I may comment on mine later but have to attend to the day job for a bit:-) Commented May 23, 2012 at 11:25
10

These types of constructs are better done, either through LaTeX2e, kernel commands and constructs, hard core TeX or with a package such as etoolbox (or LaTeX3).

In this case I would prefer the following approach.

Firstly define a command that will define the other commands. Let us call it \commandfactory.

  \def\commandfactory#1{%
     \expandafter\def\csname cal#1\endcsname{\mathcal{#1}}}

We will need a new counter to keep track of the iteration and to provide the "letters" for the command.

   \newcounter{ctr}

The easiest looping structure in this case will be Knuth's \loop..\repeat construct. Finally, the MWE.

\documentclass{article}
\makeatletter

\def\commandfactory#1{%
   \expandafter\def\csname cal#1\endcsname{\mathcal{#1}}}

\newcounter{ctr}
\loop
  \stepcounter{ctr}
  \edef\X{\@Alph\c@ctr}%
  \expandafter\commandfactory\X
\ifnum\thectr<26
\repeat

\begin{document}
\setcounter{ctr}{0}
\loop
  \stepcounter{ctr}
   $\@nameuse{cal\@Alph\c@ctr}$, 
\ifnum\thectr<26
\repeat

\end{document}

Why I normally prefer such approach is that it uses constructs that are very common in packages and the kernel (i.e, you use common paradigms) and is easy to find information. People sometimes object to hybrid TeX/LaTeX commands, but hey, the important thing is for your code to work.

2
  • Thanks for your answer. It seems to be the same as David's answer. :-) It was quite helpful, but I do tend to prefer the somewhat higher-level constructs. They're a bit more readable, and the forloop package does seem widely supported.
    – mhelvens
    Commented May 23, 2012 at 11:12
  • @mhelvens They are very similar, i just prefer not to use \count@1, advance etc. Wanted to illustrate a reasonable hybrid and I didn't like \expandafter\newcommand.
    – yannisl
    Commented May 23, 2012 at 18:30
10

Aha, no TikZ related answers! Unacceptable....

You can also use the pgffor module of the PGF/TikZ package externally. This also gives you a chance to iterate over letters directly. I have used the ensuremath to use it directly but you can remove that and the corresponding \noexpand. See When not to use \ensuremath for math macro? for more info on that.

\documentclass{article}
\usepackage{pgffor}
\foreach \x in {A,...,Z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\noexpand\mathcal{\x}}}
}
\begin{document}
\calP\calG\calF / \calT\calI\calK\calZ
\end{document}

enter image description here

I fear that I'll have a tattoo out of this in the end.

EDIT Provided by Andrew Stacey

A XeLaTeX solution with even fancier calligraphy and correct capitalization

\documentclass{article}
\usepackage{unicode-math}
\setmathfont{xits-math.otf}
\usepackage{pgffor}
\AtBeginDocument{
\foreach \x in {A,...,Z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\csname mscr\x\endcsname}}
}
\foreach \x in {a,...,z}{%
\expandafter\xdef\csname cal\x\endcsname{\noexpand\ensuremath{\csname mscr\x\endcsname}}
}
}
\begin{document}
\calP\calG\calF / \calT\cali\calK\calZ
\end{document}

enter image description here

6
  • I like the simplicity of that syntax. But I'm getting errors. I ran your exact code, and got a lot of ! Missing number, treated as zero.
    – mhelvens
    Commented May 23, 2012 at 12:07
  • That's interesting I can compile without any problems. You can add \listfiles in your preanble and check the version of PGF/TikZ package components in the log messages. I have 2.10.
    – percusse
    Commented May 23, 2012 at 12:10
  • v2.00 here. I guess that must be it? I'll try and find a newer version.
    – mhelvens
    Commented May 23, 2012 at 12:12
  • It seems to be more tricky than a single .sty file. In the end I think I'll stick with the \forLoop solution. It works, and seems to be more widely supported. Thanks!
    – mhelvens
    Commented May 23, 2012 at 12:20
  • What I meant was that the forloop package is installed in TexLive, which all my colleagues use. Apparently that particular version of pgffor is not.
    – mhelvens
    Commented May 23, 2012 at 12:31
6

Based on the answer of David Carlisle, I've altered my own solution as follows:

\newcommand{\defcal} [1]{\expandafter\newcommand\csname cal#1\endcsname{{\cal #1}}}
\newcounter{ct}
\forLoop{1}{26}{ct}{
    \edef\letter{\Alph{ct}}
    \expandafter\defcal\letter
}

The trick seems to be to create the \defcal command, then use \edef, as well as \expandafter, so its argument is expanded first.

1
  • 3
    Please, don't use the deprecated syntax {\cal A}, but rather \mathcal{A}.
    – egreg
    Commented Jun 5, 2012 at 20:27
5

The forloop package defines two commands \forloop (preferred usage) and \forLoop (deprecated).

The definition of forloop is

\forloop[⟨step⟩]{⟨counter⟩}{⟨initial value⟩}{⟨condition⟩}{⟨code⟩}

But it's not the problem here. Your problem comes from the expansion of \Alph{ct}. A lot of answers are fine, here I use something like percusse and you can see you can use \forloop instead of \foreach

But I disagree with :

They're a bit more readable, and the forloop package does seem widely

because if you compare percusse's answer with my answer, I don't see what is more readable. Now in this case, I think it's better to do like David and to avoid \forloop

\documentclass[]{article}
\usepackage[utf8]{inputenc}
\usepackage{forloop}
\makeatletter 
\let\FOR\@for
\let\NAMEUSE\@nameuse   
\makeatother

\begin{document}

\newcounter{ct} 
\forloop{ct}{1}{\value{ct} < 27}{%
\expandafter\xdef\csname cal\Alph{ct}\endcsname{%
\noexpand\ensuremath{\noexpand\mathcal{\Alph{ct}}}}
}

\FOR\letter:={A,L,T,E,R,M,U,N,D,U,S}\do{% 
\NAMEUSE{cal\letter}}

\end{document} 

Pub !

enter image description here

4

Update 5 Jun 2012:

Today the LaTeX3 team changed some internal function names of the type \prg_. The function \prg_stepwise_inline:nnnn will be renamed to.

So if you use the newest version of expl3 you have to use \int_step_inline:nnnn instead of \prg_stepwise_inline:nnnn. The syntax is the same. For more details have a look at the announcement:

Deprecated functions: \prg_.. functions and x-type expansion based on \pdfstrcmp


To complete the list I want to provide a solution with expl3. Therefor you can use the function \prg_stepwise_inline:nnnn with the following syntax:

\prg_stepwise_inline:nnnn {<starting point>}
                          {<step>}
                          {<end point>}
                          {<code>}

For your request I used:

\documentclass[]{article}
\usepackage[utf8]{inputenc}
\usepackage{expl3}
\ExplSyntaxOn
\prg_stepwise_inline:nnnn {1 } { 1 } { 26 } 
 { 
 \cs_new:cpn { cal \int_to_Alph:n { #1 } } { \mathcal{ \int_to_Alph:n { #1 } } }
 }
\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn
\prg_stepwise_inline:nnnn {1 } { 1 } { 26 } 
 { 
  $\use:c{ cal \int_to_Alph:n { #1 } }$
 }
\ExplSyntaxOff
\end{document} 

enter image description here

You must log in to answer this question.

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