使用 LaTeX3 的灵活衍生宏

使用 LaTeX3 的灵活衍生宏

在一个早期帖子我问了一个关于编写灵活的导数宏的问题,有人建议 LaTeX3 版本可能更容易理解,所以我决定尝试编写一个。不幸的是,我遇到了一些问题。首先,我在开始实现对数值导数阶数求和的功能时遇到了麻烦。特别是,当我尝试将命令添加\@tempcnta\z@到宏的清理部分时,我遇到了错误。由于我对 LaTeX 的了解极其有限,我不知道另一种方法来对数值导数阶数求和。我还尝试将命令包装在\ExplSyntaxOffand中\ExplSyntaxOn,但这没有帮助。其次,该命令有时需要比我想要的更多的括号。我认为下面注释的示例是一种合理的用法。但是,实现不支持这一点,并且需要一组额外的括号(如注释示例正下方所示)。我认为基本功能已经存在(我将主要使用第一个示例中所示的命令),但如果能获得额外的功能(对数值导数阶数求和并消除对额外括号的需求),那就太好了。

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
    % allocate variables to typeset the derivative
    \tl_new:N \l_myderivative_num_exp_tl
    \tl_new:N \l_myderivative_den_tl
    \tl_new:N \l_myderivative_den_factor_var_flag_tl
    \tl_new:N \l_myderivative_den_factor_exp_tl

    % function to write the derivative
    \NewDocumentCommand{\derivative}{m>{\SplitList,}m}
    {
        % clear any old values
        \tl_clear:N \l_myderivative_num_exp_tl
        \tl_clear:N \l_myderivative_num_exp_flag_tl
        \tl_clear:N \l_myderivative_den_tl
        \tl_clear:N \l_myderivative_den_factor_var_flag_tl
        \tl_clear:N \l_myderivative_den_factor_exp_flag_tl

        % format the denominator
        \tl_map_inline:nn { #2 }
        {
            \myderivative_add_den_factor:n { ##1 }
        }

        % write the derivative
        \frac
        {
            \partial
            \tl_if_empty:NF \l_myderivative_num_exp_flag_tl
            {
                ^{\l_myderivative_num_exp_tl}
            }
            #1
        }
        {
            \l_myderivative_den_tl
        }
    }

    % helper function to process a factor in the denominator
    \cs_new_protected:Npn \myderivative_add_den_factor:n #1
    {
        % clear the variables
        \tl_clear:N \l_myderivative_den_factor_var_flag_tl
        \tl_clear:N \l_myderivative_den_factor_exp_tl

        \tl_if_empty:NF \l_myderivative_den_tl
        {
            % add a thin space if we've already processed at least one factor
            \tl_put_right:Nn \l_myderivative_den_tl { \, }
        }

        % format the factor
        \tl_map_inline:nn { #1 }
        {
            \myderivative_fmt_den_factor:n { ##1 }
        }

        % check for an implicit exponent
        \tl_if_empty:NT \l_myderivative_den_factor_exp_flag_tl
        {
            \tl_if_empty:NF \l_myderivative_num_exp_tl
            {
                \tl_put_right:Nn \l_myderivative_num_exp_flag_tl { 1 }
                \tl_put_right:Nn \l_myderivative_num_exp_tl { + }
            }
            \tl_put_right:Nn \l_myderivative_num_exp_tl { 1 }
        }
    }

    % helper function to format a factor in the denominator
    \cs_new_protected:Npn \myderivative_fmt_den_factor:n #1
    {
        \tl_if_empty:NTF \l_myderivative_den_factor_var_flag_tl
        {
            % if the flag is not set, then we are processing the variable
            \tl_put_right:Nn \l_myderivative_den_tl { \partial #1 }

            % set the flag
            \tl_put_right:Nn \l_myderivative_den_factor_var_flag_tl { 1 }
        }
        {
            % if the flag is set, then we are processing the exponent
            \tl_put_right:Nn \l_myderivative_den_tl { ^{#1} }

            % update the numerator exponent
            \tl_if_empty:NF \l_myderivative_num_exp_tl
            {
                \tl_put_right:Nn \l_myderivative_num_exp_tl { + }
            }
            \tl_put_right:Nn \l_myderivative_num_exp_tl { #1 }

            % set the flag
            \tl_put_right:Nn \l_myderivative_den_factor_exp_flag_tl { 1 }
            \tl_put_right:Nn \l_myderivative_num_exp_flag_tl { 1 }
        }
    }
\ExplSyntaxOff

\begin{document}

\[
    \derivative{f}{xp,yq,zr}
\]

\[
    \derivative{f}{x2,y3,z4}
\]

\[
    \derivative{f}{x}
\]

\[
    \derivative{f}{{\hat{x}}{2},{\tilde{y}}{3}}
\]

%\[
%   \derivative{f}{{\hat{x}}}
%\]

\[
    \derivative{f}{{{\hat{x}}}}
\]

\end{document}

答案1

实现可能看起来像

\documentclass{article}
\usepackage{expl3,xparse}

\makeatletter
\newcommand{\ifintegerTF}[1]{%
  \ifnum`#1<`0 %
    \expandafter\@secondoftwo
  \else
    \ifnum`#1>`9 %
      \expandafter\expandafter\expandafter\@secondoftwo
    \else
      \expandafter\expandafter\expandafter\@firstoftwo
    \fi  
  \fi
}

\ExplSyntaxOn
\int_new:N \l__stirling_total_int
\seq_new:N \l__stirling_denom_seq
\tl_new:N \l__stirling_denom_tl
\tl_new:N \l__stirling_numer_tl
\seq_new:N \l__stirling_powers_seq
\cs_new_protected:Npn \stirling_derivative:nn #1#2
  {
    \group_begin:
      \int_zero:N \l__stirling_total_int
      \seq_clear:N \l__stirling_powers_seq
      \tl_clear:N \l__stirling_denom_tl
      \clist_map_function:nN {#2} \__stirling_derivative_entry:n
      \int_compare:nNnF \l__stirling_total_int = \c_zero
        {
          \seq_put_right:Nx \l__stirling_powers_seq
            { \int_use:N \l__stirling_total_int }
        }
      \tl_set:Nx \l__stirling_numer_tl
        {
          d
          \seq_if_empty:NF \l__stirling_powers_seq
            {
              ^
                { \seq_use:Nn \l__stirling_powers_seq { + } }
            }
          #1
        }
      \frac { \l__stirling_numer_tl } { \l__stirling_denom_tl }
    \group_end:
  }
\cs_new_protected:Npn \__stirling_derivative_entry:n #1
  {
    \__stirling_derivative_entry_aux:nw #1 \q_stop
  }
\cs_new_protected:Npn \__stirling_derivative_entry_aux:nw #1#2 \q_stop
  {
    \tl_if_empty:NF \l__stirling_denom_tl
      { \tl_put_right:Nn \l__stirling_denom_tl { \, } }
    \tl_if_empty:nTF {#2}
      {
        \int_incr:N \l__stirling_total_int
        \tl_put_right:Nn \l__stirling_denom_tl { d #1 }
      }
      {
        \seq_clear:N \l__stirling_denom_power_seq
        \clist_map_function:nN {#2} \__stirling_derivative_entry_power:n
        \tl_put_right:Nx \l__stirling_denom_tl
          {
            d #1 \exp_not:N ^
              { 
                \seq_use:Nn \l__stirling_denom_power_seq { + }
              }
          }
      }
  }
\cs_new_protected:Npn \__stirling_derivative_entry_power:n #1
  {
    \ifintegerTF {#1}
      { \int_add:Nn \l__stirling_total_int {#1} }
      { \seq_put_right:Nn \l__stirling_powers_seq {#1} }
    \seq_put_right:Nn \l__stirling_denom_power_seq {#1}
  }
\DeclareDocumentCommand \derivative { m m }
  { \stirling_derivative:nn {#1} {#2} }
\ExplSyntaxOff


\begin{document}

\[
    \derivative{x}{{y}{2},{z}{3}}
\]

\[
    \derivative{x}{{y}{m},{z}{n}}
\]

\[
    \derivative{x}{{v}{3},{w}{k,2},y,{z}{m}}
\]

\end{document}

我保留了\ifintegerTF与旧问题中使用的命令相同的命令,并修复了另一个问题中提出的数学部分。除此之外,它非常简单明了。

相关内容