以下是我处理宏的无限数量参数的方法。有没有更好的方法?
\documentclass[12pt,a4paper]{article}
\usepackage{ifmtarg}
\usepackage{nicematrix}
\makeatletter
\def\backify#1|#2\@nil{%
\@ifmtarg{#2}{%
#1%
}{%
#1 \\ \backify#2\@nil%
}%
}
\newcommand\vcoord[1]{%
\begin{pmatrix}
\backify#1|\@nil %
\end{pmatrix}%
}
\makeatother
\begin{document}
$\vcoord{3 | -4 | 0}$
\end{document}
答案1
我建议用不同的方法来应对你正在做的事情。
\documentclass[12pt,a4paper]{article}
\usepackage{xparse}
\usepackage{amsmath}
\ExplSyntaxOn
% a general purpose macro for defining other macros
\NewDocumentCommand{\makemultiargument}{mmmmm}
{
\projetmbc_multiarg:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 }
}
% allocate a private variable
\seq_new:N \l__projetmbc_generic_seq
% the internal version of the general purpose macro
\cs_new_protected:Nn \projetmbc_multiarg:nnnnn
{% #1 = separator
% #2 = multiargument
% #3 = code before
% #4 = code between
% #5 = code after
% a group allows nesting
\group_begin:
% split the multiargument into parts
\seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
% execute the <code before>
#3
% deliver the items, with the chosen material between them
\seq_use:Nn \l__projetmbc_generic_seq { #4 }
% execute the <code after>
#5
% end the group started at the beginning
\group_end:
}
\ExplSyntaxOff
% separator: |; before: \begin{pmatrix}; between: \\, after: \end{pmatrix}
\newcommand{\vcoord}[1]{%
\makemultiargument{|}{#1}{\begin{pmatrix}}{\\}{\end{pmatrix}}%
}
\begin{document}
$\vcoord{3 | \vcoord{-4 | -3 } | 0}$
\end{document}
可以为每个条目添加格式,并带有尾随可选参数(如果没有它,宏与以前的版本相同)。
\documentclass[12pt,a4paper]{article}
\usepackage{xparse}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\makemultiargument}{mmmmmo}
{
\projetmbc_multiarg:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
}
\seq_new:N \l__projetmbc_generic_seq
\cs_new_protected:Nn \projetmbc_multiarg:nnnnnn
{% #1 = separator
% #2 = multiargument
% #3 = code before
% #4 = code between
% #5 = code after
% #6 = ornament to items
% allow nesting
\group_begin:
% split the multiargument
\seq_set_split:Nnn \l__projetmbc_generic_seq { #1 } { #2 }
\tl_if_novalue:nF { #6 }
{
\seq_set_eq:NN \l__projetmbc_temp_seq \l__projetmbc_generic_seq
\seq_set_map:NNn \l__projetmbc_generic_seq \l__projetmbc_generic_seq { #6 }
}
#3
\seq_use:Nn \l__projetmbc_generic_seq { #4 }
#5
\group_end:
}
\ExplSyntaxOff
\NewDocumentCommand{\vcoord}{m}
{
\makemultiargument{|}{#1}{\begin{pmatrix}}{\\}{\end{pmatrix}}
}
\NewDocumentCommand{\pboxed}{m}{\boxed{#1}}
\begin{document}
$\vcoord{3 | \vcoord{-4 | -3 } | 0}$
$\makemultiargument{|}{-4 | -3 | 0}{\begin{pmatrix}}{\\}{\end{pmatrix}}[\pboxed{#1}]$
\end{document}
请注意,尾随参数中的宏必须是完全可扩展的或受保护的(这就是我定义的原因\pboxed
;标准\boxed
不会失败,但只是偶然)。
答案2
使用expl3
(由 加载xparse
)您可以使用内置序列类型。以下\vcoord
仅使用内置函数定义您的序列类型。结果不可扩展。它还添加了两个宏,\readsequence
一个设置序列变量(不可扩展),\usesequence
另一个扩展为序列,每个序列元素由其参数分隔(可扩展)。您可以查看interface3
用于 中可用功能的文档expl3
。
\documentclass[]{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l__projetmbc_seq
\NewDocumentCommand \readsequence { +m +m }
{
\seq_set_split:Nnn \l__projetmbc_seq { #1 } { #2 }
}
\NewExpandableDocumentCommand \usesequence { +m }
{
\seq_use:Nnnn \l__projetmbc_seq { #1 } { #1 } { #1 }
}
\NewDocumentCommand \vcoord { m }
{
\group_begin:
\seq_set_split:Nnn \l__projetmbc_seq { | } { #1 }
\begin { pmatrix }
\seq_use:Nnnn \l__projetmbc_seq { \\ } { \\ } { \\ }
\end { pmatrix }
\group_end:
}
\ExplSyntaxOff
\begin{document}
\readsequence{|}{a|b|c|d|e}
\[
\begin{pmatrix}
\usesequence{\\}
\end{pmatrix}
\]
\[
\vcoord{3|-4|0}
\]
\end{document}
答案3
不确定最佳实践,但你可以稍微简化定义:
\documentclass[12pt,a4paper]{article}
\usepackage{amsmath}
\long\def\backify#1|{#1\backify\\}
\def\endbackify#1#2{}
\newcommand\vcoord[1]{%
\begin{pmatrix}
\backify#1|\endbackify|%
\end{pmatrix}%
}
\begin{document}
$\vcoord{3 | -4 | 0}$
\end{document}