Use two comma lists to build a test function using \str_case:nn

expl3macros

Suppose given two comma lists of the same length:

\clist_set:Nn \l__mymodule_keys_clist { key1, key2, key3 }
\clist_set:Nn \l__mymodule_acts_clist { act1, act2, act3 }

How can one convert them into a test function of the following form?

\NewDocumentCommand { \TestFunction } { m }
  {
    \str_case:nnF { #1 }
      {
        { key1 } { act1 }
        { key2 } { act2 }
        { key3 } { act3 }
      } { No ~ action! }
  }

Below is a MWE.

\documentclass{article}
\begin{document}
\ExplSyntaxOn

\clist_new:N \l__mymodule_keys_clist
\clist_new:N \l__mymodule_acts_clist

\clist_set:Nn \l__mymodule_keys_clist { key1, key2, key3 }
\clist_set:Nn \l__mymodule_acts_clist { act1, act2, act3 }

\NewDocumentCommand { \TestFunction } { m }
  {
    \str_case:nnF { #1 }
      {
        { key1 } { act1 }
        { key2 } { act2 }
        { key3 } { act3 }
      } { No ~ action! }
  }

\ExplSyntaxOff

\TestFunction{key2}

\TestFunction{key4}

\end{document}

The expected result would be

enter image description here

The MWE produces this result but the content of the \TestFunction is hard-coded and is not dynamically created from the two given comma lists.


Below is my current attempt:

\NewDocumentCommand { \TestFunction } { m }
  {
    \clist_set_eq:NN \l_tmpa_clist \l__mymodule_acts_clist
    \tl_clear:N \l_tmpa_tl
    \clist_map_inline:Nn \l__mymodule_keys_clist
      {
        \tl_put_right:Nn \l_tmpa_tl { { ##1 } }
        \clist_pop:NN \l_tmpa_clist \l_tmpb_tl
        \exp_args:NNe \tl_put_right:Nn \l_tmpa_tl { { \l_tmpb_tl } }
      }
    \exp_args:Nno \str_case:nnF { #1 } { \l_tmpa_tl } { No ~ action! }
  }

Though it works in this particular case, the problem is that it uses the e-type expansion which would require the content of the second comma list to be fully expandable, which is not the case if it contains things like \textbf. The thing is that when popping the first item from the second clist, it seems that I can only save it to a macro, say \l_tmpb_tl; then later on, when I wish to append { \l_tmpb_tl } to a temporary macro (here \l_tmpa_tl), the o-type expansion that expand it once does not seem to be enough. Is there some way to improve this code or is there an alternative and better approach?

Best Answer

You seem to want to turn the two comma lists into a property list (I'm rather keen to believe this is an XY-question).

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\makepropfromclists}{O{default}mm}
 {% #1 = name of the prop, #2 = name of the keys clist, #3 = name of the actions clist
  \prop_clear_new:c { l_mymodule_keysacts_#1_prop }
  \int_step_inline:nn { \clist_count:c { l__mymodule_#2_clist } }
   {
    \prop_put:cxx { l_mymodule_keysacts_#1_prop }
     { \clist_item:cn { l__mymodule_#2_clist } { ##1 } }
     { \clist_item:cn { l__mymodule_#3_clist } { ##1 } }
   }
 }

\NewDocumentCommand{\TestFunction}{O{default}m}
 {
  \prop_if_in:cnTF { l_mymodule_keysacts_#1_prop } { #2 }
   {
    \prop_get:cnN { l_mymodule_keysacts_#1_prop } { #2 } \l_tmpa_tl
    \tl_use:N \l_tmpa_tl
   }
   { No~action! }
 }

\clist_new:N \l__mymodule_keys_clist
\clist_new:N \l__mymodule_acts_clist
\clist_set:Nn \l__mymodule_keys_clist { key1, key2, key3 }
\clist_set:Nn \l__mymodule_acts_clist { act1, act2, act3 }

\makepropfromclists{keys}{acts}

\ExplSyntaxOff

\begin{document}

\TestFunction{key2}

\TestFunction{key4}

\end{document}

enter image description here

Don't use clists for what they aren't thought for.

Related Question