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.

The preambles of my LaTeX documents often include many many lines of \DeclareMathOperator instructions, e.g.

\DeclareMathOperator{\Rep}{Rep}
\DeclareMathOperator{\Tet}{Tet}
\DeclareMathOperator{\Maps}{Maps}
\DeclareMathOperator{\Diff}{Diff}

Is there a nice way to map some macro over a list, so I could do this more concisely, and with less copying and pasting when I add a new math operator?

share|improve this question

8 Answers 8

up vote 29 down vote accepted

Updated solution using the features of etoolbox which has essentially implemented the “\MapCommand” and named it \forcsvlist

\documentclass{article}
\usepackage{amsmath}
\usepackage{etoolbox}

\newcommand{\DeclareMyOperator}[1]{%
  \expandafter\DeclareMathOperator\csname #1\endcsname{#1}
}
\newcommand{\DeclareMathOperators}{\forcsvlist{\DeclareMyOperator}}

\DeclareMathOperators{Rep,Tet,Maps,Diff}

\begin{document}
Operators: $\Rep, \Tet, \Maps, \Diff$
\end{document}

“For historical reasons”, I leave my original answer bellow.


Combining the previous answers from Grigory and Andrew I was able to come up with the following somewhat cleaner implementation which also exposes a nice user interface.

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\def\ops@declare#1{%
  \expandafter\DeclareMathOperator\csname #1\endcsname{#1}
}
\def\ops@scan#1,{%
  \ifx#1\relax
    \let\ops@next\relax
  \else
    \ops@declare{#1}\let\ops@next\ops@scan
  \fi\ops@next
}
\newcommand{\DeclareMathOperators}[1]{\ops@scan#1,\relax,}
\makeatother

\DeclareMathOperators{Rep,Tet,Maps,Diff}

\begin{document}
Operators: $\Rep, \Tet, \Maps, \Diff$
\end{document}
share|improve this answer
    
Nice! (and some more characters to take me over the limit) –  Loop Space Jul 27 '10 at 11:59
    
The only thing I don't like about this is that it would result in lots of code duplication if I wanted to also do something like define \cX as \mathcal{X} for each letter X. –  Scott Morrison Jul 27 '10 at 15:18
4  
Following the scheme above it wont be difficult to define a more general \MapCommand{\Cmd}{a,b,c} which expands to \Cmd{a}\Cmd{b}\Cmd{c}. –  Juan A. Navarro Jul 27 '10 at 15:33
1  
@Juan: This is very useful! Unfortunately, I don't have much practice with TeX/LaTeX beyond writing my documents in it and defining the occasional macro, so I don't really understand how your solution works, and I'm not able to generalize it to something like a \MapCommand (which is what I've been trying to do to no avail). I was wondering if you could give a hint as to how to do it, or even a full implementation? Of course, I know the value of learning to do something myself, but in this case I'm sufficiently exasperated to ask for a solution that I will then try to understand. Thanks! –  Zev Chonoles Aug 30 '11 at 7:23
2  
@Zev: I added a new simpler solution which is more robust and hopefully much more easy to understand. It relies on the etoolbox package and its command \forcsvlist which is basically the "map command" that you are looking for. Have a look at the documentation of that package. –  Juan A. Navarro Aug 30 '11 at 9:13

Not quite what you're looking for, but I'd probably write the quick hack:

\newcommand{\OP}[1]{\DeclareMathOperator{#1}}
\OP{Rep}
\OP{Tet}

and so forth. Moreover if I were to use these a lot, I'd just write them once and include them anywhere.

share|improve this answer

Put the whole list of unabbreviated \DeclareMathOperator macros in a file myoperators.sty, somewhere in your latex path (I suggest ~/tex/). Then add \usepackage{myoperators} at the top of any .tex file that uses those operators.

Do this for any macro you use more than once.

share|improve this answer
4  
I used to do this. Then I started having collaborators. Sometimes keeping everything in one file has its advantages. –  Willie Wong Jul 26 '10 at 21:36
    
You can deal with the collaborators problem by having the files you've \input get automatically inserted into the .tex file. The LaTeX compilation system Rubber has a -o expand option, for source file expansion. –  ShreevatsaR Jul 27 '10 at 5:58
1  
@Willie: only as long as you ship files via email. When using version control or syncing (such as shared Dropbox folders) along with file system symlinks, using more than one file is really quite simple. –  Konrad Rudolph Jul 27 '10 at 7:24

E.g.

\def\deflist#1{\ifx#1\stop\let\next=\kill\else\let\next=\parse\fi\next{#1}}  
\def\kill#1{\relax}
\def\parse#1#2{\newcommand{#1}{\operatorname{#2}}\deflist}

\deflist
\holim{holim}
\hocolim{hocolim}
\stop

works (although I can't recommend using such tricks).

share|improve this answer

I'd probably do this differently if I were coding it today (as I've learnt a lot more about TeX in the last decade), but here's something like how I did it for my thesis:

\documentclass{article}

\usepackage{amsmath}

\makeatletter
\def\my@shift#1:#2.{#1}
\def\my@trunc#1:#2.{#2}
\def\my@void{}\relax

\newcommand{\Mops}[1]{%
 \def\my@test{}\relax
 \def\my@list{#1:}\relax
 \loop\ifx\my@test\my@void\relax
 \edef\my@elt{\expandafter\my@shift\my@list.}\relax
 \edef\my@list{\expandafter\my@trunc\my@list.}\relax
 \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\DeclareMathOperator\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\expandafter\expandafter\expandafter\csname \expandafter\my@elt\expandafter\endcsname\expandafter}\expandafter{\my@elt}
 \ifx\my@list\my@void
 \def\my@test{t}
 \fi
 \repeat}

\makeatother

\Mops{Det:Diff:Rep}

\begin{document}
\(\Det \Diff \Rep\)
\end{document}

The test in the loop could probably be cleaned up, and that is a rather horrendous number of \expandafters! But it works.

share|improve this answer
    
+1 for the last sentence about the \expandafter. –  stalking is prohibited Sep 8 at 8:00

There are several ways to do it using different programming facilities of different packages. Here's what it looks like using the LaTeX2e kernel command \@for to map over a comma-separated list:

\makeatletter
\newcommand\MakeMathOperators[1]{%
  \@for\@ii:=#1\do{%
    \expandafter\DeclareMathOperator\@ii
  }%
}
\makeatother
\MakeMathOperators{
  \rep  {Rep}  ,
  \tet  {Tet}  ,
  \maps {Maps}
}
share|improve this answer
    
This is great. I like that it's clear how to generalize this solution. –  Scott Morrison Jul 27 '10 at 15:16
    
Talking of generalising, I just generalised this to do a step-through iteration on beamer slides (x^{\step{2,3,4,5}}). I didn't know about the \@for before. Very useful! +1 –  Loop Space Aug 27 '10 at 18:27
    
I really wish this were the selected answer, in looking for a source about what the @ symbol is used for. This response plus saving a 100 tokens and internal LaTeX commands were key to my comprehending the role of this symbol and how to react when I run across it in others' code. Grazie! @WillRobertson –  mpacer Dec 3 at 0:14

Here's a solution from Kevin Walker's LaTeX preambles:

% tricky way to iterate macros over a list
\def\semicolon{;}
\def\applytolist#1{
    \expandafter\def\csname multi#1\endcsname##1{
        \def\multiack{##1}\ifx\multiack\semicolon
            \def\next{\relax}
        \else
            \csname #1\endcsname{##1}
            \def\next{\csname multi#1\endcsname}
        \fi
        \next}
    \csname multi#1\endcsname}

% \DeclareMathOperator{\pr}{pr} etc.
\def\declaremathop#1{\expandafter\DeclareMathOperator\csname #1\endcsname{#1}}

\applytolist{declaremathop}{pr}{im}{gl}{ev}{coinv}{tr}{rot}{Eq}{obj}{mor}{ob}{Rep}{Tet}{cat}{Maps}{Diff}{Homeo}{sign}{supp}{Nbd}{res}{rad};
share|improve this answer

Combining the previous answers with the ones to the related question about scanning over a list of somethings I came up with the following solution, using etoolbox version 2.0 (2010-08-21) or later.

\newcommand{\define}[4]{\expandafter#1\csname#3#4\endcsname{#2{#4}}}
\forcsvlist{\define{\DeclareMathOperator}{}{}}{Rep, Tet, Maps, Diff}
\forcsvlist{\define{\newcommand}{\mathcal}{c}}{A,B,C,D,E,F,G,H,I,J,K}

The last line defines \cA as \mathcal{A} for all letters in the list.

If one wants a different list separator, e.g. ;, one can use \DeclareListParser*{\formylist}{;} and then replace \forcvslist with \formylist.

share|improve this answer
    
compact and very extensible - very nice –  sebastian Nov 23 '12 at 20:03

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.