4

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}

enter image description here

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?

A.Ellett
  • 50,533
  • \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

1 Answers1

4

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
\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}
mhelvens
  • 6,126
  • \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