如何在宏/命令/函数体中模拟字符串插值?

如何在宏/命令/函数体中模拟字符串插值?

我是 LaTeX 的新手,我正在尝试迭代在这个精彩的论坛上找到的可用解决方案。

% 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"
m % #2: <sequence> 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"
m % #2: <sequence> 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" 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"
#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 }
  % 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"
#2 % <sequence> 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" 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"
#2 % <sequence> 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" 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)

我想以某种方式模拟用提供的参数替换 #1 等的行为。我已将其放在所有声明之前:

\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}

并在下面添加了此功能:

\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
}

以下是我尝试使用它的方法:

\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 }
}

再次强调,我是 LaTeX 新手,http://ctan.mirror.colo-serv.net/macros/latex/contrib/l3kernel/interface3.pdf对我没什么帮助。

答案1

这里介绍一种listofitems方法,我使用以下四个命令引入了略有不同的语法:

\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

如果有人喜欢不同的分隔符,我会显示设置的位置,当然,列表分隔符也会遵循该设置。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}

在此处输入图片描述

相关内容