2

I hope this question makes sense. If I wanted to modify the following code to allow the user to pass a macro as the first parameter, how would I do it?

How it is:

(using pgf)

\def\appendtolist#1{% <item>
  \csname pgfutil@ifundefined\endcsname{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
  \expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
}%

What I effectively want to do:

(using pgf)

\def\appendtolist#1#2{% <macro representing list> <item>
  \csname pgfutil@ifundefined\endcsname{#1}{\def\ithapplist{#1}}{% Instantiate list if not already
  \expandafter\def\expandafter#1\expandafter{\ithapplist^^J#1}}% Append to list
}%

Problem

After \endcsname I need to supply a macro name without the backslash.

Even if I use this other syntax for determining whether or not the macro has been defined, I still run into this problem.

Other csname checks

TeX Kernel

https://tex.stackexchange.com/a/30484/13552

\ifcsname#1\endcsname%
    ... command '#1' exists ...%
  \else%
    ... command '#1' does not exist ...%
  \fi%

LateX kernel

https://tex.stackexchange.com/a/30486/13552emphasized text

\@ifundefined{foo}
  {%
    % \foo not defined
  }
  {%
    % \foo defined
  }%

Ultimate Goal

Normally I spit out things to the log during runtime using \typeout. Instead, I'd like to append them to a macro (delimited variable) that I can call later with something like \typeout\expandafter{\aggregatedlogentries}. This would keep certain things grouped in the log.

Example

Does not compile

 \documentclass{article}
 \usepackage{pgf}
 \def\appendtolist#1{% <item>
       \csname pgfutil@ifundefined\endcsname{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
       \expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
     }%
\begin{document}
\newcount\step
\step = 0%
\loop
  \appendtolist{\step}% <== I want to be able to provide a macro name as arg1 and item as arg2!
  \advance\step by 1%
  \unless\ifnum \step>10 %space important
\repeat %

\typeout{\mylistmacro}
\end{document}
  • I think it's best to define \mylistmacro to be empty and then define new \appendtolist using internal command \g@addto@macro – touhami Jun 16 '16 at 7:59
  • @touhami That sounds promising – Jonathan Komar Jun 16 '16 at 8:05
  • why are you using \csname pgfutil@ifundefined\endcsname rather than \pgfutil@ifundefined ? – David Carlisle Jun 16 '16 at 8:08
  • @DavidCarlisle Because I am copying Percusse's code :D tex.stackexchange.com/a/235759/13552 (which I assumed could not be such a bad approach) I got the part about \unless and e-TeX from egreg at tex.stackexchange.com/a/62381/13552 – Jonathan Komar Jun 16 '16 at 8:10
  • \unless is a primitive, the etex package does not define it (and should not be loaded into current latex as it will undo all the new allocation code) – David Carlisle Jun 16 '16 at 8:10
5

This is clear example when programmer solves a problem which does not exsist by complicated macro packages (like pgf). You can simply do:

\def\appendtolist#1#2{%
   \ifx#1\undefined \def#1{#2}\else   
   \expandafter\def\expandafter#1\expandafter{#1^^J#2}\fi % Append to list
}%

\appendtolist\ithaplist{aha} \appendtolist\ithaplist{uha}
  • @wipet May I suggest being a little less judgmental here. I had no idea what approach to take. I decided to start with Percusse's approach, simply because I think he is a skilled coder. Whether it is wise or not is another question :) – Jonathan Komar Jun 16 '16 at 8:18
  • @macmadness86 I don't know what does mean "judgmental" but I strongly recommend first to learn TeX istself and second a features of some packages. – wipet Jun 16 '16 at 8:21
  • @wipet I mean that perhaps there is a reason Percusse used pgf of which you or I am unaware of. As for why I used it here, I might have some things behind the scenes going on that are not in the question (I don't in this case, but is often the case on stackexchange). Perhaps that is one of the downsides of minimal examples. – Jonathan Komar Jun 16 '16 at 8:24
  • 2
    @macmadness86 percusse was answering a question that the OP had tagged as tikz-pgf and was using tikz for the actual drawing. In such a case, using the supplied loop macro in pgf makes sense, but if you just want a loop macro loading half a million lines of tikz code to get it might be considered excessive. – David Carlisle Jun 16 '16 at 8:29
2

Your code did not produce an error but simply defined \mylistmacro to be 10 \step as you appended literally the tokens \step^^J 10 times, here I append the expansion of \step's current value, although as wipet rightly notes this is using several orders of magnitude more code than required for the stated use case.

 \documentclass{article}
%no \usepackage{etex}% for \unless
 \usepackage{pgf}
\makeatletter
 \def\appendtolist#1{% <item>
       \pgfutil@ifundefined{mylistmacro}{\def\mylistmacro{#1}}{% Instantiate list if not already
       \expandafter\def\expandafter\mylistmacro\expandafter{\mylistmacro^^J#1}}% Append to list
     }%
\begin{document}
\newcount\step
\step = 0%
\loop
  \expandafter\appendtolist\expandafter{\the\step}% <== I want to be able to provide a macro name as arg1 and item as arg2!
  \advance\step by 1%
  \unless\ifnum \step>10 %space important
\repeat %



\typeout{\mylistmacro}
\end{document}
1

The LaTeX3 programming layer expl3 provides a lot of macros for these kinds of things.

\documentclass{article}
\usepackage{xparse}
\begin{document}
\ExplSyntaxOn
\seq_new:N \l_macmad_mylist_seq

\int_step_inline:nnnn { 0 } { 1 } { 10 }
 { \seq_put_right:Nn \l_macmad_mylist_seq { #1 } }

\seq_use:Nn \l_macmad_mylist_seq { ,~ }
\ExplSyntaxOff
\end{document}

enter image description here

1

With etoolbox:

\usepackage{etoolbox}

\newcommand{\appendtolist}[2]{%
  \ifundef{#1}{\gdef#1{== \string#1 ==}}{}%
  \gappto#1{^^J#2}%
}

\appendtolist\mylistmacro{abc}
\appendtolist\mylistmacro{def}
\appendtolist\mylistmacro{ghi}
\appendtolist\mylistmacro{lmn}

\typeout{\mylistmacro}

Output on terminal:

== \mylistmacro ==
abc
def
ghi
lmn

More customizable, because you can define whatever usage you want for the made list, just varying how \showlist is defined.

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\appendtolist}{mm}
 {
  \seq_if_exist:cF { g_macmadness_typeout_#1_seq }
   { \seq_new:c { g_macmadness_typeout_#1_seq } }
  \seq_gput_right:cn { g_macmadness_typeout_#1_seq } { #2 }
 }
\NewDocumentCommand{\showlist}{m}
 {
  \typeout
   {
    ==~#1~==^^J
    \seq_use:cn { g_macmadness_typeout_#1_seq } { ^^J }
   }
 }
\ExplSyntaxOff

\appendtolist{mylistmacro}{abc}
\appendtolist{mylistmacro}{def}
\appendtolist{mylistmacro}{ghi}
\appendtolist{mylistmacro}{lmn}

\showlist{mylistmacro}

Output on terminal

== mylistmacro ==
abc
def
ghi
lmn

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.