8

I have a mathematical symbol with 6 labels but there are multiple conventions for displaying such a symbol. One way would be [F^{abc}_d]_{ef} but other people use, e.g., [F^{abc}_d]^{e}_{f} or other forms. Since I'm at the start of writing a thesis I'd prefer not to make an absolute choice and decided to define a command with 6 labels as input such as

\newcommand{\F}[6]{[F^{{#1} {#2} {#3}}_{#4}]^{#5}_{#6}} 

but then I have to type \F{a}{b}{c}{d}{e}{f} which is a bit cumbersome. Is there any way that I could call the new command using a comma separated list, e.g. \F{a,b,c,d,e,f}, instead of the standard way??

5
  • Write a second macro, which process your short version ... Commented Mar 9, 2022 at 13:17
  • I haven't done this myself, but I have the impression that using a keyval package would make the most sense since it allows you to name the parameters and define default values, which makes writing macros a lot easier. Here is a long list of these packages: tex.stackexchange.com/questions/26771/… Moreover, this might be helpful in finding the correct package for your use case: tex.stackexchange.com/questions/292869/… Commented Mar 9, 2022 at 13:21
  • there are various options to handle a comma list, e.g. with expl3 but also with etoolbox. Commented Mar 9, 2022 at 13:26
  • @MS-SPO Would you like to elaborate on how to do that? I'm quite new to macros myself... Commented Mar 9, 2022 at 13:36
  • Can the values of labels (a, ..., f) contain a comma? Commented Mar 9, 2022 at 16:34

4 Answers 4

7

The listofitems package can parse lists, using a comma (default) or other designated tokens.

Note that your list will need at least 5 commas, or an error will occur when calling \Fvar[6].

\documentclass{article} \usepackage{listofitems} \newcommand{\F}[1]{% \readlist*\Fvar{#1}% [F^{{\Fvar[1]} {\Fvar[2]} {\Fvar[3]}}_{\Fvar[4]}]^{\Fvar[5]}_{\Fvar[6]}} \begin{document} \begin{equation} \F{a,b,c,d,e,f} \end{equation} \end{document} 

enter image description here

3
  • Thank you so much for the response! I do get an error when using 10 parameters though. I read the documentation of listofitems but it doesn't give any indication as to why this error occurs. Commented Sep 19, 2022 at 15:19
  • @Gert \newcommand can take no more than 9 parameters...this is a limitation intrinsic to TeX. However, for the approach detailed in this answer, there should not be a problem if the list exceeds 9 items...when doing so, \Fvar[10] would access the 10th item of this list. Commented Sep 19, 2022 at 23:03
  • thank you very much. Somehow it does complain about the 10. I did `solve' the problem by using \Fvar[-1], though, which gives me the feeling the problem has more to do with the package than with \newcommand Commented Sep 20, 2022 at 8:22
5

you can try

\documentclass{article} \begin{document} \def\F(#1,#2,#3,#4,#5,#6){[F^{{#1}{#2}{#3}}_{#4}]^{#5}_{#6}} $\F(a,b,c,d,e,f)$ \end{document} 
4

You can use expl3's \clist_map_function:nN or the like for mapping all items of a comma-separated list to a function which appends its argument to a token-list, nested in braces.

Then you can use \tl_count:V for counting the brace-nested arguments. If there are six of them, proceed by prepending to the token-list the call to the underlying macro for processing six arguments. If there are not six of them, raise an error.

A problem is that \clist_map_function:nN silently skips/discards blank comma-list items. This can be prevented, e.g., by regexp-replacing in the comma-list any number of horizontal spaces ocurring between commas by the same number of horizontal spaces, but nested in braces. In order to forbid a trailing comma in the comma-list the same can be done with any number of horizontal spaces ocurring between the last comma and the end of the comma-list.

\ExplSyntaxOn \cs_new:Nn \__MyStuff_Replaceblankitems: { \exp_args:NnV \regex_match:nnTF {\,([\s])*\,} \l_tmpb_tl { \regex_replace_all:nnN {\,([\s])*\,} {\,\{\1\}\,} \l_tmpb_tl \__MyStuff_Replaceblankitems: } { \regex_replace_all:nnN {\,([\s])*\z} {\,\{\1\}} \l_tmpb_tl } } \cs_new_protected:Npn \F #1 { \tl_set:Nn \l_tmpb_tl {#1} % nest blank items of the comma-list between braces so that \clist_map_function:nN will not discard them. \__MyStuff_Replaceblankitems: %\tl_show:N \l_tmpb_tl \tl_clear:N \l_tmpa_tl \exp_args:NV \clist_map_function:nN \l_tmpb_tl {\__MyStuff_PutRightTo_l_tempa_tl:n } \int_compare:nNnTF {\tl_count:V {\l_tmpa_tl}} = {6} {\tl_put_left:Nn \l_tmpa_tl {\__MyStuff_F:nnnnnn} \tl_use:N \l_tmpa_tl } {\msg_error:nnn { MyStuff } { not-six-items } { \F }} \tl_clear:N \l_tmpa_tl \tl_clear:N \l_tmpb_tl } \cs_new:Nn \__MyStuff_F:nnnnnn { [F\c_math_superscript_token{{#1}{#2}{#3}} \c_math_subscript_token{#4}] \c_math_superscript_token{#5} \c_math_subscript_token{#6} } \cs_new:Nn \__MyStuff_PutRightTo_l_tempa_tl:n {\tl_put_right:Nn \l_tmpa_tl {{#1}}} \msg_new:nnn { MyStuff } { not-six-items } { \token_to_str:N #1's~argument~does~not~hold~a~comma-list~with~six~components.} \prop_gput:Nnn \g_msg_module_type_prop { MyStuff } {} \prop_gput:Nnx \g_msg_module_name_prop { MyStuff } {\jobname.tex~(main)} \ExplSyntaxOff \documentclass{article} \begin{document} \[\F{a,b,c,d,e,f}\] % These raise errors: %\[\F{a,b,c,d,e,f, }\] %\[\F{a,b,c,d,e,f,}\] %\[\F{a,b,c,d,e, ,,f}\] %\[\F{a,b,c,d,e,f,g}\] \end{document} 

enter image description here

3

You can use expl3 and extract the items from the list by number.

\documentclass{article} \ExplSyntaxOn \NewDocumentCommand{\F}{m} { \int_compare:nF { \clist_count:n { #1 } = 6 } { \ERROR } [F \sp { \clist_item:nn {#1}{1} \clist_item:nn {#1}{2} \clist_item:nn {#1}{3} } \sb { \clist_item:nn {#1}{4} } ] \sp { \clist_item:nn {#1}{5} } \sb { \clist_item:nn {#1}{6} } } \ExplSyntaxOff \begin{document} $\F{a,b,c,d,e,f}$ \end{document} 

enter image description here

A different (and more efficient) strategy would be to replace {a,b,c,d,e,f} with {a}{b}{c}{d}{e}{f}, which can be done in the following way: with \clist_map_function:nN we can use a function that braces the item; so from a,b,c,d,e,f we can expand the mapping at once and so \gert_f:n will be called as

\gert_f:n { {a}{b}{c}{d}{e}{f} } 

and it can pass the argument to the “internal” six argument function.

\documentclass{article} \ExplSyntaxOn \NewDocumentCommand{\F}{m} { \int_compare:nTF { \clist_count:n { #1 } = 6 } { \gert_f:e { \clist_map_function:nN { #1 } \__gert_f_brace:n } } { \ERROR } } \cs_new_protected:Nn \gert_f:n { \__gert_f:nnnnnn #1 } \cs_generate_variant:Nn \gert_f:n { e } \cs_new_protected:Nn \__gert_f:nnnnnn { [F \sp { #1 #2 #3 } \sb { #4 }] \sp { #5 } \sb { #6 } } \cs_new:Nn \__gert_f_brace:n { {#1} } \ExplSyntaxOff \begin{document} $\F{a,b,c,d,e,f}$ \end{document} 

In either case you have just one place where applying changes if a different output style is decided upon.

The error checking is just hinted at and something more detailed can be added easily.

If you plan to have empty items, then you need to split the list into a sequence, so empty items will not be discarded.

\documentclass{article} \ExplSyntaxOn \NewDocumentCommand{\F}{m} { \seq_set_split:Nnn \l__gert_f_seq { , } { #1 } \int_compare:nTF { \seq_count:N \l__gert_f_seq = 6 } { \gert_f:e { \seq_map_function:NN \l__gert_f_seq \__gert_f_brace:n } } { \ERROR } } \seq_new:N \l__gert_f_seq \cs_new_protected:Nn \gert_f:n { \__gert_f:nnnnnn #1 } \cs_generate_variant:Nn \gert_f:n { e } \cs_new_protected:Nn \__gert_f:nnnnnn { [F \sp { #1 #2 #3 } \sb { #4 }] \sp { #5 } \sb { #6 } } \cs_new:Nn \__gert_f_brace:n { {#1} } \ExplSyntaxOff \begin{document} $\F{a,b,c,d,e,f}$ $\F{a,,c,d,,f}$ \end{document} 

enter image description here

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.