0

This is actually a more general question, but since a MWE is almost universally called for, consider David Carlisle's code

\documentclass{article}
\usepackage{fontspec}
\usepackage{nopageno}

\newfontfamily\mathematica[NFSSFamily=mathematica]{STIX Two Math}%

\DeclareSymbolFont{wm}{TU}{mathematica}{m}{n}
\DeclareSymbolFont{wmb}{TU}{mathematica}{b}{n}

\ExplSyntaxOn


\Umathcode"03B1  = 0 \symwm  "003B1
\Umathcode"03B2  = 0 \symwm  "003B2

\NewDocumentCommand{\mapcommands}{mm}
{
    \seq_set_from_clist:Nn\l_cmds{#1}
    \seq_set_from_clist:Nn\l_chars{#2}
    \seq_map_pairwise_function:NNN\l_cmds\l_chars\mapcommandfunction
}

\NewDocumentCommand{\mapcommandfunction}{mm}{\cs_set:Npx #1 {\codepoint_generate:nn{#2}{11}}}

\mapcommands{\alphatwo,\beta}{"03B1,"03B2}

\ExplSyntaxOff

\show\alphatwo
\begin{document}
    $$\alphatwo\beta$$
\end{document}

in his answer to one of my previous questions: https://tex.stackexchange.com/a/691806/224317. To make this code do everything I would like it to do, there needs to be a companion function called \mapcodes that maps standard codes like "03B1 for a Greek alpha to the slot location in the specific font. The only essential difference is that it needs to include a third argument containing the font family and probably needs to accept a different type specifier in the first argument. A working version of that is provided by egreg here: https://tex.stackexchange.com/a/691747/224317. Now, for the tricky part and the gist of the question.

I would like both of these functions to be able to take single arguments as well as comma-separated lists where applicable. As long as the list is provided "inline", I think they will work as is. I know for a fact that

\mapcommands{\alphatwo,\beta}{"03B1,"03B2}
\mapcommands{\gamma}{"03B3}

causes no problem, for instance. I presume the second usage is treated as a list of length one. But I also would like to be able to create and name lists with commands of the form

\DeclareCommandList{GreekCommands}{\alpha,\beta,\gamma,\delta}
\DeclareCodeList{GreekCodes}{"03B1,"03B2,"03B3,"03B4}

analogous to \defineblock in egreg's answer and then pass them as follows:

\mapcommands{GreekCommands}{GreekCodes}

I have experimented, but being new to expl3 and still a little rough in my understanding of the underlying TeX expansion mechanism, I have not yet achieved success. I am guessing there is either (a) a way to take a generalized argument and then determine its nature, doing something applicable with each case, or (b) a way to do something equivalent to function overloading. It appears that expl3 may provide something like this with variants in the l3expan package, but I'm not sure. So while I would like to solve this specific problem, I would also like to understand the differences in these two calling mechanisms in general, how to deal with them, tips for troubleshooting, and so forth.

7
  • \seq_set_from_clist:Ne\l_cmds{#1} would expand #1 before treating it as a list (you may need to generate that variant) but then unlike the current version, undefined commands would be an error, you need to choose what behaviour you want Jul 26, 2023 at 12:57
  • function overloading really goes against the tex (and L3) model which is why L3 is always explicit about argument types \seq_map_pairwise_function:NNN and \seq_map_pairwise_function:nnN are essentially overloaded signatures of the same base function but they are separate names distinguished in the call Jul 26, 2023 at 12:59
  • @DavidCarlisle Assuming that I can unravel how to generate the variant you mention in your first comment, given that you're saying passing in, say, \koppa when it has not been defined would cause an error, would this new problem be remedied by passing in koppa instead and then defining the command with \cs_set?
    – Mike Pugh
    Jul 26, 2023 at 16:11
  • \cs_generate_variant:Nn\seq_set_from_clist:Nn{Ne} should work, yes if you ensure your lists are expandable, but seems more trouble to do that than simply have two commands Jul 26, 2023 at 16:15
  • I'm sure I already commented that, but: DO NOT USE $$ TO START DISPLAY MATH IN LATEX!!! And please don't show it in MWEs. This way it only spreads further :(
    – Skillmon
    Jul 26, 2023 at 18:46

1 Answer 1

1

The following adds the two macros and support for them to your MWE.

The support is added by introducing two optional stars, if either star is given the next mandatory argument is considered as a named list input instead of a comma separated list.

We could also not require the stars, and instead check whether such a list exists, if you need help with that just leave a comment.

\documentclass{article}
\usepackage{fontspec}
\usepackage{nopageno}

\newfontfamily\mathematica[NFSSFamily=mathematica]{STIX Two Math}%

\DeclareSymbolFont{wm}{TU}{mathematica}{m}{n}
\DeclareSymbolFont{wmb}{TU}{mathematica}{b}{n}

\ExplSyntaxOn


\Umathcode"03B1  = 0 \symwm  "003B1
\Umathcode"03B2  = 0 \symwm  "003B2
\Umathcode"03B3  = 0 \symwm  "003B3
\Umathcode"03B4  = 0 \symwm  "003B4


\msg_new:nnn { mike-pugh } { unknown-cmd-list }
  { The~ named~ cmd~ list~ `#1'~ is~ unknown.~ Make~ sure~ you~ defined~ it. }
\msg_new:nnn { mike-pugh } { unknown-char-list }
  { The~ named~ char~ list~ `#1'~ is~ unknown.~ Make~ sure~ you~ defined~ it. }
\seq_new:N \l__mikepugh_cmds_seq
\seq_new:N \l__mikepugh_chars_seq
\NewDocumentCommand \mapcommands { s m s m }
  {
    \IfBooleanTF {#1}
      {
        \seq_if_exist:cTF { l__mikepugh_cmds_ \tl_to_str:n {#2} _seq }
          {
            \seq_set_eq:Nc \l__mikepugh_cmds_seq
              { l__mikepugh_cmds_ \tl_to_str:n {#2} _seq }
          }
          { \msg_error:nnn { mike-pugh } { unknown-cmd-list } {#2} }
      }
      { \seq_set_from_clist:Nn \l__mikepugh_cmds_seq  {#2} }
    \IfBooleanTF {#3}
      {
        \seq_if_exist:cTF { l__mikepugh_chars_ \tl_to_str:n {#4} _seq }
          {
            \seq_set_eq:Nc \l__mikepugh_chars_seq
              { l__mikepugh_chars_ \tl_to_str:n {#4} _seq }
          }
          { \msg_error:nnn { mike-pugh } { unknown-char-list } {#2} }
      }
      { \seq_set_from_clist:Nn \l__mikepugh_chars_seq {#4} }
    \seq_map_pairwise_function:NNN
      \l__mikepugh_cmds_seq \l__mikepugh_chars_seq \mapcommandfunction
  }

\NewDocumentCommand \DeclareCommandList { m m }
  {
    \seq_clear_new:c { l__mikepugh_cmds_ \tl_to_str:n {#1} _seq }
    \seq_set_from_clist:cn { l__mikepugh_cmds_ \tl_to_str:n {#1} _seq } {#2}
  }
\NewDocumentCommand \DeclareCodeList { m m }
  {
    \seq_clear_new:c { l__mikepugh_chars_ \tl_to_str:n {#1} _seq }
    \seq_set_from_clist:cn { l__mikepugh_chars_ \tl_to_str:n {#1} _seq } {#2}
  }

\NewDocumentCommand \mapcommandfunction { m m }
  { \cs_set:Npx #1 { \codepoint_generate:nn {#2} {11} } }

\mapcommands{\alphatwo,\beta}{"03B1,"03B2}

\DeclareCommandList{GreekCommands}{\alpha,\gamma,\delta}
\DeclareCodeList{GreekCodes}{"03B1,"03B3,"03B4}
\mapcommands*{GreekCommands}*{GreekCodes}

\ExplSyntaxOff

\show\alphatwo
\show\delta
\begin{document}
\[\alphatwo\beta\delta\]
\end{document}

You must log in to answer this question.

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