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.

I have a macro that prints exactly what I want, but I can't use it nested in another one. As far as I understand it is because the fist one is not completely executed and commands from first macro mixt together with those from the second one.

How to proceed ?

enter image description here

\documentclass{article}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=1.9}

\makeatletter
\def\L@ste#1#2{
    \count255 = 1
    \loop   
    \def\n{\the\count255}%
    #1%
    \advance\count255 by 1
    \ifnum\count255>#2
    \else
    ,%
    \repeat
    }
\def\Liste#1#2{\L@ste{#1}{#2}}
\makeatother

\begin{document}

\verb+\Liste{\n-\n/(6-\n)*x}{5}+

Prints exactly what I need :

\Liste{\n-\n/(6-\n)*x}{5}

\bigskip    

But I can't use it directly :

\verb+max(\Liste{\n-\n/(6-\n)*x}{5})+

produces errors ...

\bigskip    

\begin{tikzpicture}

\begin{axis}[xmin=0,xmax=5,ymax=7]
  \addplot[color=black,smooth,samples=400] 
  {
% can't use it here, Why ?
    %max(\Liste{\n-\n/(6-\n)*x}{5})
max(1-1/(6-1)*x,2-2/(6-2)*x,3-3/(6-3)*x,4-4/(6-4)*x,5-5/(6-5)*x)
  };
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this question
    
This code makes no sense, sorry. For many reasons. One of them is that \else is not legal in \loop, but it's perhaps the least. –  egreg Jun 15 at 10:25
    
@egreg Loop seems to ignore that as it works well, the result is correct. I don't understand then what you mean. By the way, how to test count255<=#2 as <= is forbiden and doesn't work ? –  Tarass Jun 15 at 10:31
    
    
@DavidCarlisle I know that paper; but this has the original \loop macro. –  egreg Jun 15 at 10:48
    
@Tarass Your \Liste macro produces the instruction for printing what you'd like to feed to max; but you can't use it in the argument of max, because this wants the functions, not the instructions for printing them. –  egreg Jun 15 at 10:51

2 Answers 2

up vote 10 down vote accepted

The loop via \loop is not expandable, because it contains assignments. For the same reason \def\n{\the\count255 } (BTW, note the space) is not expandable as advancing the counter via \advance.

\Liste could be implemented in an expandable way:

  • Package intcalc helps in incrementing in an expandable way,
  • \n needs to be exchanged by the number in an expandable way.

But it is much easier to construct a macro (also token register) that contains the expanded list. In the following example \Liste generates the list and stores the result in macro \ListeResult. The latter can be used in max:

\documentclass{article}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=1.9}

\makeatletter
\newcommand*{\Liste}[2]{%
  \count@ = 1 %
  \let\ListeResult\@empty
  \loop
    \def\n{\the\count@}%
    \edef\ListeResult{\ListeResult#1}%
    \advance\count@ by 1 %
  \ifnum#2<\count@
  \else
    \edef\ListeResult{\ListeResult,}%
  \repeat
}
\makeatother

\begin{document}

Prints exactly what I need :

\Liste{\n-\n/(6-\n)*x}{5}
\ListeResult

\bigskip

\begin{tikzpicture}

\begin{axis}[xmin=0,xmax=5,ymax=7]
  \Liste{\n-\n/(6-\n)*x}{5}
  \addplot[color=black,smooth,samples=400] {max(\ListeResult)};
\end{axis}
\end{tikzpicture}
\end{document}

Result

share|improve this answer
    
Great ! thank you for explantions and for the solution. –  Tarass Jun 15 at 11:09

You can't feed \Liste to max, because it wants a syntactically correct list of functions, not the instructions for printing them.

Here's a working implementation; you must first compute the substitutions and define a macro to contain the list. Then you can use this macro in the argument of \max.

\documentclass{article}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=newest}

\makeatletter
\newcommand\Liste[3][]{%
  \def\Liste@temp{\@gobble}%
  \count@=\z@
  \loop\ifnum\count@<#3\relax
  \advance\count@ by \@ne
  \begingroup\edef\n{\the\count@}%
  \edef\x{\endgroup\def\noexpand\Liste@temp{\Liste@temp,#2}}\x%
  \repeat
  \if\relax\detokenize{#1}\relax
    \Liste@temp
  \else
    \let#1=\Liste@temp
  \fi
}
\makeatother

\begin{document}

\Liste{\n-\n/(6-\n)*x}{5}

\bigskip    

\begin{tikzpicture}

\begin{axis}[xmin=0,xmax=5,ymax=7]
   \Liste[\foo]{\n-\n/(6-\n)*x}{5}
  \addplot[color=black,smooth,samples=400] 
  {
    max(\foo)
  };
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Thank you for this answer. It is much harder to understand for me than Heiko's one. Could you please, on spair time, add some comments explaining the purpose of the different commands ? I am very interested in. Of course I'll add a bounty on it. –  Tarass Jun 15 at 11:22

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.