如何在 expl3 中递归处理逗号分隔的列表? 如何创建带有逗号分隔参数列表的递归 Latex 宏看起来像一个(更一般的)重复,并提供不少于两个 expl3 答案。然而,我显然是个白痴,因为我仍然不知道该怎么做。我知道扩展总是让我困惑,但我不明白为什么没有任何我玩过的许多变体都成功了 - 或者甚至给了我错误。(好吧,我或多或少理解为什么它们没有给我错误,因为它们不起作用。)
我也尝试过序列。不出所料,我也无法让它们工作。我尝试使用一个aux
函数(我认为)按照Scott H. 的回答。但是,我显然无法很好地辨别该解决方案的显著特点,无法在这里采用它。我不太理解 egreg 的答案,无法尝试任何事情。
\documentclass[border=10pt]{standalone}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\cs_new_protected_nopar:Nn \subsets_construct_subset:nn
{
\clist_set:Nn \l_tmpa_clist { #1 }
\int_zero:N \l_tmpa_int
\tl_clear:N \l_tmpa_tl
\clist_map_inline:Nn \l_tmpa_clist
{
\int_incr:N \l_tmpa_int
\int_compare:nF { \l_tmpa_int = #2 }{
\int_compare:nTF { #2 = 1 }{
\int_compare:nF { \l_tmpa_int = 2 } { \tl_put_right:Nn \l_tmpa_tl { , } }
}{
\int_compare:nF { \l_tmpa_int = 1 } { \tl_put_right:Nn \l_tmpa_tl { , } }
}
\tl_put_right:Nn \l_tmpa_tl { ##1 }
}
}
\tl_use:N \l_tmpa_tl
}
\cs_generate_variant:Nn \clist_set:Nn { Nx }
\subsets_construct_subset:nn { 2, 3, 4, 5 } { 2 } ~ : ~
\subsets_construct_subset:nn { 2, 4, 5 } { 1 } ~ : ~
\subsets_construct_subset:nn { \subsets_construct_subset:nn { 2, 3, 4, 5 } { 2 } } { 1 } ??
\ExplSyntaxOff
\end{document}
有时,在 expl3 中扩展似乎比革命前更难处理!
编辑
我想用这个来回答使用 forest 或 tree 包列出集合 {1, 2, 3, 4, 5} 的子集的方法。但是,我的答案实际上有所不同。我重写了 Forest 代码,以避免需要expl3
递归应用该函数。我想避免这样做,部分原因是递归方法似乎反映了需要什么(或者我认为需要什么),部分原因是在 Forest 树中添加循环会使事情变得非常慢,非常快。另外,我认为我一定是错过了一些简单而明显的解决方案,因为我想要的似乎是一件非常平凡的事情。所以我想,在添加每个节点时,根据其父节点的内容和值构建其内容n
。但是,要做到这一点,必须expl3
在树增长时反复应用该函数。我目前的解决方案只是添加节点,并仅在整个结构到位时填充它们(使用expl3
非常类似于一位基督徒建议如下,事实上)。但这似乎是一种不太透明的方法……
答案1
我可以根据第一个参数中的第一个标记提供递归;如果是\subsets_construct_subset:nn
,则执行该函数并将结果作为参数传递给同一个函数。
不过,我看到过好几种可能失败的情况。无论如何,这显然不是扩展的问题:\subsets_construct_subset:nn
纯扩展不起作用,所以你不能指望某些f
扩展魔法能起作用(x
扩展肯定不会起作用,因为它没有通过纯扩展来实现。
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\cs_new_protected:Nn \subsets_construct_subset:nn
{
\clist_set:Nn \l_tmpa_clist { #1 }
\exp_last_unbraced:Nx \token_if_eq_meaning:NNTF { \tl_head:n { #1 } } \subsets_construct_subset:nn
{
\cs_set_eq:NN \__subsets_use:n \use_none:n
#1
\cs_set_eq:NN \__subsets_use:n \use:n
\subsets_construct_subset:xn { \tl_use:N \l_tmpa_tl } { #2 }
}
{
\__subsets_construct_subset:nn { #1 } { #2 }
\__subsets_use:n { \tl_use:N \l_tmpa_tl }
}
}
\cs_set_eq:NN \__subsets_use:n \use:n % initialize
\cs_new_protected:Nn \__subsets_construct_subset:nn
{
\int_zero:N \l_tmpa_int
\tl_clear:N \l_tmpa_tl
\clist_map_inline:Nn \l_tmpa_clist
{
\int_incr:N \l_tmpa_int
\int_compare:nF { \l_tmpa_int = #2 }{
\int_compare:nTF { #2 = 1 }{
\int_compare:nF { \l_tmpa_int = 2 } { \tl_put_right:Nn \l_tmpa_tl { , } }
}{
\int_compare:nF { \l_tmpa_int = 1 } { \tl_put_right:Nn \l_tmpa_tl { , } }
}
\tl_put_right:Nn \l_tmpa_tl { ##1 }
}
}
}
\cs_generate_variant:Nn \subsets_construct_subset:nn { x }
\subsets_construct_subset:nn { 2, 3, 4, 5 } { 2 } \par
\subsets_construct_subset:nn { 2, 4, 5 } { 1 } \par
\subsets_construct_subset:nn { \subsets_construct_subset:nn { 2, 3, 4, 5 } { 2 } } { 1 }
\ExplSyntaxOff
\end{document}
答案2
一种无需递归的解决方案,通过“double”循环第二个参数,该参数也是一个逗号分隔的列表:
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\clist_new:N \l_cfr_subset_clist
\cs_new:Nn \subsets_construct_subset:nn
{
\group_begin:
\clist_set:Nn \l_cfr_subset_clist {#1}
\clist_set:Nn \l_tmpb_clist { #2 }
\clist_map_inline:Nn \l_tmpb_clist {% Loop over the indices
\int_zero:N \l_tmpa_int
\clist_set_eq:NN \l_tmpa_clist \l_cfr_subset_clist
\clist_clear:N \l_cfr_subset_clist
\clist_map_inline:Nn \l_tmpa_clist
{% Loop over the current temp list
\int_incr:N \l_tmpa_int
\int_compare:nF { \l_tmpa_int = ##1 }{
\clist_put_right:Nn \l_cfr_subset_clist {####1}
}
}
}
\clist_use:Nn \l_cfr_subset_clist {,}
\group_end:
}
\subsets_construct_subset:nn { 2, 3, 4, 5 } { 2 } ~ : ~
\par
\subsets_construct_subset:nn { 2, 4, 5 } { 1 } ~ : ~
\par
\subsets_construct_subset:nn { 2, 3, 4, 5 } { 2, 1 } ~ : ~
\par
\subsets_construct_subset:nn { 2, 3, 4, 5 } { 2, 1,1 } ~ : ~
\ExplSyntaxOff
\end{document}