How to repeat text

1,592

Solution 1

Your \append macro cannot work in the argument to tabular, where macros can be used as long as they are fully expandable; this isn't, because it contains assignments.

Here's a quick version with LaTeX3 functions. Note that this won't work in the argument of tabular if array is loaded, because this package disables expanding the argument.

However, typing l*{2}{c} as the argument seems not so complicated to need a macro.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\append}{mmm}
 {
  #1\prg_replicate:nn{#3}{#2}
 }
\ExplSyntaxOff

\begin{document}

\noindent\append{c}{c}{0}

\noindent\append{cd}{c}{1}

\noindent\append{c}{c}{2}

\noindent\append{c}{c}{3}

\noindent\begin{tabular}{\append{l}{c}{2}}
1&2&3\\
\append{start}{&test}{1}\\
\append{start}{&test}{2}
\end{tabular}

\end{document}

enter image description here

Solution 2

There is really no need to reinvent the wheel. There are a number of looping packages out there that you can use to iterate over a sequence. I've used multido below:

enter image description here

\documentclass{article}
\usepackage{multido}% http://ctan.org/pkg/multido
\makeatletter
\newcommand{\append}[3]{ % #1 = start of text, #2 = text to repeat, #3 = number of repetitions
 \def\@looop{#1}% start of text
 \ifnum#3>0\multido{\iA=1+1}{#3}{\g@addto@macro\@looop{#2}}\fi% text to repeat
 \@looop}% Execute
\makeatother
\begin{document}

\noindent\append{c}{c}{0}

\noindent\append{c}{c}{1}

\noindent\append{c}{c}{2}

\noindent\append{c}{c}{3}

\noindent\begin{tabular}{*{3}{c}}
  1 & 2 & 3 \\
  \append{start}{&test}{1} \\
  \append{start}{&test}{2}
\end{tabular}

\end{document}

The idea is to construct a macro \@looop that contains the starting element, and repeated elements are added using \g@addto@macro. Then, at the end of \append, \@looop is executed.

Note that tabular column specifications already provide a type of duplication/repetition using a *{<num>}{<col spec>} style, where the column specification <col spec> is repeated <num> times.

Solution 3

The spaces are due to an extra space that you have in the definition of \append, between the opening brace and the comment. You have one more before the \else. This is how I'd write it:

\newcommand{\append}[3]{%
  % #1 = start of text, #2 = text to repeat, #3 = number of repetitions
  \ifnum #3>0
    \setcounter{tempcount}{#3}%
    \addtocounter{tempcount}{-1}%
    \append{#1#2}{#2}{\arabic{tempcount}}%
  \else
    #1%
  \fi}

The rest works, except when you try to use \append in the argument of tabular. The problem there is that \append is not expanded before the column information is needed. If you want this to work as well, I suggest that you follow @Werner's answer. It's not worth the effort re-inventing everything. However, if you must, you'll need to understand how precisely macro expansion works.

Solution 4

Others have explained he origin of the spaces, and the fact that the argument of tabular must be completely expandable. The other errors come from the fact that after the first expansion of \append, TeX sees an &, and different parts of the macro's code occur in different cells of the alignment. You need to delay the point at which the ampersands are recognized. The following will work in this example, but I can't say it if it will work anywhere else:

\def\amp{&}
\noindent
\begin{tabular}{ccc}
  1&2&3\\
  \append{start}{\amp test}{1}\\
  \append{start}{\amp test}{2}
\end{tabular}
Share:
1,592
John Kormylo
Author by

John Kormylo

Updated on August 01, 2022

Comments

  • John Kormylo
    John Kormylo 10 months

    I get interesting errors with the following macro. Mostly it works, but I get extra spaces after \noindent (but not after \newline). I tried using \loop or \whiledo (from ifthen) but get stack overflows. The really strange stuff occurs when I try to repeat & symbols (the log shows everything working until TeX throws in an extra \fi).

    \documentclass{article}
    
    \tracingmacros=1
    \newcounter{tempcount}
    
    \newcommand{\append}[3]{ % #1 = start of text, #2 = text to repeat, #3 = number of repetitions
    \ifnum #3>0%
    \setcounter{tempcount}{#3}%
    \addtocounter{tempcount}{-1}%
    \append{#1#2}{#2}{\arabic{tempcount}}
    \else #1 \fi}
    
    \begin{document}
    
    \noindent\append{c}{c}{0}
    
    \noindent\append{c}{c}{1}
    
    \noindent\append{c}{c}{2}
    
    \noindent\append{c}{c}{3}
    
    \noindent\begin{tabular}{\append{c}{c}{2}}
    1&2&3\\
    \append{start}{&test}{1}\\
    \append{start}{&test}{2}
    \end{tabular}
    
    \end{document}
    

    I should mention that I've played with \noexpand to no avail. enter image description here

    • egreg
      egreg over 9 years
      You have several spaces in the definition of append; as it stands it can't be used in the argument of tabular, which must be fully expandable.
  • egreg
    egreg over 9 years
    I've removed two %: the one after \else was redundant; the one after 0 is wrong: the space (end-of-line here) terminates the numeric constant and is better to make TeX see it.
  • nickie
    nickie over 9 years
    @egreg: You're the master, whatever you say... :-)
  • John Kormylo
    John Kormylo over 9 years
    Excellent, but I still have the problem with & and the error messages I forgot to mention.
  • John Kormylo
    John Kormylo over 9 years
    The column specification was mostly what I was looking for. I am so embarassed. I actually have the documentation for that. (multido, on the other hand...)
  • barbara beeton
    barbara beeton over 9 years
    the (lack of) vertical space between the last row of "c"s and the tabular doesn't look good. a strut would fix it.
  • egreg
    egreg over 9 years
    @barbarabeeton It's just because the tabular isn't protected in a center or similar environment; that's just for the example.