我有一个宏可以准确打印我想要的内容,但我无法将其嵌套在另一个宏中。据我所知,这是因为第一个宏没有完全执行,并且第一个宏的命令与第二个宏的命令混合在一起。
如何进行 ?
\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}
答案1
循环 via\loop
不可扩展,因为它包含赋值。出于同样的原因\def\n{\the\count255 }
(顺便说一句,请注意空格),它与推进计数器 via 一样不可扩展\advance
。
\Liste
可以以可扩展的方式实现:
- 包
intcalc
有助于以可扩展的方式增加, \n
需要通过可扩展的方式通过数字进行交换。
但构造一个包含扩展列表的宏(也是令牌寄存器)要容易得多。在下面的例子中,\Liste
生成列表并将结果存储在宏中\ListeResult
。后者可用于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}
答案2
您无法将其提供\Liste
给max
,因为它需要语法正确的函数列表,而不是印刷他们。
这是一个可行的实现;您必须首先计算替换并定义一个宏来包含列表。然后您可以在的参数中使用此宏\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}
采用 的新实现expl3
。
\documentclass{article}
\usepackage{geometry}
\usepackage{xparse}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=newest}
\ExplSyntaxOn
\NewDocumentCommand{\addplotlist}{smO{1}mmO{}}
{% #1 = * if printing
% #2 = function to apply to the list
% #3 = starting point, default 1
% #4 = end point
% #5 = list building function
% #6 = options for addplot
\cs_set:Nn \__tarass_process:n { ,#5 }
\clist_set:Nx \l__tarass_process_clist
{
\int_step_function:nnnN { #3 } { 1 } { #4 } \__tarass_process:n
}
\IfBooleanTF{#1}
{
$\use:c{#2}(\clist_use:Nn \l__tarass_process_clist { ,~ })$
}
{
\addplot[#6]{ #2(\l__tarass_process_clist) }
}
}
\clist_new:N \l__tarass_process_clist
\ExplSyntaxOff
\begin{document}
\addplotlist*{max}{5}{#1-#1/(6-#1)*x}
\addplotlist*{min}{5}{#1+#1/(6-#1)*x}
\bigskip
\begin{tikzpicture}
\begin{axis}[xmin=0,xmax=5,ymax=7]
\addplotlist{max}{5}{#1-#1/(6-#1)*x}[color=black,smooth,samples=400];
\addplotlist{min}{5}{#1+#1/(6-#1)*x}[color=red,smooth,samples=400];
\end{axis}
\end{tikzpicture}
\end{document}
变量参数用 表示#1
。*
版本打印获取的列表。