3

I try to give multiple arguments to a function using a comma seperated list (clist). This seems to work and I can also iterate over the elements by using a seq. However, using the elements of the seq as parameters to another function and then using \str_case does not seem to work.

Why?

\documentclass{article}

\ExplSyntaxOn

\newcommand{\HPsatz}[1]{
    #1:~
    \str_case:nn { #1 } {
        { H123 }{ First~sentence. }
        { H124 }{ Second~sentence. }
        { H125 }{ Third~sentence. }             
    }
}

\int_new:N \l__ghs_test_int
\int_new:N \l__ghs_tmpa_int
\seq_new:N \l__ghs_seq_numbers
\newcommand {\GHStext}[1]
{
    % generate seq from clist argument 1
    \seq_set_from_clist:Nn \l__ghs_seq_numbers { #1 }
    
    % set number of elements in seq
    \int_set:Nn \l__ghs_test_int { \seq_count:N \l__ghs_seq_numbers }
    
    % reset loop counter to 1
    \int_set:Nn \l__ghs_tmpa_int { 1 }
    
    % int_do_while of seq for each element
    \int_do_while:nn { \l__ghs_tmpa_int <= \l__ghs_test_int }
    {
        % print sentence from \HPsatz
        \HPsatz{\seq_item:Nn \l__ghs_seq_numbers { \l__ghs_tmpa_int }}

%       \seq_item:Nn \l__ghs_seq_numbers { \l__ghs_tmpa_int }

        % increment loop counter
        \int_incr:N \l__ghs_tmpa_int
    }
}

\ExplSyntaxOff

\begin{document}
    Sentences (clist):

    \GHStext{H123, H125}
    
    Sentences (manual):

    \HPsatz{H123}
    \HPsatz{H125}   
\end{document}
4
  • 1
    this exact issue came up with another user this morning \str_case:nn compares detokenized strings so you are comparing \seq_item:Nn \l__ghs_seq_numbers { \l__ghs_tmpa_int } and H123 which are not the same declare an :en variant to expand #1 first Dec 2, 2023 at 17:02
  • 1
    perhaps you need it in your real application but you don't need the seq or counting the list here you could simply have mapped \HPsatz over the supplied clist which would also have fixed the expansion issue. Dec 2, 2023 at 17:03
  • @DavidCarlisle: declare and :en variant of what? Of #1? Dec 2, 2023 at 17:05
  • @DavidCarlisle: That sounds easier but what do you mean with to map over the supplied clist? Can I directly iterate over the clist? How? Dec 2, 2023 at 17:06

2 Answers 2

4

You could use

    \exp_args:Ne \str_case:nn { #1 } {

Or declare a \str_case:en variant (which would do the same thing) so that #1 is expanded before the string comparison.

But simpler would be to map over the clist directly avoiding all the counting.

\documentclass{article}

\ExplSyntaxOn

\newcommand{\HPsatz}[1]{
    #1:~
    \exp_args:Ne \str_case:nn { #1 } {
        { H123 }{ First~sentence. }
        { H124 }{ Second~sentence. }
        { H125 }{ Third~sentence. }             
    }
}

\seq_new:N \l__ghs_seq_numbers
\newcommand {\GHStext}[1]
{
    \clist_map_function:nN {#1} \HPsatz
}

\ExplSyntaxOff

\begin{document}
    Sentences (clist):

    \GHStext{H123, H125}
    
    Sentences (manual):

    \HPsatz{H123}
    \HPsatz{H125}   
\end{document}
3
  • 1
    Thanks! Wow, that makes my life much easier. I did not know about \clist_map_function:nN... Dec 2, 2023 at 17:12
  • What if \HPsatz also takes two optional arguments that will be passed in the clist? Can you also easily use \clist_map_function then? Dec 2, 2023 at 18:43
  • no if you have a two argument function you would need to construct a one-argument wrapper that does the mapping so to map a 2-agument \foo calling \foo{x}{...} for each element use \clist_map_inline:Nn \clist_variable {\foo {x}{#1}} @mrCarnivore Dec 2, 2023 at 19:35
3

You can even make everything fully expandable.

The guidelines suggest to separate the user interface with the internal implementation.

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\HPsatz}{m}
  {
    \ghs_satz:n { #1 } 
  }

\NewExpandableDocumentCommand{\GHStext}{m}
  {
    \ghs_text:n { #1 }
  }

\cs_new:Nn \ghs_satz:n
  {
    #1:~
    \str_case_e:nn { #1 } {
        { H123 }{ First~sentence. }
        { H124 }{ Second~sentence. }
        { H125 }{ Third~sentence. }             
    }
  }

\cs_new:Nn \ghs_text:n
  {
    \clist_map_function:nN { #1 } \__ghs_text:n
  }

\cs_new:Nn \__ghs_text:n
  {
    \ghs_satz:n { #1 }~
  }

\ExplSyntaxOff

\begin{document}

Sentences (clist):

\GHStext{H123, H125}
    
Sentences (manual):

\HPsatz{H123}
\HPsatz{H125}   

\end{document}

enter image description here

Just for information: the loop you define with two counters can more simply be done with \seq_map_inline:Nn or \seq_map_function:NN.

6
  • 1
    Thanks for that solution. I need some more time to fully understand your example and the advantages. Dec 2, 2023 at 18:36
  • What is the \ghs_text:n for? Could you not just put the code into \GHStext? Why the extra 3 layers? Dec 2, 2023 at 20:56
  • @mrCarnivore To distinguish between user interface and programming layer.
    – egreg
    Dec 2, 2023 at 21:42
  • So you assume the content of the interface function also to be visible and therefore want to hide the real content also? Dec 2, 2023 at 22:13
  • How do you create a \cs_new:Nn function that needs no arguments? Dec 2, 2023 at 22:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .