我真的希望我问的是正确的问题。我实际上正在研究的问题比 MWE 中发生的事情要复杂得多。我想我已经把问题缩小到了真正的问题。
我有一些旧代码,可以完美地实现我的要求。现在我想在新情况下使用该代码,在输出任何内容之前,我会使用旧代码进行多次迭代。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
%%--------------------------------------------------------------------------------
%% In theory, this first section of code works correctly and gives me the desired
%% result.
%%--------------------------------------------------------------------------------
%% This next macro does some complicated things:
%%
%% testing booleans, setting token lists, \int_compare, \int_case
%%
%% But, regardless, everything it does--I believe--is fully expandable. That is
%% it should work whether in an "x" or "f" type argument.
\cs_new:Npn \_format_expression:n #1 { #1 x 2 - }
\seq_new:N \l_collection_of_expressions_seq
\cs_new:Npn \_parse_expressions:n #1
{ \seq_set_split:Nnn \l_collection_of_expressions_seq {,} {#1} }
%% This next function, while fully expandable is not expandable in an "f"
%% tyep argument.
\cs_new:Nn \_write_expression:
{
\seq_map_inline:Nn \l_collection_of_expressions_seq
{ \_format_expression:n { ##1 } }
}
\NewDocumentCommand{\trialFunctionA}{ m }
{ \_parse_expressions:n { #1 }
\_write_expression:
}
%%--------------------------------------------------------------------------------
%% Here starts the problematic code
%%--------------------------------------------------------------------------------
%% The start of more complicated things.
\seq_new:N \l_outer_collection_of_expressions_seq
\tl_new:N \l_numerator_tl
\seq_new:N \l_formatted_expressions_seq
\seq_new:N \l_denominator_seq
\cs_new:Npn \_parse_outer:nn #1#2
{
\tl_put_right:Nn \l_numerator_tl {#2}
\_parse_expressions:n {#1}
%% This is where my problem step seems to be. I need the
%% expansion of \_write_expression: but can't get it. However,
%% since \_write_expression: uses \seq_map_inline, this is not
%% expandable in an "f" type argument. But neither do I want to blast
%% this with "x" because I might have some unexpandable stuff in here
\seq_put_right:Nn \l_formatted_expressions_seq { 3^{\_write_expression:} }
}
\cs_new:Npn \parse_outer:n #1
{
\seq_set_split:Nnn \l_outer_collection_of_expressions_seq {,} { #1 }
\seq_map_inline:Nn \l_outer_collection_of_expressions_seq
{ \_parse_outer:nn ##1 }
\frac{\l_numerator_tl}{\seq_use:Nn \l_formatted_expressions_seq {\,}}
}
\NewDocumentCommand{\trialFunctionB}{ m }
{ \parse_outer:n { #1 } }
%%--------------------------------------------------------------------------------
%% This is here just so I can easily demo the desired final result.
\def\cheat#1{\_format_expression:n{#1}}
\ExplSyntaxOff
\begin{document}
\[
\trialFunctionA{1,2,3}
\]
\[
\frac{ABC}{3^{\cheat{1}\cheat{2}\cheat{3}}\,
3^{\cheat{a}\cheat{b}\cheat{c}}\,
3^{\cheat{M}\cheat{N}\cheat{P}}}
\]
\[
\trialFunctionB{{1,2,3}{A},
{a,b,c}{B},
{M,N,P}{C}}
\]
\end{document}
上述代码确实可以编译,这比我的实际文档要好。但是我没有得到想要的结果,因为扩展发生得太晚了。
有没有什么方法可以让它\_write_expression:
扩张得足够远,但又不会扩张得太远?
答案1
我建议您:x
无论如何都要用 爆破它,并用 保护易碎内容\exp_not:n
。
另外,你对 做出了错误的假设\seq_map_inline:Nn
。任何_map_inline
函数都必须在后台进行定义,因此不符合:x
扩展条件。所以你需要使用\seq_map_function:NN
。
以下代码应该可以工作。我添加了一些脆弱的内容,以表明它在适当的时候之前不会扩展。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \_format_expression:n #1 { \exp_not:n{#1} x 2 - } % CHANGED
\seq_new:N \l_collection_of_expressions_seq
\cs_new:Npn \_parse_expressions:n #1
{ \seq_set_split:Nnn \l_collection_of_expressions_seq {,} {#1} }
\cs_new:Nn \_write_expression:
{
\seq_map_function:NN
\l_collection_of_expressions_seq
\_format_expression:n % CHANGED
}
%%--------------------------------------------------------------------------------
%% Here starts the problematic code
%%--------------------------------------------------------------------------------
\seq_new:N \l_outer_collection_of_expressions_seq
\tl_new:N \l_numerator_tl
\seq_new:N \l_formatted_expressions_seq
\seq_new:N \l_denominator_seq
\cs_new:Npn \_parse_outer:nn #1#2
{
\tl_put_right:Nn \l_numerator_tl {\exp_not:n{#2}} % CHANGED
\_parse_expressions:n {#1}
\seq_put_right:Nx
\l_formatted_expressions_seq
{ 3^{\_write_expression:} } % CHANGED
}
\cs_new:Npn \parse_outer:n #1
{
\seq_set_split:Nnn \l_outer_collection_of_expressions_seq {,} { #1 }
\seq_map_inline:Nn \l_outer_collection_of_expressions_seq
{ \_parse_outer:nn ##1 }
\frac{\l_numerator_tl}{\seq_use:Nn \l_formatted_expressions_seq {\,}}
}
\NewDocumentCommand{\trialFunctionB}{ m }
{ \parse_outer:n { #1 } }
%%% Example don't-want-this-to-expand content
\int_new:N \g_counter_int
\cs_new:Npn \DontExpandPlease {
\int_gincr:N \g_counter_int
\int_use:N \g_counter_int
}
\ExplSyntaxOff
\begin{document}
\[
\trialFunctionB{{\DontExpandPlease,\DontExpandPlease,\DontExpandPlease}{A},
{a,b,c}{B},
{M,N,P}{C}}
\]
\end{document}