0

Consider the case below as a minimal example. But the questions concerns understanding nonfragile composition of macros each which parse using something like xparse.

(code below thanks to egreg)

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\funA}{m}
{
  % split the input at the spaces
  \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
  % use a counter for knowing where we are
  \int_zero:N \l_tmpa_int
  % map the sequence
  \seq_map_inline:Nn \l_tmpa_seq
   {% one more step
    \int_incr:N \l_tmpa_int
    \int_compare:nTF { \int_mod:nn { \l_tmpa_int - 3 } { 5 } = 0 }
     {% if we're at the 3rd, 5th, 8th, 13th, ... item, apply \form
      \form { ##1 }
     }
     {% otherwise just deliver the item
      ##1
     }
    % if not at the last, add a space
    \int_compare:nT { \l_tmpa_int < \seq_count:N \l_tmpa_seq } { ~ }
   }
 }
\NewDocumentCommand{\funB}{m}
{
    % split the input at the spaces
    \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
    % use a counter for knowing where we are
    \int_zero:N \l_tmpa_int
    % map the sequence
    \seq_map_inline:Nn \l_tmpa_seq
    {% one more step
        \int_incr:N \l_tmpa_int
        \int_compare:nTF { \int_mod:nn { \l_tmpa_int - 2 } { 5 } = 0 }
        {% if we're at the 3rd, 5th, 8th, 13th, ... item, apply \form
            \form { ##1 }
        }
        {% otherwise just deliver the item
            ##1
        }
        % if not at the last, add a space
        \int_compare:nT { \l_tmpa_int < \seq_count:N \l_tmpa_seq } { ~ }
    }
}
\ExplSyntaxOff

\NewDocumentCommand{\form}{m}{+++}

\begin{document}

\raggedright

\funA{Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias}

\funB{Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias}

\funA{\funB{Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias}}

\end{document}

Look at \funA{\funB{Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias}}.

EXPECTED:

Non +++ +++ Brute cum quae +++ +++ exquisitaque doctrina philosophi +++ +++ tractavissent ea Latinis +++ +++ fore ut hic +++ +++ in varias

ACTUAL:

Non +++ nescius Brute cum quae +++ ingeniis exquisitaque doctrina philosophi +++ sermone tractavissent ea Latinis +++ mandaremus fore ut hic +++ labor in varias

This is the same as if \funB{Non eram nescius Brute cum quae summis ingeniis exquisitaque doctrina philosophi Graeco sermone tractavissent ea Latinis litteris mandaremus fore ut hic noster labor in varias} was written only.

QUESTION:

What is the error in this type of composite construction and how to fix it so that \funA{\funB{...}} gives the EXPECTED?

SIMPLEST EXAMPLE OF THE PROBLEM:

\funA{{X}}gives X not \funA{X}; so what is best way to write \fun or add something inside {...{...}} get \funA{X} when writing \funA{{X}}?

This type of parsing is a useful solution to many problems. Question is how to compose to solve problems. When composition is necessary or logically simplest.

  • 1
    TeX macros are not in general function-like. One can arrange for a limited subset of stuff to work in that way, provided the implementation of everything is expandable. Here, you are carrying out assignments: they are not expandable, so it's not possible done this way. – Joseph Wright Mar 23 at 16:45
  • For an example in expl3 where everything is done to allow 'function like' working, see the case-changing functions \tl_upper_case:n, etc. You will see that depending on the desired outcome this can be very tricky. (I can perhaps provide something based on that code ...) – Joseph Wright Mar 23 at 16:46
  • 2
    you would have to define things quite differently if you want to nest them like this, e.g. the command would have to store the bits so that the next command can pick them up. As it is the definition is not expandable. – Ulrike Fischer Mar 23 at 16:47
  • @Joseph-Wright @Ulrike-Fischer So checking if I understand correctly, "Non +++ nescius Brute cum quae +++ ingeniis exquisitaque doctrina philosophi +++ sermone tractavissent ea Latinis +++ mandaremus fore ut hic +++ labor in varias" is not really what \funA{...} "sees" because the spaces, glue, tokens, ..., in "Non +++ nescius Brute cum quae +++ ingeniis exquisitaque doctrina philosophi +++ sermone tractavissent ea Latinis +++ ..." output by \funB are no longer of the same type as manually entered text. Merely typset as if it were, and that is causing the unexpected behavior? – Guido Jorg Mar 23 at 17:02
  • 2
    @GuidoJorg Like I said, TeX is not a functional language. The argument to \funA is exactly the tokens you pass it. To arrange function-like behaviour you need to expand that argument first, then work with it further. No glue or whatever: that's typesetting so unexpandable. You can deal with character tokens, macros, spaces. I'll try to code this up. – Joseph Wright Mar 23 at 17:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.