# I need a fully expandable function to expand in an “f” type argument

I really hope that I'm asking the correct question. What I'm actually working on if far more convoluted than what's happening in the MWE here. I think I've narrowed down things to real problem.

I have some old code that does what I want perfectly. Now I would like to use that code in a new situation where I iterate several times using the old code before outputting anything.

\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}


The above code does compile, which is better than my actual document. But I don't have the desired results because expansion is happening too late.

Is there some way to get \_write_expression: to expand just far enough, but not too far?

-
\seq_map_inline:Nn is not fully expandable. – egreg Aug 24 '13 at 21:32
Can you replace \_write_expression: with an appropriate \seq_use as in changing parse expressions to \cs_new:Npn \_parse_expressions:n #1 { \seq_set_split:Nnn \l_collection_of_expressions_seq {,} {#1} \seq_put_right:Nx \l_formatted_expressions_seq { 3^{\seq_use:Nn \l_collection_of_expressions_seq {x2-} x2-}} } and eliminating write expressions. – Scott H. Aug 24 '13 at 22:05

I would suggest that you blast it with :x anyway and protect fragile content with \exp_not:n.

Also, you made a wrong assumption about \seq_map_inline:Nn. Any _map_inline function has to make a definition in the background, and is thus ineligible for :x expansion. So you need to use \seq_map_function:NN.

The following code should work. I added some fragile content to show that it's protected from expansion until the right time.

\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
\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}

-
\seq_map_inline:Nn doesn't survive x expansion, while \seq_map_function:Nn can be used in f expansion. – egreg Aug 24 '13 at 22:24
Yes, of course, silly me. Any _map_inline has to make a definition in the background, and is thus ineligible for :x expansion. (I blame sleep-deprivation. :-)) --- However, your second statement confuses me still. The docs would suggest that \seq_map_function:Nn can not be expanded by :f (it has a hollow star). – mhelvens Aug 24 '13 at 22:32
You're right: it is fully expandable, but not in f arguments. – egreg Aug 24 '13 at 22:35
Nice explanation. I'm still trying to get my actual document to compile correctly. I'm still scratching my head. No error messages now, but my formatting is still getting lost. :( – A.Ellett Aug 24 '13 at 22:43
Well, it's hard to say without seeing your code, but are you perhaps :xing your formatted content again at some point? \exp_not:n will only protect it once. – mhelvens Aug 24 '13 at 22:49