附录

附录

我想编写一个\TransTM扩展命令,例如,扩展\TransTM{a, x, R | b, y, L}\shortstack{a;~x,~R \\ b;~y,~L}

数学家协会

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \TransTM { m  }
  { \edge_label:cn {edge_item_tm:nnn} {#1} }

\cs_new_protected:Npn \edge_label:cn #1 #2
{
  \seq_set_split:Nnn \l_tmpa_seq { | } { #2 } 
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \edge_item:cn {#1} {##1} }
  \shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}

\cs_new_protected:Npn \edge_item:cn #1 #2
{
  \seq_set_split:Nnn \l_tmpa_seq { , } { #2 }
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { {##1} }
  \use:c { #1 } x x x % \seq_use:Nn \l_tmpb_seq { }
}

\cs_new_protected:Npn \edge_item_tm:nnn #1 #2 #3
{
  #1;~#2,~#3
}

\ExplSyntaxOff

\begin{document}

\TransTM{a, x, L | b, y, R}

\end{document}

|仅部分起作用,因为我已设法在第一级上拆分参数,但没有在,第二级上拆分参数。\seq_use:Nn\edge_item:cn注释掉并由硬编码替换,x x x因为它会产生错误。

试图在第二个层次上分裂论点有什么错误?

注意:将来会有不同的变体。这就是我将函数名称edge_item_tm:nnn作为参数传递的原因。\TransFA{a | b | c}例如,另一个文档级命令应该扩展为\shortstack{a \\ b \\ c}。区别仅在于标记之间部分的结构|

附录

似乎我过于简化了上述 MWE。以下代码

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{relsize}

\ExplSyntaxOn

\NewDocumentCommand \Char { O{\width} m } 
{
  \makebox[#1] 
  {
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      {              } { $\varepsilon$           }
      { ##           } { \texttt{\#}             }
      { \c_tilde_str } { \textscale{.87}{$\Box$} }
    }
    { \texttt{#2} }
  }
}

\NewDocumentCommand \TransTM { m }
  { \__edge_label_tm:n {#1} }

\cs_new_protected:Npn \__edge_label_tm:n #1 
{
  \seq_set_split:Nnn \l_tmpa_seq { | } { #1 } 
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \SplitItemTM \exp_not:n { {##1} } }
  \shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}

\NewDocumentCommand \SplitItemTM { >{\SplitArgument{2}{,}} m }
  { \__edge_item_tm:nnn #1 }

\cs_new_protected:Npn \__edge_item_tm:nnn #1 #2 #3 
{
  \Char[.63em]{#1};\;\Char[.63em]{#2},\,\Char{#3}
}

\ExplSyntaxOff

\begin{document}

\TransTM{a, x, L} \qquad
\TransTM{a, x, L | b, y, L} \qquad
\TransTM{a, x, L | b, y, L | ~, ~, R}

\end{document}

产生期望的结果。

期望结果

但是,它滥用了它,\NewDocumentCommand因为\SplitItemTM它属于实现,而不是用户界面。\SplitItemTM用内部函数替换的正确方法是什么?

答案1

首先:您不应该使用\cs_new_protected:Npn具有签名的函数进行定义:cn

我认为您的输入是这种形式\TransTM{a, x, R | b, y, L | c, m, n, p},并且您想要隔离每个|分隔部分中的第一个项目,以便在其后使用分号。

首先将参数拆分为|,并执行映射,在每个项周围添加辅助函数。此辅助宏将在\shortstack打印 中的行时起作用:隔离第一个项,打印后跟分号和空格,然后传递其余的序列项,并用逗号和空格分隔。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\TransTM}{m}
 {
  \matthias_edge_label:n { #1 }
 }

\seq_new:N \l__matthias_edge_labels_in_seq
\seq_new:N \l__matthias_edge_labels_out_seq
\seq_new:N \l__matthias_edge_label_seq
\tl_new:N \l__matthias_edge_label_head_tl

\cs_new_protected:Nn \matthias_edge_label:n
 {
  % first let's split at |
  \seq_set_split:Nnn \l__matthias_edge_labels_in_seq { | } { #1 }
  % populate the sequence for output
  \seq_set_map:NNn
   \l__matthias_edge_labels_out_seq
   \l__matthias_edge_labels_in_seq
   { \__matthias_edge_label:n { \exp_not:n { ##1 } } }
  % deliver it
  \shortstack{ \seq_use:Nn \l__matthias_edge_labels_out_seq { \\ } }
 }

\cs_new_protected:Nn \__matthias_edge_label:n
 {
  % split the argument at commas
  \seq_set_split:Nnn \l__matthias_edge_label_seq { , } { #1 }
  % remove the first item
  \seq_pop_left:NN \l__matthias_edge_label_seq \l__matthias_edge_label_head_tl
  \tl_use:N \l__matthias_edge_label_head_tl
  ;~
  \seq_use:Nn \l__matthias_edge_label_seq { ,~ }
 }
\ExplSyntaxOff

\begin{document}

\TransTM{a, x, L | b, y, R}
\qquad 
\TransTM{a, x, R | b, y, L | c, m, n, p}

\end{document}

在此处输入图片描述

现在,让我们看看你的方法出了什么问题。当你这样做时

\TransTM{a, x, L | b, y, R}

序列\l_tmpb_seq将包含以下项目

{\edge_item:cn {edge_item_tm:nnn} {a, x, L}}
{\edge_item:cn {edge_item_tm:nnn} {b, y, R}}

(为了清晰起见,用了外括号,但实际上没有)。当序列传递时,你会得到

\shortstack{%
  \edge_item:cn {edge_item_tm:nnn} {a, x, L}\\%
  \edge_item:cn {edge_item_tm:nnn} {b, y, R}%
}

(为了便于阅读,我们分行了)。现在,您的想法是将第二个参数中的项目用逗号分开,然后应用一个三参数函数。但是如果您这样做

\use:c{edge_item_tm:nnn} \seq_use:Nn \l_tmpb_seq { }

的第一个参数\edge_item_tm:nnn将是\seq_use:Nn,因为它尚未扩展。

虽然可以这样做,但我不推荐这种方法。无论如何,这些c论点都不合适。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \TransTM { m  }
  { \edge_label:Nn \edge_item_tm:nnn {#1} }

\cs_new_protected:Npn \edge_label:Nn #1 #2
{
  \seq_set_split:Nnn \l_tmpa_seq { | } { #2 } 
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \edge_item:Nn #1 {##1} }
  \shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}

\cs_new_protected:Npn \edge_item:Nn #1 #2
{
  \seq_set_split:Nnn \l_tmpa_seq { , } { #2 }
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { {##1} }
  \exp_last_unbraced:Nf #1 \seq_use:Nn \l_tmpb_seq { }
}

\cs_new_protected:Npn \edge_item_tm:nnn #1 #2 #3
{
  #1;~#2,~#3
}

\ExplSyntaxOff

\begin{document}

\TransTM{a, x, L | b, y, R}

\end{document}

附录

您认为那\SplitItemTM不属于那里,这是对的。

\documentclass{article}
\usepackage{xparse}
\usepackage{graphicx,amssymb}

\ExplSyntaxOn

\NewDocumentCommand \Char { O{\width} m } 
 {
  \makebox[#1]{ \edge_char:n { #2 } }
 }

\NewDocumentCommand \TransTM { m }
 {
  \edge_label:n {#1}
 }

\seq_new:N \l__edge_labels_in_seq
\seq_new:N \l__edge_labels_out_seq

\cs_new_protected:Nn \edge_char:n
 {
  \str_case_x:nnF { \tl_to_str:n {#1} }
   {
    {              } { $\varepsilon$           }
    { ##           } { \texttt{\#}             }
    { \c_tilde_str } { \scalebox{.87}{$\Box$}  }
   }
  { \texttt{#1} }
 }
\cs_generate_variant:Nn \edge_char:n { f }

\cs_new_protected:Nn \edge_label:n
 {
  \group_begin:
  % this because otherwise boxes would not print
  \char_set_active_eq:nN { `\~ } \c_tilde_str

  \seq_set_split:Nnn \l__edge_labels_in_seq { | } { #1 }
  \seq_set_map:NNn
   \l__edge_labels_out_seq
   \l__edge_labels_in_seq
   { \edge_item:n { \exp_not:n { ##1 } } }
  \shortstack
   {
    \seq_use:Nn \l__edge_labels_out_seq { \\ }
   }
  \group_end:
 }

\cs_new_protected:Nn \edge_item:n
 {
  \edge_char:f { \clist_item:nn { #1 } {1} } ; ~
  \edge_char:f { \clist_item:nn { #1 } {2} } , ~
  \edge_char:f { \clist_item:nn { #1 } {3} }
}

\ExplSyntaxOff

\begin{document}

\TransTM{a, x, L} \qquad
\TransTM{a, , L | b, #, L} \qquad
\TransTM{a, x, L | b, y, L | ~, ~, R}

\end{document}

在此处输入图片描述

答案2

L3 版本的替代版本listofitems。已编辑以消除对参数可扩展性的需要,这通过\ddag在参数中使用不可扩展性来证明。

\documentclass{article}
\usepackage{listofitems}
\newcommand{\addtotoks}[2]{#1\expandafter{\the#1#2}}
\newcommand{\xxaddtotoks}[2]{\expandafter\expandafter\expandafter\addtotoks%
  \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{#2}}
\newtoks\zztoks
\newcommand\TransTM[1]{%
  \setsepchar{{|}/,}%
  \readlist*\zz{#1}%
  \zztoks{}%
  \foreachitem\x\in\zz[]{%
   \if\xcnt=1\else\addtotoks\zztoks{\\}\fi
   \xxaddtotoks\zztoks{\zz[\xcnt,1];~}%
   \xxaddtotoks\zztoks{\zz[\xcnt,2],~}%
   \xxaddtotoks\zztoks{\zz[\xcnt,3]}%
  }%
  \expandafter\shortstack\expandafter{\the\zztoks}%
}
\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | c, y, \ddag}
\end{document}

或者如果不喜欢标记列表,则使用\defs (通过\g@addto@macro):

\documentclass{article}
\usepackage{listofitems}
\makeatletter
\newcommand\TransTM[1]{%
  \setsepchar{{|}/,}%
  \readlist*\zz{#1}%
  \def\zzz{}%
  \foreachitem\x\in\zz[]{%
   \if\xcnt=1\else\g@addto@macro\zzz{\\}\fi
   \addzzz{\zz[\xcnt,1];~}%
   \addzzz{\zz[\xcnt,2],~}%
   \addzzz{\zz[\xcnt,3]}%
  }%
  \expandafter\shortstack\expandafter{\zzz}%
}
\newcommand\addzzz[1]{\expandafter\expandafter\expandafter\g@addto@macro%
  \expandafter\expandafter\expandafter\zzz\expandafter\expandafter\expandafter{#1}}
\makeatother
\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | c, y, \ddag}
\end{document}

在此处输入图片描述


\Char显示可以与此方法一起使用的版本:

\documentclass{article}
\usepackage{listofitems,xparse,relsize,amssymb}
\newcommand{\addtotoks}[2]{#1\expandafter{\the#1#2}}
\newcommand{\xxaddtotoks}[2]{\expandafter\expandafter\expandafter\addtotoks%
  \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{#2}}
\def\ZZ{\Char[.5em]{~}}%
\newtoks\zztoks
\newcommand\TransTM[1]{%
  \setsepchar{{|}/,}%
  \readlist*\zz{#1}%
  \zztoks{}%
  \foreachitem\x\in\zz[]{%
   \if\xcnt=1\else\addtotoks\zztoks{\\}\fi
   \xxaddtotoks\zztoks{\zz[\xcnt,1];~}%
   \xxaddtotoks\zztoks{\zz[\xcnt,2],~}%
   \xxaddtotoks\zztoks{\zz[\xcnt,3]}%
  }%
  \texttt{\expandafter\shortstack\expandafter{\the\zztoks}}%
}
\ExplSyntaxOn

\NewDocumentCommand \Char { O{\width} m } 
{
  \makebox[#1] 
  {
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      {              } { $\varepsilon$           }
      { ##           } { \texttt{\#}             }
      { \c_tilde_str } { \textscale{.87}{$\Box$} }
    }
    { \texttt{#2} }
  }
}

\ExplSyntaxOff

\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | \ZZ, y, \ddag}
\end{document}

在此处输入图片描述

相关内容