我需要将一个定义为 clist 的向量传递给一个函数,该函数将其解析为多个后续计算的组件。如果将向量 clist 作为参数直接传递给解析器,解析器似乎可以完美运行,但当将其定义为命令(例如)时则不行\vectora
。
从长远来看,我想在中进行向量计算,LaTeX3
但首先,我需要一种将向量定义为命令的方法,其组件表示为 clist。我设想了类似的东西,\DefineVector[b]{1,2,3}
其中[b]
是具有默认值的可选标签a
,{1,2,3}
是包含向量数值组件的 clist。标签可以简单到一个字母,也可以是类似的东西vectorb
。得到的向量,例如,在传递给解析器时\vectora
,将扩展为例如{1,2,3}
。解析器将是一个编程层函数,用户实际上不会与之交互,但会用于执行实际向量计算(如幅度、点积或交叉积)的其他函数。解析器将获取向量分量,例如,并将{1,2,3}
它们逐一分配给变量,如vectorax
和vectoray
和vectoraz
,然后随后用于浮点计算。在这个例子中,\vectorax
将扩展为1
,\vectoray
将扩展为2
,并将\vectoraz
扩展为3
。所以如果我要定义一个新函数来计算,比如说,交叉积,我会解析两个向量,vectora
和vectorb
,并最终得到两组组件,我可以用它们来计算交叉积。我遇到的问题是创建一个正确传递给解析器的向量。
在下面的代码中,这是我花了至少两三个小时修改的结果,\ParseVector
当我传递带有向量组件的 clist 时,命令可以工作,但当我传递我认为是作为另一个命令的一部分定义的 clist 时,命令不起作用。这是我需要解决的直接问题,而且我显然遗漏了一些重要概念。我在做这件事的同时,也试图遵守LaTeX3
编码标准。
\documentclass[10pt]{article}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \joe_parsevector:n {%
% Create sets temporary clist to #1
\clist_set:Nn \l_tmpa_clist { #1 }
% Applies { ... } to each element in the temporary clist.
%\clist_map_inline:Nn \l_tmpa_clist { [##1] }
\begin{enumerate}
\clist_map_inline:Nn \l_tmpa_clist { \item ##1 }
\end{enumerate}
}%
\NewDocumentCommand{\ParseVector}{ m }{%
\joe_parsevector:n { #1 }
}%
\NewDocumentCommand{\DefineVector}{ m m }{%
[#1][#2]
%\exp_args:Nc \newcommand{#1}[1]{#2}
\cs_new:cpn {#1} ##1 { #2 }
}%
\ExplSyntaxOff
\begin{document}
Hello.
Parsing the vector \verb!{5,-3,4}! gives \ParseVector{5,-3,4}
\DefineVector{vectora}{3,-5,7}
\vectora
\end{document}
答案1
如果我理解正确的话,您想用符号名称存储向量并使用它们执行操作。
我将展示如何定义存储函数(在序列中,而不是在列表中)和一些运算:幅度、标量积、向量(交叉)积。
符号名称可以是任意字母和数字的序列。
前两个是可扩展的,最后一个则不可扩展,因为我们需要存储结果。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DefineVector}{O{a}m}
{
\joe_vector_define:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\PrintVector}{m}
{
(\seq_use:cn { l_joe_vector_#1_seq } { , })
}
\NewExpandableDocumentCommand{\VectorMagnitude}{O{15}m}
{
\joe_vector_magnitude:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\ScalarProduct}{O{15}mm}
{
\joe_vector_scalarproduct:nnn { #1 } { #2 } { #3 }
}
\NewDocumentCommand{\VectorProduct}{mmm}
{% #1 = first vector, #2 = second vector, #3 = result
\joe_vector_vectorproduct:nnn { #1 } { #2 } { #3 }
}
\cs_new_protected:Nn \joe_vector_define:nn
{
\seq_clear_new:c { l_joe_vector_#1_seq }
\seq_set_from_clist:cn { l_joe_vector_#1_seq } { #2 }
}
\cs_new:Nn \joe_vector_magnitude:nn
{
\fp_eval:n
{
round
(
sqrt( \seq_map_function:cN { l_joe_vector_#2_seq } \__joe_vector_square:n )
,
#1
)
}
}
\cs_new:Nn \__joe_vector_square:n { + (#1)^2 }
\cs_new:Nn \joe_vector_scalarproduct:nnn
{
\fp_eval:n
{
round
(
\seq_mapthread_function:ccN { l_joe_vector_#2_seq } { l_joe_vector_#3_seq } \__joe_vector_product:nn
,
#1
)
}
}
\cs_new:Nn \__joe_vector_product:nn
{
+(#1)*(#2)
}
\cs_new_protected:Nn \joe_vector_vectorproduct:nnn
{
\seq_clear_new:c { l_joe_vector_#3_seq }
\seq_put_right:cx { l_joe_vector_#3_seq }
{
\fp_eval:n
{
(\seq_item:cn { l_joe_vector_#1_seq } { 2 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 3 })
-
(\seq_item:cn { l_joe_vector_#1_seq } { 3 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 2 })
}
}
\seq_put_right:cx { l_joe_vector_#3_seq }
{
\fp_eval:n
{
(\seq_item:cn { l_joe_vector_#1_seq } { 3 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 1 })
-
(\seq_item:cn { l_joe_vector_#1_seq } { 1 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 3 })
}
}
\seq_put_right:cx { l_joe_vector_#3_seq }
{
\fp_eval:n
{
(\seq_item:cn { l_joe_vector_#1_seq } { 1 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 2 })
-
(\seq_item:cn { l_joe_vector_#1_seq } { 2 }) * (\seq_item:cn { l_joe_vector_#2_seq } { 1 })
}
}
}
\ExplSyntaxOff
\begin{document}
\DefineVector[a]{0,-4,0}
\DefineVector[b]{1,1,1}
\DefineVector[x4]{1,2,3,4}
\DefineVector[y4]{-1,1,0,2}
$\VectorMagnitude{a}$
$\VectorMagnitude{b}$
$\VectorMagnitude[2]{b}$
$\ScalarProduct{a}{b}$
$\ScalarProduct{x4}{y4}$
\VectorProduct{a}{b}{c}
$\PrintVector{c}$
\end{document}
叉积的实现比较困难,因为它实际上并不是向量运算。