动机
我想要一个\pythagoras
命令,它接受一个表达式列表,以及第二个可选的括号形状列表,并返回一个勾股表达式。
期望结果
例如,
\pythagoras{a,b,c}
应该返回相当于
\sqrt{a^2+b^2+c^2}
尽管
\pythagoras{a,\frac{b}{2},c}[.,r,.]
应该返回相当于
\sqrt{a^2+\left(\frac{b}{2}\right)^2+c^2}
当前代码
\documentclass{article}
\usepackage{xparse,amsmath}
\ExplSyntaxOn
% count list
\NewDocumentCommand{\countlist}{m}{
\clist_count:n { #1 }
}
% repeat command
\cs_new_eq:NN \Repeat \prg_replicate:nn
% brackets; my notation of r for round, s for square, c for curly
\NewDocumentCommand{\br}{O{r} O{#1} m}{
\left
\str_case:nnF { #1 } { {r}{(} {s}{[} {c}{\{} {v}{|} {V}{\|} {.}{.} } {.}
#3
\right
\str_case:nnF { #2 } { {r}{)} {s}{]} {c}{\}} {v}{|} {V}{\|} {.}{.} } {.}
}
% pythagoras
\NewDocumentCommand{\pythagoras}{m O{.\Repeat{\countlist{#1}-1}{,.}}}{
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_set_from_clist:Nn \l_tmpb_seq {#2}
\cs_set:Npn \__mapper ##1##2 {\__sep \tl_if_empty:nTF { ##2 }{##1}{\br[##2]{##1}}^2}
\cs_set:Npn \__sep {\cs_set:Npn \__sep {+}}
\seq_mapthread_function:NNN \l_tmpa_seq \l_tmpb_seq \__mapper
}
\ExplSyntaxOff
问题
\Repeat
我当前尝试使用可选参数创建括号形状的默认列表,但\pythagoras
似乎不起作用。
\begin{document}
\begin{align*}
& \pythagoras{x,y}[.,.] \\ % pass the bracket parameters explicitly; works as desired
& .\Repeat{\countlist{x,y}-1}{,.} \\ % the expression used in the definition; in the document, it works as desired
& \pythagoras{x,y} % rely on the \Repeat command in the optional argument in the definition;
% should return x^2+y^2;
% actually returns x^2
\end{align*}
\end{document}
我也不确定如何将总和包装在 中\sqrt
。包装命令的相关行\pythagoras
会返回错误。
致谢
答案1
这更简单。;-)
作为围栏的说明符,我使用以下amsmath
约定:
p
对于(圆)括号b
方括号B
用于牙套v
表示垂直线(绝对值)V
对于双垂直线(标准)
您可以添加到列表或修改它,但我不建议使用可能造成混淆的不同缩写。
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\pythagoras}{mo}
{
\IfNoValueTF{#2}
{
\sqrt { \mjc_pythagoras:n { #1 } }
}
{
\sqrt{ \mjc_pythagoras:nn { #1 } { #2 } }
}
}
\bool_new:N \l__mjc_pythagoras_delims_bool
\seq_new:N \l__mjc_pythagoras_items_seq
\seq_new:N \l__mjc_pythagoras_delims_seq
\seq_new:N \l__mjc_pythagoras_output_seq
\cs_new_protected:Nn \mjc_pythagoras:n
{% no optional argument
\seq_set_split:Nnn \l__mjc_pythagoras_items_seq { , } { #1 }
\bool_set_false:N \l__mjc_pythagoras_delims_bool
\__mjc_pythagoras:
}
\cs_new_protected:Nn \mjc_pythagoras:nn
{
\seq_set_split:Nnn \l__mjc_pythagoras_items_seq { , } { #1 }
\seq_set_split:Nnn \l__mjc_pythagoras_delims_seq { , } { #2 }
\bool_set_true:N \l__mjc_pythagoras_delims_bool
\__mjc_pythagoras:
}
\cs_new_protected:Nn \__mjc_pythagoras:
{
\seq_clear:N \l__mjc_pythagoras_output_seq
\seq_map_indexed_inline:Nn \l__mjc_pythagoras_items_seq
{
\seq_put_right:Nx \l__mjc_pythagoras_output_seq
{
\bool_if:NTF \l__mjc_pythagoras_delims_bool
{ \__mjc_pythagoras_left:n { ##1 } ##2 \__mjc_pythagoras_right:n { ##1 } }
{ ##2 }
^{2}
}
}
\seq_use:Nn \l__mjc_pythagoras_output_seq { + }
}
\cs_new:Nn \__mjc_pythagoras_left:n
{
\str_case_e:nn { \seq_item:Nn \l__mjc_pythagoras_delims_seq { #1 } }
{
{p}{\left(}
{b}{\left[}
{B}{\left\{}
{v}{\left|}
{V}{\left\|}
}
}
\cs_new:Nn \__mjc_pythagoras_right:n
{
\str_case_e:nn { \seq_item:Nn \l__mjc_pythagoras_delims_seq { #1 } }
{
{p}{\right)}
{b}{\right]}
{B}{\right\}}
{v}{\right|}
{V}{\right\|}
}
}
\ExplSyntaxOff
\begin{document}
\begin{gather*}
\pythagoras{a} \\
\pythagoras{a,b} \\
\pythagoras{a,b,c} \\
\pythagoras{a,\frac{1}{2},c}[.,p,.]
\end{gather*}
\end{document}
答案2
以下使用两种不同的输出例程,具体取决于是否使用可选参数。在两种情况下,它都使用该\clist_use:Nn
函数。
\documentclass[]{article}
\ExplSyntaxOn
\clist_new:N \l_mjc_pythagoras_elements_clist
\clist_new:N \l_mjc_pythagoras_brackets_clist
\tl_new:N \l_mjc_pythagoras_element_tl
\msg_new:nnn { mjc-pythagoras } { unmatched-braces }
{
The~ bracket~ specification~ and~ the~ number~ of~ elements~ don't~ match.\\
Elements:~ #1\\
Brackets:~ #2
}
\NewDocumentCommand \pythagoras { m o }
{
\sqrt
{
\group_begin:
\clist_set:Nn \l_mjc_pythagoras_elements_clist {#1}
\IfNoValueTF {#2}
{
\clist_use:Nn \l_mjc_pythagoras_elements_clist { \sp{2} + }
\sp{2}
}
{
\clist_set:Nn \l_mjc_pythagoras_brackets_clist {#2}
\int_compare:nNnTF
{ \clist_count:N \l_mjc_pythagoras_elements_clist }
=
{ \clist_count:N \l_mjc_pythagoras_brackets_clist }
{
\__mjc_delimiter_left:
\clist_use:Nn \l_mjc_pythagoras_elements_clist
{
\__mjc_delimiter_right:
+
\__mjc_delimiter_left:
}
\__mjc_delimiter_right:
}
{
\msg_error:nnxx { mjc-pythagoras } { unmatched-braces }
{ \clist_count:N \l_mjc_pythagoras_elements_clist }
{ \clist_count:N \l_mjc_pythagoras_brackets_clist }
}
}
\group_end:
}
}
\cs_new_protected:Npn \__mjc_delimiter_left:
{
\clist_pop:NN \l_mjc_pythagoras_brackets_clist \l_mjc_pythagoras_bracket_tl
\str_case_e:nn \l_mjc_pythagoras_bracket_tl
{
{ r } { \left( }
{ s } { \left[ }
{ c } { \left\{ }
{ v } { \left| }
{ V } { \left\| }
}
}
\cs_new_protected:Npn \__mjc_delimiter_right:
{
\str_case_e:nn \l_mjc_pythagoras_bracket_tl
{
{ r } { \right) }
{ s } { \right] }
{ c } { \right\} }
{ v } { \right| }
{ V } { \right\| }
}
\sp {2}
}
\ExplSyntaxOff
\begin{document}
$\pythagoras{a,b,c}$
$\pythagoras{a,b,c}[.,r,.]$
$\pythagoras{a,b,c}[.,r]$ % throws an error
\end{document}