expl3 支持 int 数组。但是 dims 数组呢?
我需要一个整数索引数组变量,用于保存 dim 值。数组大小应该能够随时增长,而不是提前知道(我不知道它将保存多少 dim 值,大小取决于自定义环境的嵌套级别)。例如,如果计数器为 1,则数组大小为 1;如果计数器增长到 3,则数组应该增长到 3 个索引。
我需要类似下面的索引变量myDim
。
myDim[1]=5.0pt
myDim[2]=7.35pt
...
编辑:
% \myDim = 0 here
\begin{myEnv} % myDim[1] = 5.0pt; current index = 1
\begin{myEnv} % myDim[2] = 7.35pt; current index = 2
\end{myEnv} % current index = 1
\end{myEnv} % current index = 0
答案1
不能intarray
改变大小,并且对它的分配始终是全局的,因此您不能利用环境分组来模拟这样的行为(至少不容易)。的文档l3intarray
确实说:
intarray
因此,在需要快速访问的情况下,建议使用数据。
但大多数情况下并非如此。如果您不打算使用包含数千个元素的数组并访问这些元素数千次,那么变量seq
可能就足够了。
这是一个特别指定一种数据类型的实现array
,它提供与 大致相同的接口,l3intarray
但底层使用 的数据类型expl3
。seq
接口:
\array_new:N ⟨array var⟩
— 创建一个⟨array var⟩
没有元素的新变量。\array_zero:N ⟨array var⟩
— 将所有元素设置为零⟨array var⟩
。\array_allocate:Nn ⟨array var⟩ {⟨num items⟩}
— 将 分配⟨array var⟩
为⟨num items⟩
,所有 都等于0pt
。 中已有的项目⟨array var⟩
保持不变,因此可以多次使用。\array_deallocate:N ⟨array var⟩
— 设置⟨array var⟩
为没有元素。\array_count:N ⟨array var⟩
★ — 扩展为 中的元素数量⟨array var⟩
。\array_item:Nn ⟨array var⟩ {⟨index⟩}
⟨index⟩
★ — 扩展到位置存储的维度⟨array var⟩
。如果⟨index⟩
大于 的大小⟨array var⟩
,则函数扩展为零。如果⟨index⟩
小于零,则索引从数组末尾开始计算。\array_set:Nnn ⟨array var⟩ {⟨index⟩} {⟨dimen⟩}
⟨index⟩
— 设置的位置⟨array var⟩
以包含⟨dimen⟩
。如果⟨array var⟩
不包含⟨index⟩
,则元素将分配(包含\array_allocate:Nn
)直到⟨index⟩
存在。\array_put_left:Nn ⟨array var⟩ {⟨dimexpr⟩}
— 在末尾添加一个项目⟨array var⟩
并放入⟨dimexpr⟩
其中。\array_put_right:Nn ⟨array var⟩ {⟨dimexpr⟩}
— 在 开头添加一个项目⟨array var⟩
并放入⟨dimexpr⟩
其中。\array_set_from_clist:Nn ⟨array var⟩ {⟨clist⟩}
— 设置⟨array var⟩
以包含 的项目⟨clist⟩
。\array_log:N ⟨array var⟩
— 写入⟨array var⟩
日志文件。\array_show:N ⟨array var⟩
— 显示⟨array var⟩
在命令窗口中。
标有★的功能完全可扩展。所有分配都是本地的(如果您需要全局分配,请在评论中询问),除了\array_new:N
创建⟨array var⟩
全局的。
代码如下:
\RequirePackage{filecontents}
\begin{filecontents}{bparray.sty}
\RequirePackage{expl3}
\ProvidesExplPackage{bparray}{2019-06-29}{0.1}{Array data type for expl3 (PHO)}
\cs_new_eq:NN \array_new:N \seq_new:N
\cs_new_eq:NN \array_count:N \seq_count:N
\cs_new_eq:NN \array_item:Nn \seq_item:Nn
\cs_new_eq:NN \array_deallocate:N \seq_clear:N
\cs_new_eq:NN \array_show:N \seq_show:N
\cs_new_eq:NN \array_log:N \seq_log:N
\cs_new_eq:NN \array_put_right:Nn \seq_put_right:Nn
\cs_new_eq:NN \array_put_left:Nn \seq_put_left:Nn
\cs_new_protected:Npn \array_allocate:Nn #1#2
{
\int_step_inline:nnn { \array_count:N #1 + 1 } { #2 }
{ \exp_args:NNx \array_put_right:Nn #1 { \dim_use:N \c_zero_dim } }
}
\cs_new_protected:Npn \array_set:Nnn #1#2
{
\int_compare:nNnT {#2} > { \array_count:N #1 }
{ \array_allocate:Nn #1 {#2} }
\__array_set_item:Nnn #1 {#2}
}
\cs_new_protected:Npn \__array_set_item:Nnn #1
{ \exp_after:wN \__array_item:wNn #1 \q_stop #1 }
\cs_new_protected:Npn \__array_item:wNn \s__seq #1 \q_stop #2#3#4
{
\exp_args:Nf \__array_item:nnwn
{ \exp_args:Nf \__seq_item:nN { \int_eval:n {#3} } #2 } { }
#1
\prg_collect_point:
\__array_replace_item:Nn #2 {#4}
\prg_break: \__seq_item:n { }
\prg_break_point:
}
\cs_new_protected:Npn \__array_item:nnwn #1#2#3 \__seq_item:n #4
{
#3
\int_compare:nNnTF {#1} = 1
{
\tl_set:Nn \l__array_internal_tl {#2}
\prg_break_collect:Nw \__array_set_item_end:n
}
{
\exp_args:Nf \__array_item:nnwn
{ \int_eval:n { #1 - 1 } }
{ #2 \__seq_item:n {#4} }
}
}
\cs_new_protected:Npn \__array_set_item_end:n #1
{ \exp_args:NV \__array_set_item_end:nnwn \l__array_internal_tl {#1} }
\cs_new_protected:Npn \__array_set_item_end:nnwn #1 #2 \__array_replace_item:Nn #3 #4
{
\tl_set:Nx #3
{
\s__seq
\exp_not:n {#1}
\exp_not:N \__seq_item:n { \dim_eval:n {#4} }
\exp_not:n {#2}
}
\prg_break:
}
\cs_new_eq:NN \__array_replace_item:Nn \use_none:nn
\cs_new:Npn \prg_break_collect:Nw #1 #2 \prg_collect_point: { #1{#2} }
\cs_new_eq:NN \prg_collect_point: \prg_do_nothing:
\cs_new_protected:Npn \array_zero:N #1
{ \exp_args:Nf \__array_zero:nN { \array_count:N #1 } #1 }
\cs_new_protected:Npn \__array_zero:nN #1#2
{
\array_deallocate:N #2
\array_allocate:Nn #2 {#1}
}
\cs_new_protected:Npn \array_set_from_clist:Nn #1#2
{
\array_deallocate:N #1
\clist_map_inline:nn {#2}
{ \exp_args:NNx \array_put_right:Nn #1 { \dim_eval:n {##1} } }
}
\end{filecontents}
以及测试文档:
\documentclass{article}
\usepackage{bparray}
\begin{document}
\ExplSyntaxOn
\array_new:N \l_bp_array
\array_log:N \l_bp_array \array_allocate:Nn \l_bp_array { 3 }
\array_log:N \l_bp_array \array_set:Nnn \l_bp_array { 5 } { 1 pt + 2.141592 pt }
\array_log:N \l_bp_array \array_zero:N \l_bp_array
\array_log:N \l_bp_array \array_set_from_clist:Nn \l_bp_array { 1pt, 2pt, 3pt }
\array_log:N \l_bp_array
\ExplSyntaxOff
\end{document}
然后.log
包含:
The sequence \l_bp_array is empty
> .
The sequence \l_bp_array contains the items (without outer braces):
> {0.0pt}
> {0.0pt}
> {0.0pt}.
The sequence \l_bp_array contains the items (without outer braces):
> {0.0pt}
> {0.0pt}
> {0.0pt}
> {0.0pt}
> {3.14159pt}.
The sequence \l_bp_array contains the items (without outer braces):
> {0.0pt}
> {0.0pt}
> {0.0pt}
> {0.0pt}
> {0.0pt}.
The sequence \l_bp_array contains the items (without outer braces):
> {1.0pt}
> {2.0pt}
> {3.0pt}.
然后您可以轻松定义该环境:
\documentclass{article}
\usepackage{bparray}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l_myenv_int
\array_new:N \l_myenv_array
\array_set_from_clist:Nn \l_myenv_array { 5pt, 7.35pt }
\NewDocumentEnvironment {myEnv} { }
{ \int_incr:N \l_myenv_int } { }
\NewDocumentCommand \arrayitem { }
{ \array_item:Nn \l_myenv_array { \l_myenv_int } }
\NewDocumentCommand \arrayindex { }
{ \int_use:N \l_myenv_int }
\ExplSyntaxOff
\begin{document}
Array index = \arrayindex{} and array item = \arrayitem\par
\begin{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\begin{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{document}
输出为:
但是看起来您实际上并不需要动态分配。上面的结果可以通过以下方式轻松实现fparray
(不同之处在于可能会发生索引越界错误):
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l_myenv_int
\fparray_new:Nn \l_myenv_fparray { 2 }
\fparray_gset:Nnn \l_myenv_fparray { 1 } { 5pt }
\fparray_gset:Nnn \l_myenv_fparray { 2 } { 7.35pt }
\NewDocumentEnvironment {myEnv} { }
{ \int_incr:N \l_myenv_int } { }
\NewDocumentCommand \arrayitem { }
{ \dim_eval:n { \fparray_item:Nn \l_myenv_fparray { \l_myenv_int } pt } }
\NewDocumentCommand \arrayindex { }
{ \int_use:N \l_myenv_int }
\ExplSyntaxOff
\begin{document}
% Array index = \arrayindex{} and array item = \arrayitem\par % Error
\begin{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\begin{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
% Array index = \arrayindex{} and array item = \arrayitem\par % Error
\end{document}
输出: