2

I am new to LaTeX and I am trying to iterate on the available solution that I found on this wonderful forum.

% Credit: https://tex.stackexchange.com/questions/215563/storing-an-array-of-strings-in-a-command
\ExplSyntaxOn

% Some commands are declared with NewDocumentCommand and NewExpandableDocumentCommand because \ExplSyntaxOn messes up with text % (produces no spaces)

\NewDocumentCommand{\storedata}{ m % #1: <token list> array name; for example, a_wonderful_name_for_my_array&quot; m % #2: &lt;sequence&gt; that stores braced list of values; for example,{one}{two}{three}" } { \au_store_data:nn { #1 } { #2 } }

\NewDocumentCommand{\appenddata}{ m % #1: <token list> array name; for example, a_wonderful_name_for_my_array&quot; m % #2: &lt;sequence&gt; of values to append; for example,{one}{two}{three}" } { \au_append_data:nn { #1 } { #2 } }

\NewExpandableDocumentCommand{\getdata}{ O{1} % #1: <integer expression> that evalues to the accessed index m % #2: <token list> array name; for example, ``a_wonderful_name_for_my_array" } { \au_get_data:nn { #1 } { #2 } }

\NewExpandableDocumentCommand{\getlength}{ m % #1: <token list> array name; for example, ``a_wonderful_name_for_my_array" } { \au_get_length:n { #1 } }

\NewDocumentCommand{\removelast}{ o % #1: <cname> output variable prefixed with a ''; for example, scratch variable \l_tmpa_tl&quot; or\scope_module_description_type" m % #2: <token list> array name; for example, ``a_wonderful_name_for_my_array" } { \au_remove_last:Nn { #1 } { #2 } }

\cs_new_protected:Npn \au_store_data:nn #1 % <token list> array name; for example, a_wonderful_name_for_my_array&quot; #2 % &lt;sequence&gt; that stores braced list of values; for example,{one}{two}{three}" { % create the sequence if it doesn't exist or clear it if it exists \seq_clear_new:c { l_au_data_#1_seq } % append the items __au_append_data:nn { #1 } { #2 } }

\cs_new_protected:Npn \au_append_data:nn #1 % <token list> array name; for example, a_wonderful_name_for_my_array&quot; #2 % &lt;sequence&gt; of values to append; for example,{one}{two}{three}" { % create the sequence if it doesn't exist, do nothing if it exists \seq_if_exist:cF { l_au_data_#1_seq } { \seq_new:c { l_au_data_#1_seq } } % append the items __au_append_data:nn { #1 } { #2 } }

\cs_new:Npn \au_get_data:nn #1 % <integer expression> that evalues to the accessed index #2 % <token list> array name; for example, ``a_wonderful_name_for_my_array" { % retrieve the requested item \seq_item:cn { l_au_data_#2_seq } { #1 } }

\cs_new:Npn \au_get_length:n #1 % <token list> array name; for example, ``a_wonderful_name_for_my_array" { \seq_count:c { l_au_data_#1_seq } }

\cs_new_protected:Npn \au_remove_last:Nn #1 % <cname> output variable prefixed with a ''; for example, scratch variable \l_tmpa_tl&quot; or\scope_module_description_type" #2 % <token list> array name; for example, ``a_wonderful_name_for_my_array" { \IfNoValueTF { #1 } { __au_remove_last:Nn \l_tmpa_tl { #2 } } { __au_remove_last:Nn #1 { #2 } } }

\cs_new_protected:Npn __au_append_data:nn #1 % <token list> array name; for example, a_wonderful_name_for_my_array&quot; #2 % &lt;sequence&gt; of values to append; for example,{one}{two}{three}" { % append items one at a time \tl_map_inline:nn { #2 } { \seq_put_right:cn { l_au_data_#1_seq } { ##1 } } }

\cs_new_protected:Npn __au_remove_last:Nn #1 % <cname> output variable prefixed with a ''; for example, scratch variable \l_tmpa_tl&quot; or\scope_module_description_type" #2 % <token list> array name; for example, ``a_wonderful_name_for_my_array" { \seq_pop_right:cN { l_au_data_#2_seq } #1 }

\ExplSyntaxOff % Credit (end)

I would like to somehow emulate the behavior of replacing #1 etc with provided arguments. I've placed this before all declarations:

\tl_new:N \g_au_internal_seq_prefix_tl
\tl_gset:Nn \g_au_internal_seq_prefix_tl {l_au_data_}
\tl_new:N \g_au_internal_seq_postfix_tl
\tl_gset:Nn \g_au_internal_seq_postfix_tl {_seq}

and added this function below:

\cs_new_protected:Npn \au_get_internal_seq_name_by_array_name:n
#1 % <token list> array name; for example, ``a_wonderful_name_for_my_array"
{
    \tl_set_eq:NN \l_tmpa_tl \g_au_internal_seq_prefix_tl
    \tl_put_right:Nn \l_tmpa_tl { #1 }
    \tl_put_right:NV \l_tmpa_tl \g_au_internal_seq_prefix_tl
    \tl:use:N \l_tmpa_tl
}

Here is how I tried to use it:

\cs_new_protected:Npn \au_store_data:nn
#1 % <token list> array name; for example, ``a_wonderful_name_for_my_array"
#2 % <sequence> that stores braced list of values; for example, ``{one}{two}{three}"
{
    % create the sequence if it doesn't exist or clear it if it exists
    %\seq_clear_new:c { l_au_data_#1_seq }
    \seq_clear_new:c { \tl_use:N \au_get_internal_seq_name_by_array_name:n{ #1 } }
    % append the items
    \__au_append_data:nn { #1 } { #2 }
}

Once again, I'm new to LaTeX and http://ctan.mirror.colo-serv.net/macros/latex/contrib/l3kernel/interface3.pdf wasn't a big help to me.

1 Answers1

2

Here is a listofitems approach, where I have introduced slightly different syntax, with these four commands:

\initializedata<\array>{<comma separated list>}% TO DEFINE LIST
<\array[element number]>% TO RECALL LIST ELEMENT
\replacedata<\array[element number]>{<replacement data>}% TO REPLACE DATA
\extenddata<\array>{<data to extend list>}% TO EXTEND LIST

If one prefers a different separator, I show where that is set, and of course, the list separators follow that lead. The MWE:

\documentclass{article}
\usepackage{listofitems}
\setsepchar{,}% <---LIST SEPARATOR
\newcommand\initializedata[2]{\readlist*#1{#2}}
\makeatletter
\def\replacedata#1[#2]#3{%
  \def\tmp{}%
  \foreachitem\z\in#1[]{%
    \ifnum\zcnt=1\else\g@addto@macro\tmp{,}\fi
    \ifnum\zcnt=#2\relax\g@addto@macro\tmp{#3}\else
      \expandafter\g@addto@macro\expandafter\tmp\expandafter{\z}%
    \fi
  }%
  \readlist*#1{\tmp}%
}
\newcommand\extenddata[2]{%
  \def\tmp{}%
  \foreachitem\z\in#1[]{%
    \ifnum\zcnt=1\else\g@addto@macro\tmp{,}\fi
    \expandafter\g@addto@macro\expandafter\tmp\expandafter{\z}%
  }%
  \g@addto@macro\tmp{,#2}%
  \readlist*#1{\tmp}%
}
\makeatother
\begin{document}
\initializedata\mydata{23, 46, Hi mom, foo, bar}
Element 3 is \mydata[3]

\replacedata\mydata[3]{Bye mom} Element 3 is \mydata[3]

Element 4 is \mydata[4]

\extenddata\mydata{More, data, added} Element 7 is \mydata[7]

\end{document}

enter image description here

  • Thank you for your answer, but I'm actually trying to figure out how to emulate the replacing of the string inside the macro body. I'm creating a custom package for making my overgrown glossary slightly more manageable. I will have to do a lot of replacement (index with a letter, letter with the names of arrays storing the hyperlink tags and those storing the names of the entries, etc). – Dmitrii Demenev Apr 25 '21 at 22:49
  • @DmitriiDemenev I understand. There is an \xpatchcmd command, part of the xpatch package, that allows macros to be patched directly. Also, I've written a package called tokcycle that allows tokens from an input stream to be examined one-by-one with user-defined directives on how to proceed. Perhaps there may be something there for your need. – Steven B. Segletes Apr 25 '21 at 23:16