再次出现扩展问题

再次出现扩展问题

我似乎一直遇到同样的问题。为了更多地了解扩展,我编写了一个程序,该程序以 1 的序列开始,然后在每一步之后将其递增以生成 2 的序列,等等。然后,生成的所有不同序列必须tikz以以下格式显示在矩阵中:

在此处输入图片描述

我使用了以下代码:

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\ExplSyntaxOn
\NewDocumentCommand{\indexprod}{ m }  % indices   
{
    \seq_set_from_clist:Nn \l_tmpc_seq { #1 }
    \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
    {
        \seq_put_right:Nn \l_tmpa_seq {1}
        \seq_put_right:Nn \l_tmpb_seq {1}
    }
    \int_step_inline:nn {\seq_count:N \l_tmpc_seq - 1}
    {
        \tl_put_right:Nn \l_tmpa_tl {\mbox{\tiny $ \seq_item:Nn \l_tmpc_seq {##1} = 1$} \&}
    }
    \tl_put_right:Nn \l_tmpa_tl {\mbox{\tiny $ \seq_item:Nn \l_tmpc_seq {\seq_count:N \l_tmpc_seq} = 1$} \\}
    \int_new:N \l_tmpc_int
    \int_new:N \l_tmpd_int
    \int_set:Nn \l_tmpc_int {4}
    \int_step_inline:nnn {2} {\seq_count:N \l_tmpc_seq}
    {
        \int_set:Nn \l_tmpc_int {\l_tmpc_int * 4}
    }
    \int_log:N \l_tmpc_int
    \int_step_inline:nnn {2} {\l_tmpc_int} 
    {
        \int_set:Nn \l_tmpb_int {##1}
        \int_log:N \l_tmpb_int
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
        {
            \int_set:Nn \l_tmpa_int {\seq_item:Nn \l_tmpa_seq{####1}}
            \int_set:Nn \l_tmpd_int { \int_eval:n  {\l_tmpa_int + 1}}
            \int_log:N \l_tmpd_int
            \seq_set_item:NnV \l_tmpb_seq {####1} \l_tmpd_int 
        }
        \seq_log:N \l_tmpb_seq
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq - 1}
        {
            \tl_put_right:Nn \l_tmpa_tl {\mbox{\tiny $ \seq_item:Nn \l_tmpc_seq {####1} = \seq_item:Nn \l_tmpb_seq{####1} $} \&}
        }
        \tl_put_right:Nn \l_tmpa_tl {\mbox{\tiny $ \seq_item:Nn \l_tmpc_seq {\seq_count:N \l_tmpc_seq} = \seq_item:Nn \l_tmpb_seq {\seq_count:N \l_tmpb_seq}$} \\}
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
        {
            \int_set:Nn \l_tmpa_int {\int_eval:n {\seq_item:Nn \l_tmpb_seq{####1}}}
            \int_log:N \l_tmpa_int
            \seq_set_item:NnV \l_tmpa_seq {####1} \l_tmpa_int 
        }
        \seq_log:N \l_tmpa_seq
    }
    \begin{tikzpicture}[baseline={([yshift=-0ex]current~bounding~box.center)}]
        \matrix(m) [
          matrix~of~nodes,
           ampersand~replacement=\&,
           column~sep=1ex,
           nodes~in~empty~cells,
           nodes={
             shape=rectangle,
             minimum~height=3ex,
             anchor=center
           },
         ]{
            \tl_use:N \l_tmpa_tl
         };
    \end{tikzpicture}
}

\cs_generate_variant:Nn \seq_set_item:Nnn { NnV }
\ExplSyntaxOff

\begin{document}
\[
    \indexprod{i,j}    
\]

\end{document}

但结果当然是,

在此处输入图片描述

因为标记列表中的命令被冻结,并且诸如评估之类的命令\seq_item:Nn \l_tmpb_seq{####1}使用其最新值来计算,而这些最新值恰好等于 16。

我查阅了相关文档,试图找到一种方法来改变这样的表达方式,

\tl_put_right:Nn \l_tmpa_tl {\mbox{\tiny $ \seq_item:Nn \l_tmpc_seq {####1} = \seq_item:Nn \l_tmpb_seq{####1} $} \&}

所以我利用了这些价值观\seq_item:Nn \l_tmpb_seq{####1},但却没能取得突破。

欢迎任何想法...

答案1

您需要\tl_put_right:Nx让参数完全展开。但您不想完全展开\mbox\tiny,因此需要一个强大的包装器。用定义的命令\NewDocumentCommand永远不会在e-expansion 或x-expansion 中展开。

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\NewDocumentCommand{\tinybox}{m}{\mbox{\tiny#1}}

\ExplSyntaxOn
\NewDocumentCommand{\indexprod}{ m }  % indices   
{
    \seq_set_from_clist:Nn \l_tmpc_seq { #1 }
    \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
    {
        \seq_put_right:Nn \l_tmpa_seq {1}
        \seq_put_right:Nn \l_tmpb_seq {1}
    }
    \int_step_inline:nn {\seq_count:N \l_tmpc_seq - 1}
    {
        \tl_put_right:Nx \l_tmpa_tl {\tinybox{$ \seq_item:Nn \l_tmpc_seq {##1} = 1$} \&}
    }
    \tl_put_right:Nx \l_tmpa_tl {\tinybox{$ \seq_item:Nn \l_tmpc_seq {\seq_count:N \l_tmpc_seq} = 1$} \\}
    \int_new:N \l_tmpc_int
    \int_new:N \l_tmpd_int
    \int_set:Nn \l_tmpc_int {4}
    \int_step_inline:nnn {2} {\seq_count:N \l_tmpc_seq}
    {
        \int_set:Nn \l_tmpc_int {\l_tmpc_int * 4}
    }
    \int_log:N \l_tmpc_int
    \int_step_inline:nnn {2} {\l_tmpc_int} 
    {
        \int_set:Nn \l_tmpb_int {##1}
        \int_log:N \l_tmpb_int
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
        {
            \int_set:Nn \l_tmpa_int {\seq_item:Nn \l_tmpa_seq{####1}}
            \int_set:Nn \l_tmpd_int { \int_eval:n  {\l_tmpa_int + 1}}
            \int_log:N \l_tmpd_int
            \seq_set_item:NnV \l_tmpb_seq {####1} \l_tmpd_int 
        }
        \seq_log:N \l_tmpb_seq
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq - 1}
        {
            \tl_put_right:Nx \l_tmpa_tl {\tinybox{$ \seq_item:Nn \l_tmpc_seq {####1} = \seq_item:Nn \l_tmpb_seq{####1} $} \&}
        }
        \tl_put_right:Nx \l_tmpa_tl {\tinybox{$ \seq_item:Nn \l_tmpc_seq {\seq_count:N \l_tmpc_seq} = \seq_item:Nn \l_tmpb_seq {\seq_count:N \l_tmpb_seq}$} \\}
        \int_step_inline:nn {\seq_count:N \l_tmpc_seq}
        {
            \int_set:Nn \l_tmpa_int {\int_eval:n {\seq_item:Nn \l_tmpb_seq{####1}}}
            \int_log:N \l_tmpa_int
            \seq_set_item:NnV \l_tmpa_seq {####1} \l_tmpa_int 
        }
        \seq_log:N \l_tmpa_seq
    }
    \begin{tikzpicture}[baseline={([yshift=-0ex]current~bounding~box.center)}]
        \matrix(m) [
          matrix~of~nodes,
           ampersand~replacement=\&,
           column~sep=1ex,
           nodes~in~empty~cells,
           nodes={
             shape=rectangle,
             minimum~height=3ex,
             anchor=center
           },
         ]{
            \tl_use:N \l_tmpa_tl
         };
    \end{tikzpicture}
}

\cs_generate_variant:Nn \seq_set_item:Nnn { NnV }
\ExplSyntaxOff

\begin{document}
\[
    \indexprod{i,j}    
\]

\end{document}

在此处输入图片描述

您可能会喜欢研究下面更简单的代码。

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\NewDocumentCommand{\tinybox}{m}{\mbox{\tiny#1}}

\ExplSyntaxOn
\NewDocumentCommand{\indexprod}{ O{16} m }  % indices   
 {
  % the indices
  \seq_set_from_clist:Nn \l_tmpa_seq { #2 }
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \tinybox{$##1=\int_eval:n { \l_tmpa_int }$} }
  \tl_clear:N \l_tmpa_tl
  \int_zero:N \l_tmpa_int
  \prg_replicate:nn { #1 }
   {
    \int_incr:N \l_tmpa_int
    \tl_set:Nx \l_tmpb_tl { \seq_use:Nn \l_tmpb_seq { \& } }
    \tl_put_right:Nx \l_tmpa_tl { \l_tmpb_tl \exp_not:N \\ }
   }
  \begin{tikzpicture}[baseline={([yshift=-0ex]current~bounding~box.center)}]
    \matrix(m) [
      matrix~of~nodes,
      ampersand~replacement=\&,
      column~sep=1ex,
      nodes~in~empty~cells,
      nodes={
        shape=rectangle,
        minimum~height=3ex,
        anchor=center
      },
    ]{
      \tl_use:N \l_tmpa_tl
    };
  \end{tikzpicture}
 }

\ExplSyntaxOff

\begin{document}
\[
  \indexprod{i,j}\qquad
  \indexprod[5]{i,j,k}
\]

\end{document}

在此处输入图片描述

对上述代码的一些注释。如果我们设置它们之后,我们\seq_show:N \l_tmpa_seq得到\seq_show:N \l_tmpb_seq

The sequence \l_tmpa_seq contains the items (without outer braces):
>  {i}
>  {j}.

The sequence \l_tmpb_seq contains the items (without outer braces):
>  {\tinybox {$i=\int_eval:n {\l_tmpa_int }$}}
>  {\tinybox {$j=\int_eval:n {\l_tmpa_int }$}}.

现在添加\tl_show:N \l_tmpb_tl并在循环\tl_show:N \l_tmpa_tl中设置它们\prg_replicate:nn:在第一次迭代中我们得到

> \l_tmpb_tl=\tinybox {$i=\int_eval:n {\l_tmpa_int }$}\&\tinybox
{$j=\int_eval:n {\l_tmpa_int }$}.

> \l_tmpa_tl=\tinybox {$i=1$}\&\tinybox {$j=1$}\\.

这利用了这样一个事实:序列中的项目在\exp_not:n它们周围返回,因此\tl_set:Nx刚好到达“表面”标记列表;但在\tl_put_right:Nx项目之后完全展开。在这种情况下,我利用了 中的项目\l_tmpa_seq是“扩展安全的”。其他用例可能需要其他注意。

更安全的版本

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\NewDocumentCommand{\tinybox}{m}{\mbox{\tiny#1}}

\NewDocumentCommand{\tbinnermatrix}{m}{%
  \begin{tikzpicture}[baseline={([yshift=-0ex]current bounding box.center)}]
    \matrix(m) [
      matrix of nodes,
      ampersand replacement=\&,
      column sep=1ex,
      nodes in empty cells,
      nodes={
        shape=rectangle,
        minimum height=3ex,
        anchor=center
      },
    ]{ #1 };
  \end{tikzpicture}%
}

\ExplSyntaxOn

\NewDocumentCommand{\indexprod}{ O{16} m }  % indices   
 {
  \tedblack_indexprod:nn { #1 } { #2 }
 }

\cs_generate_variant:Nn \cs_set:Nn { NV }
\cs_set_eq:NN \tedblack_innermatrix:n \tbinnermatrix
\cs_generate_variant:Nn \tedblack_mymatrix:n { V }

\cs_new_protected:Nn \tedblack_indexprod:nn
 {
  % the indices
  \seq_set_from_clist:Nn \l_tmpa_seq { #2 }
  \seq_set_map:NNn \l_tmpa_seq \l_tmpa_seq { \tinybox{$\exp_not:n { ##1 }=####1$} }
  \tl_set:Nx \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { \& } }
  \cs_set:NV \__tedblack_temp:n \l_tmpa_tl
  \tl_clear:N \l_tmpa_tl
  \int_step_inline:nn { #1 }
   {
    \tl_put_right:Nx \l_tmpa_tl { \__tedblack_temp:n { ##1 } \exp_not:N \\ }
   }
  \tedblack_innermatrix:V \l_tmpa_tl
 }

\ExplSyntaxOff

\begin{document}
\[
  \indexprod{i,j}\qquad
  \indexprod[5]{i,j,\mathbf{k}}
\]

\end{document}

这不仅表明诸如的“危险”命令\mathbf在的参数中是安全的\indexprod,而且还表明了更好的编程风格,其中区分了用户级命令和内部函数。

“矩阵构建”命令在外部执行\ExplSyntaxOn,这在 Ti 时始终是最好的涉及 Z。稍后将定义内部版本,并有可能定义其变体。

定义了一个“本地”函数,以便可以使用它来替换循环中的当前值\int_step_inline:nn

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\NewDocumentCommand{\tinybox}{m}{\mbox{\tiny#1}}

\NewDocumentCommand{\tbinnermatrix}{m}{%
  \begin{tikzpicture}[baseline={([yshift=-0ex]current bounding box.center)}]
    \matrix(m) [
      matrix of nodes,
      ampersand replacement=\&,
      column sep=1ex,
      nodes in empty cells,
      nodes={
        shape=rectangle,
        minimum height=3ex,
        anchor=center
      },
    ]{ #1 };
  \end{tikzpicture}%
}

\ExplSyntaxOn

\NewDocumentCommand{\indexprod}{ O{16} m }  % indices   
 {
  \tedblack_indexprod:nn { #1 } { #2 }
 }

\cs_generate_variant:Nn \cs_set:Nn { NV }
\cs_set_eq:NN \tedblack_innermatrix:n \tbinnermatrix
\cs_generate_variant:Nn \tedblack_innermatrix:n { V }

\cs_new_protected:Nn \tedblack_indexprod:nn
 {
  % the indices
  \seq_set_from_clist:Nn \l_tmpa_seq { #2 }
  \seq_set_map:NNn \l_tmpa_seq \l_tmpa_seq { \tinybox{$\exp_not:n { ##1 }=####1$} }
  \tl_set:Nx \l_tmpa_tl { \seq_use:Nn \l_tmpa_seq { \& } }
  \cs_set:NV \__tedblack_temp:n \l_tmpa_tl
  \tl_clear:N \l_tmpa_tl
  \int_step_inline:nn { #1 }
   {
    \tl_put_right:Nx \l_tmpa_tl { \__tedblack_temp:n { ##1 } \exp_not:N \\ }
   }
  \tedblack_innermatrix:V \l_tmpa_tl
 }

\ExplSyntaxOff

\begin{document}
\[
  \indexprod{i,j}\qquad
  \indexprod[5]{i,j,\mathbf{k}}
\]

\end{document}

在此处输入图片描述

答案2

我知道这是 LaTeX3 中的一项练习,但我想提供我的 PGFKeys 版本。

值键也只存储我们可以修改的标记(其中包括

  • \pgfkeyssetvalue{/key}{<value>}
  • \pgfkeysaddvalue{/key}{<prefix>}{<suffix>}

或其处理程序替代方案(其中包括

  • /key/.initial=<value>(或者/key=<value>如果/key之前已经初始化)
  • /key/.add={<prefix>}{<suffix>}
  • /key/.prefix=<prefix>
  • /key/.append=<suffix>

可以通过处理程序实现未分组的 PGFFor 循环,.list从而允许我们重复使用一个键。

通过嵌套.list应用程序,可以构建一个矩阵。我们只需确保将一个\pgfmatrixnextcell(所有元素的&/ )放入比列数少的元素中。这是通过不将其放入行的第一个单元格来实现的。这就是为什么在其自己的定义中重新定义的\&原因。/tikz/matrix/create cell

我选择anchor = base矩阵内的节点,使它们的基线对齐。矩阵本身固定在其中心,这意味着它的中心将位于= 0pt 这是为 选择的值baseline


除了使用i, j, \mathbf{k}列表之外,您还可以使用

\indexprod[
  indexprod/rows=5,
  column 3/.style={set matrix macro={$\mathbf{##2}=##1$}}
]{i, j, k}

达到同样的效果。当然,你可以使用另一个不那么冗长的顶级接口。

代码

\documentclass{article}
\usepackage{tikz}
\tikzset{
  matrix node/.style 2 args={
    name=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn},
  set matrix macro/.code=
    \protected\def\tikzmatrixcell##1##2{\node[matrix node={##1}{##2}]{#1};},
  set matrix macro'/.code=\protected\def\tikzmatrixcell##1##2{#1},
  create matrix/.code 2 args=% quicker https://tex.stackexchange.com/a/692610
    \pgfkeyssetvalue{/tikz/matrix/content}{}%
    \pgfkeysdef{/tikz/matrix/create rows}{%
      \pgfkeysvalueof{/tikz/matrix/reset create cell/.@cmd}\pgfeov
      \pgfkeysdef{/tikz/matrix/create columns}{%
        \pgfkeysvalueof{/tikz/matrix/create cell/.@cmd}{##1}{####1}\pgfeov}%
      \tikzset{matrix/create columns/.list={#2}}%
      \pgfkeysaddvalue{/tikz/matrix/content}{}{\pgfmatrixendrow}}%
    \tikzset{matrix/create rows/.list={#1},
      node contents=\pgfkeysvalueof{/tikz/matrix/content}},
  matrix/reset create cell/.code=
    \pgfkeysdefargs{/tikz/matrix/create cell}{##1##2}{%
      \pgfkeysaddvalue{/tikz/matrix/content}{}{\tikzmatrixcell{##1}{##2}}%
      \pgfkeysdefargs{/tikz/matrix/create cell}{####1####2}{%
        \pgfkeysaddvalue{/tikz/matrix/content}{}{%
          \pgfmatrixnextcell\tikzmatrixcell{####1}{####2}}}}}

\tikzset{
  indexprod/rows/.initial=16,
  indexprod/list/.initial={1, ..., \pgfkeysvalueof{/tikz/indexprod/rows}},
  every indexprod diagram/.style={
    baseline=+0pt, column sep=1ex, set matrix macro={$##2 = ##1$},
    every outer matrix/.style={shape=rectangle, inner sep=+0pt, outer sep=+0pt},
    every matrix/.style={
      anchor=center, nodes={shape=rectangle, anchor=base, minimum height=3ex}}}}
\NewDocumentCommand{\indexprod}{O{} m}{%
  \tikz[every indexprod diagram,#1]
    \matrix[create matrix/.expanded=
      {\pgfkeysvalueof{/tikz/indexprod/list}}{\unexpanded{#2}}];}
\begin{document}
\indexprod{i, j}
\quad
\indexprod[indexprod/rows=5]{i, j, \mathbf{k}}
\end{document}

输出

在此处输入图片描述

相关内容