5

I have trouble with expanding a counter inside another macro. It seems that I cant use a simple chain of expandafter here since my counter can get very high. I found Force expansion of counter value in command argument but could not figure out how to apply it in my examplecode:

\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}

\newcounter{Mynumbers}


\makeatletter
\def\printmylist{}
\makeatother

\newcommand{\addtomylist}[2]{ %
        \stepcounter{Mynumbers}%
        $^{( \theMynumbers , #1  ) }~$%
        }

\begin{document}

first\addtomylist{0}{one}\\
second\addtomylist{4}{four} \\

~
\printmylist \\

~\\~\\~\\~\\
expected outcome:\\
$first^{(1,0)}$ \\
$secound^{(2,4)}$  \\

1: one \\
2: four \\


\end{document}
3
  • I"m not sure what the problem is as it works foer me and I get your expected output (well, I really get first$^{(1,0)}$ second$^{(2,4)}$, but I think that this is what you intended). What error are you getting? Also, I am not sure if this is an accident or an artifact of your cutting it down to a MWE, but \addtomylist ignores #2.
    – user30471
    Commented Feb 17, 2017 at 5:27
  • @Andrew the missing part is the 1: one \\ 2: four \\ Commented Feb 17, 2017 at 5:28
  • never use \\ at the end of a paragrah (it makes terrible output and tex warns about badness 10000 (which is the maximum badness possible) Commented Feb 17, 2017 at 9:25

3 Answers 3

5

Depending on what you are really trying to do there may be better ways of doing this. The following appears to produce your requested output, so I think that this may do what you want:

\documentclass[a4paper,10pt]{report}
\parindent=0pt

\usepackage{etoolbox}

\def\printmylist{}

\newcounter{Mynumbers}
\newcommand{\addtomylist}[2]{%
        \stepcounter{Mynumbers}%
        ${}^{(\theMynumbers, #1 )}~$%
        \xappto\printmylist{\theMynumbers: \unexpanded{#2\\}}%
        }

\begin{document}

first\addtomylist{0}{one}

second\addtomylist{4}{four}

\printmylist

\end{document}

This produces:

enter image description here

I have used the \xappto command from the etoolbox package. This command appends an expanded version of the second argument to the macro specified by the first argument:

\xappto<macro><stuff to append>

I have put \unexpanded because you don't want that part to expand when it is added to \printmylist.

Also, notice that I removed the space from the start of

\newcommand{\addtomylist}[2]{ % <-- unwanted space????
        \stepcounter{Mynumbers}%
        $^{( \theMynumbers , #1  ) }~$%
        }

This is what caused the gap between the one and the super-scripted (1,0) in your MWE.

11
  • Interestingly, you can use \par instead of \\ with no problems. Commented Feb 17, 2017 at 5:42
  • @JohnKormylo Yes, you need \noexpand\newline or \noexpand\\ but, as you say, \par is fine by itself (that is, you don't need\noexpand). The difference, I think, is that \par is not expandable whereas the others are.
    – user30471
    Commented Feb 17, 2017 at 5:46
  • @Andrew thank you very much for the fast solution! also a big thanks for the explanation, now I understand why my experiments failed badly ;) Commented Feb 17, 2017 at 5:59
  • 1
    The other difference between \par and \\ is that \par is that putting \\ at the end of a paragraph is always completely wrong and generates a spurious line of maximum badness 10000 Commented Feb 17, 2017 at 9:27
  • @user2567875 The best way to thank, provided I've answered your question, is by adding a green tick.
    – user30471
    Commented Feb 17, 2017 at 13:01
1

You have to expand the counter's value before adding it to the list.

\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}

\newcounter{Mynumbers}

\newcommand\printmylist{}

\makeatletter
\newcommand{\addtomylist}[2]{%
  \stepcounter{Mynumbers}%
  {\textsuperscript{(\theMynumbers,#1)}}%
  \edef\@tempa{\theMynumbers}%
  \expandafter\addto@mylist@\expandafter{\@tempa}{#2}%
}
\newcommand{\addto@mylist@}[2]{%
  \g@addto@macro\printmylist{#1: #2\par}%
}
\makeatother

\begin{document}

first\addtomylist{0}{one}

second\addtomylist{4}{four}


\printmylist

\end{document}

enter image description here

The mandatory expl3 version:

\documentclass[a4paper,10pt]{report}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\addtomylist}{mm}
 {
  \int_gincr:N \g_mylist_index_int
  \textsuperscript{(\int_use:N \g_mylist_index_int,#1)}
  \mylist_add:fn { \int_use:N \g_mylist_index_int }{ #2 }
 }
\NewDocumentCommand{\printmylist}{}
 {
  \seq_use:Nn \g_mylist_list_seq { \par }
 }

\int_new:N \g_mylist_index_int
\seq_new:N \g_mylist_list_seq

\cs_new_protected:Nn \mylist_add:nn
 {
  \seq_gput_right:Nn \g_mylist_list_seq { #1:~#2 }
 }
\cs_generate_variant:Nn \mylist_add:nn { f }
\ExplSyntaxOff

\setlength{\parindent}{0pt}

\begin{document}

first\addtomylist{0}{one}

second\addtomylist{4}{four}

\printmylist

\end{document}

The output is the same.

1

The output you expect differs from the output you get in two aspects:

  1. The phrases "first" and "second" are not in mathmode.
  2. The macro \printmylist does not deliver the output 1: one \\ 2: four \\ .

Besides this you don't need \makeatletterand \makeatother with the definition of the \printmylist-macro as that definition does not contain the symbol "@". Also the definition of your \addtomylist-command will contain space tokens that might produce horizontal space.

Here comes your code with slight modifications. I hope it now does what you wish it to do:

\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}

\newcounter{Mynumbers}

\newcommand*\printmylist{}

\makeatletter
\newcommand{\addtomylist}[2]{%
  \stepcounter{Mynumbers}%
  $^{(\theMynumbers,#1) }~$%
  \expandafter\g@addto@macro\expandafter\printmylist\expandafter{\number\value{Mynumbers}: #2 \\}%
}%
\makeatother

\begin{document}

$first$\addtomylist{0}{one}\\
$second$\addtomylist{4}{four}\\

\printmylist\\

\hrulefill\\
expected output:\\

$first^{(1,0)}$\\
$second^{(2,4)}$ \\

1: one \\
2: four \\


\end{document}

You might get better results using \ensuremathinstead of $..$.

You might get better results either using \par instead of \\ or wrapping things into \hboxes while via \par ensuring that TeX is in vertical mode where each outermost \hbox is treated a s a single line:

\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{1cm}

\newcounter{Mynumbers}

\newcommand*\printmylist{\par}

\makeatletter
\newcommand{\addtomylist}[2]{%
  \stepcounter{Mynumbers}%
  \ensuremath{^{(\theMynumbers,#1)}}%
  \expandafter\g@addto@macro
  \expandafter\printmylist
  \expandafter{%
  \expandafter\hbox
  \expandafter{%
  \number\value{Mynumbers}: #2}}%
}%
\makeatother

\begin{document}

\verb|\parindent| is set to 1cm so you can see the difference between \TeX{}
acting in horizontal mode (where it also does the horizontal line-indenting with
the first line of a paragraph and the line breaking within a paragraph and the
\verb|\parfillskip|-glue-thingie at the end of a paragraph) and \TeX{} acting
in vertical mode where each outermost \verb|\hbox| is treated as a single
"line" whose content in turn gets processed in restricted horizontal mode:

\noindent\hrulefill

received output:

$first\addtomylist{0}{one}$

$second\addtomylist{4}{four}$

\printmylist

\noindent\hrulefill

expected output:

$first^{(1,0)}$

$second^{(2,4)}$

\hbox{1: one}
\hbox{2: four}

\end{document}

Output after compiling the example

1
  • Thank you for paying so much attention to the details!. I would have accept the other solutions as well if it were possible, but since it was the one I used in my document I did choose Andrews solution) Commented Feb 18, 2017 at 21:23

You must log in to answer this question.

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