# Expansion issue with \begingroup and \foreach

This question led to a new package:
nowidow

I'm trying to define a dynamic \begingroup command to get rid of widows:

\usepackage{pgffor}
\newcommand{\nowidow}[1][2]{%
\begingroup\widowpenalties #1 \foreach \n in {2,...,#1}{10000 } 0
\par\endgroup
}


This fails complaining that \begingroup requires a number and I'm guessing this has to do with expansion.

Here is a MWE:

\documentclass{scrbook}

\usepackage{lipsum}

\usepackage{pgffor}
\newcommand{\nowidow}[1][2]{%
\begingroup\widowpenalties #1 \foreach \n in {2,...,#1}{10000 } 0
\par\endgroup
}

\begin{document}

\lipsum
\nowidow

\end{document}


How can I get this to work? Would it be easier (although less portable) to do it in Lua?

-

\begingroup doesn't require a number. It is \widowpenalties which looks for one and \foreach isn't expandable, so it doesn't produce a number directly and therefore you get an error. Most likely \begingroup is just shown somewhere in the error message because it was the last correctly read token before the error.

In order to fix this you need to use an expandable loop, e.g. using e-TeX's \numexpr:

\documentclass{scrbook}

\usepackage{lipsum}

\def\nowidowX#1{%
\ifnum#1<\nowidowmax
10000
\expandafter\nowidowX\expandafter{\the\numexpr(#1)+1\expandafter\relax\expandafter}%
\fi
}

\newcommand{\nowidow}[1][2]{%
\begingroup
\mathchardef\nowidowmax#1\relax
\widowpenalties #1 \nowidowX{1} 0\par
\endgroup
}

\begin{document}

\lipsum
\nowidow

\end{document}

-
How can I use an expandable loop? –  ℝaphink Aug 22 '11 at 11:43
I added some code now. –  Martin Scharrer Aug 22 '11 at 11:51
Thanks, I'll test :-) –  ℝaphink Aug 22 '11 at 11:52
Thank you very much. –  ℝaphink Aug 22 '11 at 11:56
@Martin: you save a few \expandafter if you make the argument of \nowidowX delimited (e.g., \def\nowidowX#1;{\ifnum#1<\nowidowmax10000 \expandafter\nowidowX\the\numexpr#1+1\expandafter;\fi}). –  Bruno Le Floch Aug 22 '11 at 16:23

Martin has already pointed out that \foreach is non-expandable. I'd add that the expl3 bundle provides such expandable tools. For instance,

\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand {\nowidow} { O{2} }
{
\begingroup
\widowpenalties #1~ \prg_replicate:nn {#1-1} {10000~} 0~
\par\endgroup
}
\ExplSyntaxOff


(I'm just using xparse for \NewDocumentCommand. You could simply stick with \newcommand if you prefer.)

-
This is latex3, right? –  ℝaphink Aug 22 '11 at 16:56
@Raphink, yes. I should add that spaces are ignored between \ExplSyntaxOn and Off and the odd-looking ~ are spaces. Basically, I replicate 10000~ a given number of times. Also, it seems that the last 0 penalty is not really needed, is it? You could put \widowpenalties \int_eval:n{#1-1}~ \prg_replicate:nn... and remove that 0~. –  Bruno Le Floch Aug 22 '11 at 18:03