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.

Here is an example document.

\documentclass[a4paper]{amsart}

\usepackage{tikz}

\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]
\foreach \x in                                         % 1
    {conjecture, definition, example}                  % 2
    {\newtheorem{\x}[baseTheorem]{\MakeUppercase{\x}}} % 3

\begin{document}

\section{Even numbers}

\begin{definition}
    A number is called \emph{even} if its remainder on division by $2$ is zero.
\end{definition}

\begin{example}
    $2$ and $0$ are both even numbers.
\end{example}

\begin{conjecture}
    The sum of two even numbers is again an even number.
\end{conjecture}

\end{document}

This document does not compile. It produces the following error:

! Undefined control sequence.
<argument> \x 

l.16    A
          number is called \emph{even} if its remainder on division by $2$ i...

However, if the lines numbered 1, 2 and 3 are replaced with the following lines...

\newtheorem{conjecture}[baseTheorem]{\MakeUppercase{conjecture}}
\newtheorem{definition}[baseTheorem]{\MakeUppercase{definition}}
\newtheorem{example}[baseTheorem]{\MakeUppercase{example}}

... then the document does compile, and looks as I expect. (What I really want is to capitalise the first letter of "Conjecture" etc., not the entire word, but this is a separate problem.)

Additionally, if \x is changed to \t in the original versions of lines 1 and 3, a different error message is obtained:

! Argument of \UseTextAccent has an extra }.
<inserted text> 
                \par 
l.16     A
           number is called \emph{even} if its remainder on division by $2$ ...

I reasoned that the issue might be that the third argument of \newtheorem was being recorded verbatim and only evaluated when it comes time to typeset an individual theorem environment. I tried the following:

\foreach \x in
    {conjecture, definition, example}
    {\def\uppercased\MakeUppercase{\x} \newtheorem{\x}[baseTheorem]{\uppercased}}

But it did not get around the problem:

! Undefined control sequence.
<argument> \uppercased 

l.16     A
           number is called \emph{even} if its remainder on division by $2$ ...

What can I do?

share|improve this question
1  
For the capitalization side note, \usepackage{titlecaps} and replace each instance of \MakeUppercase{} with \titlecap{}. –  Steven B. Segletes Sep 16 '13 at 15:29
    
add comment

4 Answers 4

up vote 9 down vote accepted

The commands in the final argument of \newtheorem are expanded as each theorem is set not at the point of definition, so each theorem tries to use the command \x in its title, long after your loop has finished. You need to change the order of evaluation, for example this works:

\documentclass[a4paper]{amsart}

\usepackage{pgffor}

\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]
\foreach \x in                                         % 1
    {conjecture, definition, example}                  % 2
    {\edef\tmp{\noexpand\newtheorem{\x}[baseTheorem]{\noexpand\MakeUppercase{\x}}}\tmp} % 3

\begin{document}

\section{Even numbers}

\begin{definition}
    A number is called \emph{even} if its remainder on division by $2$ is zero.
\end{definition}

\begin{example}
    $2$ and $0$ are both even numbers.
\end{example}

\begin{conjecture}
    The sum of two even numbers is again an even number.
\end{conjecture}

\end{document}
share|improve this answer
add comment

While David Carlisle has given the technical reasons for your problem (\x is expanded to late) in his answer, you can also use the .list handler that uses \foreach internally but

  • doesn’t group its content (not a problem here because \newtheorem defines the environments globally anyway) and
  • can be used with the already expanded content as #1 (rather than as a macro sequence).

Code

\documentclass[a4paper]{amsart}

\usepackage{pgffor}
\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]

\pgfkeys{/utils/my Foreach/.code={\newtheorem{#1}[baseTheorem]{\MakeUppercase{#1}}},
         /utils/my Foreach/.list={conjecture, definition, example}}

\begin{document}
\section{Even numbers}

\begin{definition}
    A number is called \emph{even} if its remainder on division by $2$ is zero.
\end{definition}

\begin{example}
    $2$ and $0$ are both even numbers.
\end{example}

\begin{conjecture}
    The sum of two even numbers is again an even number.
\end{conjecture}
\end{document}
share|improve this answer
    
+1 Ah well you'd have to know something about pgf to give this answer:-) –  David Carlisle Sep 16 '13 at 15:24
add comment

As David has already explained, you need to get the strings, not \x which expands to the strings. It's easy with expl3.

\documentclass[a4paper]{amsart}
\usepackage{expl3}

\ExplSyntaxOn
% provide a "user interface"
\cs_set_eq:NN \Foreach \clist_map_inline:nn
\ExplSyntaxOff

\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]
\Foreach{conjecture, definition, example}
  {\newtheorem{#1}[baseTheorem]{\MakeUppercase{#1}}}

\begin{document}

\section{Even numbers}

\begin{definition}
    A number is called \emph{even} if its remainder on division by $2$ is zero.
\end{definition}

\begin{example}
    $2$ and $0$ are both even numbers.
\end{example}

\begin{conjecture}
    The sum of two even numbers is again an even number.
\end{conjecture}

\end{document}

enter image description here

share|improve this answer
    
+1 Ah well you'd have to know something about pgf to give this answer:-) s/pgf/latex3/ –  David Carlisle Sep 16 '13 at 16:15
    
@DavidCarlisle s/pgf/any other loop-providing package/ –  Qrrbrbirlbel Sep 16 '13 at 17:55
add comment

The reason was explained by David, here is an alternative to using pgffor, with the (expandable) utility \xintApplyUnbraced of package xint (yes I do some shameless constant advertising of it here). Presumably some future package release will have more tools and more user-friendly syntax, such as using comma separated list of values.

The \Action macro is defined starting with a space: this is done to stop \xintApplyUnbraced which always tries to expand things; the space is gobbled, and \xintApplyUnbraced will be happy. Then, when all the three \newtheorem statements have been prepared, and only then, they are executed.

Note that \xintApplyUnbraced is completely expandable and this can help in some contexts.

For each use of \xintApplyUnbraced one needs some \Action macro, there is no reserved name for it, but a document can use again and again an \Action with each time a new definition. I use \def rather than \newcommand because \Action is more of a low-level helper thing.

\documentclass[a4paper]{amsart}

\usepackage{xint}

\theoremstyle{definition}
\newtheorem{baseTheorem}{Base Theorem}[section]

% space at the start could be removed, but in some other situations
% it has its use. It means: don't execute the following code until
% all elements from the initial list have been fed to \Action

\def\Action #1{ \newtheorem{#1}[baseTheorem]{\MakeUppercase{#1}}}

\xintApplyUnbraced\Action{{conjecture}{definition}{example}} 

\begin{document}

\section{Even numbers}

\begin{definition}
    A number is called \emph{even} if its remainder on division by $2$ is zero.
\end{definition}

\begin{example}
    $2$ and $0$ are both even numbers.
\end{example}

\begin{conjecture}
    The sum of two even numbers is again an even number.
\end{conjecture}

\end{document}

Output:

why-doesnt-foreach-etc

share|improve this answer
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.