如何将参数传递给使用 \csname 调用的宏

如何将参数传递给使用 \csname 调用的宏

我有一个宏,可以生成随机数列表并将其转换为字母进行打印。我想创建另一个宏来打印这些列表及其中间的文本。也就是说,如果
\first生成 A、C、B、D,

\first{2}返回 C
,我想要的功能如下:
sometext 包含 A、sometext 包含 C、sometext 包含 B、sometext 包含 D

sometext 包含的字母可能位于中间,并且可能因上下文而异。我使用 X 作为占位符,并使用 StrSubstitute 放置适当的字母。这不起作用,但我怀疑这更多地与以下事实有关:其中一个参数来自foreach使用pgffor

我当前的工作代码(我想要注释掉的部分,因为它不起作用):

\documentclass[12pt,letterpaper]{article}
\def\colors{4}
\def\version{2}

\usepackage{xstring}
\usepackage{pgf}
\usepackage{pgffor}
\usepackage{etoolbox}
\usepackage{listofitems}
\usepackage{transparent}

\usepackage[first = 1, last = \colors, seed = \version]{lcg}

\setcounter{enumi}{1}
\newcommand{\row}{\item[Round \theenumi:] \stepcounter{enumi}}
\newcommand{\rn}{\rand\Alph{rand}}

\newcommand{\nums}[3]{\chgrand[counter = rand, seed = #2]
\foreach \i in {1,...,#1}{\ifnum\numexpr #3=0\rn~\else\ifnum\i=\numexpr #3\rn\else\makebox[0pt]{{\transparent{0}\rn}}\fi\fi}
}
\newcommand{\first}[1]{\nums{5}{\version}{#1}}

\newcommand{\expand}[3]{
    \foreach \i in {1,...,#2}{
        \StrSubstitute{#1}{X}{\i} %Code that works, but doesn't do what I want
%       \StrSubstitute{#1}{X}{\expandafter{\csname #3\endcsname{\i}}} %Code that I want, but doesn't work
    }
}

\newcommand{\dcinc}[2]{#1 text [#2] more text}

\begin{document}


\begin{description}
    \row \expand{\dcinc{3}{M,2 X},}{5}{first}
\end{description}
\end{document}```

答案1

一方面:

该命令\nums在内部用于\chgrand执行分配。\nums也这样做\pgffor,这反过来也不是完全可扩展的。依次执行分配和其他不可扩展的命令意味着该命令\nums不能仅通过扩展来发挥作用。

另一方面:

该命令在-loop\nums的主体内使用,而使用-loops 时,主体通过扩展而不考虑 LaTeX 的-expansion-protection,这反过来意味着主体要么通过扩展来实现,要么通过 TeX 引擎的扩展保护来实现。\expand\foreach\foreach\edef\protect\foreach\protected\def

我建议定义并使用一个扩展保护的命令,\expansionprotectednums它调用\nums

\documentclass[12pt,letterpaper]{article}
\def\colors{4}
\def\version{2}

\usepackage{xstring}
\usepackage{pgf}
\usepackage{pgffor}
\usepackage{etoolbox}
\usepackage{listofitems}
\usepackage{transparent}

\usepackage[first = 1, last = \colors, seed = \version]{lcg}

\setcounter{enumi}{1}
\newcommand{\row}{\item[Round \theenumi:] \stepcounter{enumi}}
\newcommand{\rn}{\rand\Alph{rand}}

\newcommand{\nums}[3]{%
  \chgrand[counter = rand, seed = #2]%%%
  \foreach \i in {1,...,#1}{%
    \ifnum\numexpr(#3)\relax=0 %
      \rn~%
    \else
      \ifnum\i=\numexpr(#3)\relax
        \rn
      \else
        \makebox[0pt]{{\transparent{0}\rn}}%
      \fi
    \fi
  }%%%
}
\makeatletter
\@ifdefinable\expansionprotectednums{%
  \protected\def\expansionprotectednums{\nums}%
}%
\makeatother
\newcommand{\first}[1]{\expansionprotectednums{5}{\version}{#1}}

\newcommand{\expand}[3]{%%%
    \foreach \i in {1,...,#2}{%%%
%        \StrSubstitute{#1}{X}{\i} %Code that works, but doesn't do what I want
       \StrSubstitute{#1}{X}{\csname #3\endcsname{\i}} %Code that I want, and seems to work
    }%%%
}

\newcommand{\dcinc}[2]{#1 text [#2] more text}

\begin{document}


\begin{description}
    \row \expand{\dcinc{3}{M,2 X},}{5}{first}
\end{description}
\end{document}

在此处输入图片描述

答案2

弄清楚问题中代码的意图相当困难,但我怀疑您不需要任何所使用的包。

在此处输入图片描述

\documentclass{article}

\ExplSyntaxOn
\seq_new:N\l_cb_seq
% start with a list of letters
\seq_set_from_clist:Nn \l_cb_seq {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}
\let\reseed\sys_gset_rand_seed:n
\def\shuffle{\seq_shuffle:N \l_cb_seq}
\def\nth{\seq_item:Nn \l_cb_seq}
\ExplSyntaxOff

\begin{document}

\reseed{1234}
\shuffle

2nd=\nth{2}, 5th=\nth{5}

\shuffle

2nd=\nth{2}, 5th=\nth{5}

\end{document}

这会用字母列表初始化一个序列,然后使用可重复的随机打乱对字母进行打乱,每次运行时都会给出相同的顺序,因为种子是明确设置的。然后显示两个示例项目,重新打乱列表并选择相同的项目编号,显示它们的新值。


在评论中澄清后

此版本构建了一个长度为 10 的随机列表,包含“A”、“B”、“C”、“D”,目前只有一个列表a在此调用。它提供了对该列表第 n 个项目的访问函数,\nth{a}{4}并提供了一个迭代器,该迭代器将使用 dupplied 函数中的指定字母循环遍历整个列表。

它产生终端输出

list a is: D,C,B,A,D,C,A,A,D,B
item 2 of list a: C

和排版

在此处输入图片描述

\documentclass{article}

\ExplSyntaxOn

% generate one random value from ABCD (1 is the position in the list, not used)
\cs_new:Npn \cb_rand_color:n #1 {\char_generate:nn{`A+\int_rand:nn{0}{3}}{11},}

% set up list "a"  as a list of length 10
\clist_new:N\l_cb_lista_clist
\clist_set:Ne \l_cb_lista_clist {
  \int_step_function:nnN {1} {10} \cb_rand_color:n
}

% seed for the random numbers
\let\reseed\sys_gset_rand_seed:n

%The #2 item from list #1
\def\nth#1#2{\clist_item:cn{l_cb_list#1_clist}{#2}}

% iterate pver the list
\def\printlist#1#2{\clist_map_inline:cn {l_cb_list#1_clist} {#2}}

\ExplSyntaxOff

\typeout{list a is: \UseName{l_cb_lista_clist}}

\typeout{item 2 of list a: \nth{a}{2}}

\begin{document}

\reseed{54321}% arbitrary fixed seed for repeateable results

\printlist{a}{text [M,2,#1] more text}

\end{document}

相关内容