如何定义一个带有参数的命令来指定要返回哪个列表?

如何定义一个带有参数的命令来指定要返回哪个列表?

我想定义一个命令,返回一个或另一个列表,作为用括号括起来的列表,在我的真实文档而不是这个 MWE 中,我可以将其用作其他内容的参数(即,在 TikZ 结构中要迭代的列表\foreach)。

以下不是工作!

\documentclass{article}
\usepackage{ifthen}
\usepackage{tikz}

\newcommand{\whichlist}[1]{%
  \ifthenelse{#1=1}{{1,2,3}}%
     {{4,5}}
}

\begin{document}

I want to get \verb!{1,2,3}! but I get:
\whichlist{1}

I want to get \verb!{4,5}! but I get:
\whichlist{2}

Fanciful usage for MWE purposes is:

\begin{tikzpicture}    
  %\foreach \x in {\whichlist{1}} { \draw (0,0)--(\x,\x); }; % this gives error
  % Preceding, uncommented, should give same result as this:
  \foreach \x in {1,2,3}{ \draw (0,0)--(\x,\x*\x);}
\end{tikzpicture}

\end{document}

答案1

得到{1,2,3},但括号是组分隔符,因此不打印任何内容。不,你的尝试不能工作,因为\whichlist{1}不是列表,而是说明打印它。

您可以使用\foreach \x in \foo {...}provided\foo宏,该宏在单个扩展步骤后扩展为列表:因此,如果您这样做

\newcommand{\foo}{1,2,3}

然后

\foreach \x in \foo {...}

其工作原理与

\foreach \x in {1,2,3}{...}

经过一个扩展步骤后,您\whichlist{1}并没有得到一个列表。

您可以这样做:

\documentclass{article}
\usepackage{tikz}

\ExplSyntaxOn

\NewDocumentCommand{\preparelists}{O{default}m}
 {
  \seq_clear_new:c { l_murray_lists_#1_seq }
  \tl_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_murray_lists_#1_seq } { ##1 }
   }
 }

\NewExpandableDocumentCommand{\fetchlist}{O{default}m}
 {
  { \seq_item:cn { l_murray_lists_#1_seq } { #2 } }
 }

\ExplSyntaxOff

\preparelists{
  {1,2,3}
  {a,b,c,d}
}

\begin{document}

\begin{tikzpicture}    
  \expanded{\unexpanded{\foreach \x in }\fetchlist{1}} {
     \draw (0,0)--(\x,\x*\x/2);
   }
\end{tikzpicture}

\end{document}

但当然那东西相当不方便。这里有一个不太麻烦的方法,但请注意 周围的括号\fetchlist{1}

\documentclass{article}
\usepackage{tikz}

\ExplSyntaxOn

\NewDocumentCommand{\preparelists}{O{default}m}
 {
  \seq_clear_new:c { l_murray_lists_#1_seq }
  \tl_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_murray_lists_#1_seq } { ##1 }
   }
 }

\NewExpandableDocumentCommand{\fetchlist}{O{default}m}
 {
  { \seq_item:cn { l_murray_lists_#1_seq } { #2 } }
 }

\cs_new_protected:Npn \expandedforeach #1 in #2
 {
  \use:e { \exp_not:n { \foreach #1~in~ } #2 }
 }

\ExplSyntaxOff

\preparelists{
  {1,2,3}
  {a,b,c,d}
}

\begin{document}

\begin{tikzpicture}    
  \expandedforeach \x in {\fetchlist{1}} {
     \draw (0,0)--(\x,\x*\x/2);
   }
\end{tikzpicture}

\end{document}

在此处输入图片描述

你可以定义任意数量的列表,只要给它们命名即可:例如,如果你想命名foo这个列表,你可以这样做

\documentclass{article}
\usepackage{tikz}

\ExplSyntaxOn

\NewDocumentCommand{\preparelists}{O{default}m}
 {
  \seq_clear_new:c { l_murray_lists_#1_seq }
  \tl_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_murray_lists_#1_seq } { ##1 }
   }
 }

\NewExpandableDocumentCommand{\fetchlist}{O{default}m}
 {
  { \seq_item:cn { l_murray_lists_#1_seq } { #2 } }
 }

\cs_new_protected:Npn \expandedforeach #1 in #2
 {
  \use:e { \exp_not:n { \foreach #1~in~ } #2 }
 }

\ExplSyntaxOff

\preparelists[foo]{
  {1,2,3}
  {a,b,c,d}
}

\begin{document}

\begin{tikzpicture}    
  \expandedforeach \x in {\fetchlist[foo]{1}} {
     \draw (0,0)--(\x,\x*\x/2);
   }
\end{tikzpicture}

\end{document}

默认名称为default

答案2

问题在于\foreachTikZ 的参数语法有些不切实际,因此您必须使用\expanded才能获取宏的结果列表。您可以\myforeach按如下方式定义宏:

\documentclass{article}
\usepackage{tikz}

\def\listlist#1{\ifcase#1 \or
   {1,2,3}\or   % 1
   {4,5}\or     % 2
   {6,7,8}\fi   % 3
}
\def\myforeach#1inlist#2{\expanded{\noexpand\foreach\noexpand#1 in \listlist{#2}}}

\begin{document}

\begin{tikzpicture}
  \myforeach \x inlist 1 {
     \draw (0,0)--(\x,\x*\x/2);
   }
\end{tikzpicture}

\end{document}

当然,您不需要任何\ExplSyntaxOn,这里只使用 TeX 原语。

相关内容