数学函数和扩展问题

数学函数和扩展问题

以下 MWE 是非常我正在尝试开发的更复杂系统的简化版本。因此,界面看起来有点奇怪,我不希望任何人喜欢它目前的形式,我自己也不喜欢。然而,它展示了我正在处理的一些扩展问题。

假设我想为以下任何形式的界面创建一个宏系统

⟨符号⟩ ^ ⟨上索引⟩ _ ⟨下索引⟩ ( ⟨参数⟩ )

为此,我创建了命令\newmathfunctioncommand{#1}#1命令名称不带反斜杠)。这定义了一些用于存储能力、索引和参数的标记列表,以及\#1带有接口的命令

\#1 { ⟨symbol⟩ } [ ⟨upper index⟩ ] [ ⟨lower index⟩ ] { ⟨argument⟩ (optional argument) } [ ⟨output math function⟩ ]

这应该打印出⟨symbol⟩ ^ ⟨upper index⟩ _ ⟨lower index⟩ ( ⟨argument⟩ )如上所示的行。然后它需要一个额外的可选参数⟨output math function⟩。这应该包含另一个数学函数命令的名称,以包装函数的最终值\#1,以便它本身成为一个数学函数。换句话说,它应该允许如下接口:

\newmathfunctioncommand{fun}

\newmathfunctioncommand{otherfun}

$\fun{f}[i][j]$ % Should output f^{i}_{j}

$\fun{f}[i][j]{x}$ % Should output f^{i}_{j}(x)

$\fun{f}[\fun{g}{x}]{t}$ % Should output f^{g(x)}(t)

$\fun{f}[i][j]{x}[otherfun]$ % Should output \otherfun{ f^{i}_{j}(x) }

$\fun{f}[i][j]{x}[otherfun]{t}$
    % Should output \otherfun{ f^{i}_{j}(x) }{t},
    % i.e., f^{i}_{j}(x)(t)

这样做的目的是允许函数的值是其他函数,这是数学中一个众所周知的现象。然而,这是我无法工作的系统的一部分。出错的代码是包含在标签中的代码<code that does not work>工作在标签中<code that does work>。此工作代码实现了除输出函数系统之外的所有内容。有人可以修复这个扩展问题吗?

请注意,使用的原因\group_begin: ... \group_end:是为了允许像表达式那样\fun{f}[\fun{g}{x}]{t}不会导致无限循环。

我知道这个 MWE 中的某些代码部分看起来很荒谬,例如,输出函数设置时没有反斜杠。我要求你保留这个系统,因为它们在我真正试图创建的更复杂的设置中更有意义。此外,为了保持代码简短,这个版本的代码中删除了很多东西,例如,控制括号的大小。

\documentclass{article}

\usepackage{amsmath,xparse}

\ExplSyntaxOn

\tl_new:N\l_mathfunction_temp

\cs_set:Npn\g_mathfunction_identity:n#1 { #1 } % the identity function

\DeclareDocumentCommand\newmathfunctioncommand{m}
{
    % This defines the command \⟨#1⟩. First we define some token lists
    % to store the data of upper index, lower index etc. in.
    \tl_new:c { g_mathfunction_#1_upper_index }
    \tl_new:c { g_mathfunction_#1_lower_index }
    \tl_new:c { g_mathfunction_#1_argument }
    \tl_new:c { g_mathfunction_#1_output_function }
    \tl_set:cn { g_mathfunction_#1_output_function } { g_mathfunction_identity:n  }
        % This will be the default output function if none else is given
    \exp_args:Nc\DeclareDocumentCommand{#1}{moogo}{
        \group_begin:
            \IfNoValueTF { ##2 } % If ##2 is non-empty, set upper index token list
                                 % to that value 
            {
                % do nothing
            }
            {
                \tl_set:cn { g_mathfunction_#1_upper_index } { \exp_not:n { ##2 } }
            }
            \IfNoValueTF { ##3 } % If ##3 is non-empty, set lower index token list
                                 % to that value
            {
                % do nothing
            }
            {
                \tl_set:cn { g_mathfunction_#1_lower_index } { \exp_not:n { ##3 } }
            }
            \IfNoValueTF { ##4 } % If ##4 is non-empty, set argument token list
                                 % to that value
            {
                % do nothing
            }
            {
                \tl_set:cn { g_mathfunction_#1_argument } {
                    \exp_not:n { ##4 }
                }
            }
            \IfNoValueTF { ##5 } % If ##5 is non-empty, set output function
                                 % token list to that value.
            {
                % do nothing
            }
            {
                \tl_set:cn { g_mathfunction_#1_output_function } { \exp_not:n { ##5 } }
            }
            %
            %
            %
            \tl_set:Nx\l_mathfunction_temp  % Store output data in a temporary
                                            % token list
            {
                \exp_not:n { ##1 }
                \tl_if_empty:cTF { g_mathfunction_#1_upper_index }
                {
                    % do nothing
                }
                {
                    \sp { \use:c { g_mathfunction_#1_upper_index } }
                }
                \tl_if_empty:cTF { g_mathfunction_#1_lower_index }
                {
                    % do nothing
                }
                {
                    \sb { \use:c { g_mathfunction_#1_lower_index } }
                }
                \tl_if_empty:cTF { g_mathfunction_#1_argument }
                {
                    % do nothing
                }
                {
                    (\use:c { g_mathfunction_#1_argument } )
                }
            }
            %
            % Now if the argument has a value, and only in this case, set
            % the command \l_mathfunction_output_command:n to be equal
            % to the output math function command.
            %
            \tl_if_empty:cTF { g_mathfunction_#1_argument }
            {
                \cs_set_eq:NN
                    \l_mathfunction_output_command:n
                    \g_mathfunction_identity:n
            }
            {
                \exp_args:Nno\cs_set_eq:cc
                    { l_mathfunction_output_command:n }
                    { \use:c { g_mathfunction_#1_output_function } }
            }
        %
        %
        % Now finally it is time to render the actual output
        %
        % <code that does not work>
         \exp_args:NNo
         \exp_args:NNV
         \group_end:
         \l_mathfunction_output_command:n
         { \l_mathfunction_temp }
        % </code that does not work>
        %
        %
        % <code that does work>
        % \exp_args:NV
        % \group_end:
        % \l_mathfunction_temp
        % </code that does work>
    }
}

\DeclareDocumentCommand\mathfunctionsetup{moogo}
    % a command to setup the arguments
    % globally.
{
    \IfNoValueTF { #2 }
    {
        % do nothing
    }
    {
        \tl_set:cn { g_mathfunction_#1_upper_index } { \exp_not:n { #2 } }
    }
    \IfNoValueTF { #3 }
    {
        % do nothing
    }
    {
        \tl_set:cn { g_mathfunction_#1_lower_index } { \exp_not:n { #3 } }
    }
    \IfNoValueTF { #4 }
    {
        % do nothing
    }
    {
        \tl_set:cn { g_mathfunction_#1_argument } {
            \exp_not:n { #4 }
        }
    }
    \IfNoValueTF { #5 }
    {
        % do nothing
    }
    {
        \tl_set:cn { g_mathfunction_#1_output_function } { \exp_not:n { #5 } }
    }
}

\ExplSyntaxOff

\begin{document}

\newmathfunctioncommand{fun}

\newmathfunctioncommand{otherfun}

$\fun{f}[i][j]$ % Should output f^{i}_{j}

$\fun{f}[i][j]{x}$ % Should output f^{i}_{j}(x)

$\fun{f}[\fun{g}{x}]{t}$ % Should output f^{g(x)}(t) 

$\fun{f}[i][j]{x}[otherfun]$ % Should output \otherfun{ f^{i}_{j}(x) }

$\fun{f}[i][j]{x}[otherfun]{t}$
    % Should output \otherfun{ f^{i}_{j}(x) }{t},
    % i.e., f^{i}_{j}(x)(t)

\mathfunctionsetup{fun}[a][b][otherfun]

$\fun{g}{x}{t}$ % Should output \otherfun { g^{a}_{b}(x) } { t },
                % i.e., g^{i}_{j}(x)(t)

\mathfunctionsetup{fun}[a][b][fun]

$\fun{g}{x}[p][q]{r}$   % Should output \fun { g^a_b(x) }[p][q]{r},
                        % i.e., g^{a}_{b}(x) ^{p}_{q}(r) 
\end{document}

答案1

语法可能会更清楚吗\fun{f}[a][b](x)

无论如何,这是一个解决方案。唯一的变化是可选函数参数在开头\fun[otherfun]{f}[a][b]{t}{x}应该是给出函数的方式。

请注意,您的文档中有很多内容可以纠正(变量名称、函数名称、用法TF、与扩展有关的一些不必要的内容等)。

唯一不正确的是最后一个输出,因为我不知道背后的逻辑,我不知道如何确保最后一个下标上标只在正确的情况下添加。如果你添加逻辑,我可以修正我的代码。

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\tl_new:N \l_gaussler_tmp_tl

\NewDocumentCommand \newmathfunctioncommand { m }
 {
  \gaussler_newmfcmd:c { #1 }
 }
\NewDocumentCommand \mathfunctionsetup { m o o g o }
 {
  \IfValueT {#2} { \tl_set:cn { l_gaussler_mf_ \tl_to_str:n {#1} _sp_tl  } { #2 } }
  \IfValueT {#3} { \tl_set:cn { l_gaussler_mf_ \tl_to_str:n {#1} _sb_tl  } { #3 } }
  \IfValueT {#4} { \tl_set:cn { l_gaussler_mf_ \tl_to_str:n {#1} _arg_tl } { #4 } }
  \IfValueT {#5} { \cs_set:cpn { gaussler_mf_ \tl_to_str:n {#1} _use:w } { \use:c { #5 } } }
 }
\cs_new_protected:Npn \gaussler_newmfcmd:N #1
 {
  \tl_new:c { l_gaussler_mf_ \cs_to_str:N #1 _arg_tl }
  \tl_new:c { l_gaussler_mf_ \cs_to_str:N #1 _sp_tl }
  \tl_new:c { l_gaussler_mf_ \cs_to_str:N #1 _sb_tl }
  \cs_new:cpn { gaussler_mf_ \cs_to_str:N #1 _use:w } { \use:n }
  \NewDocumentCommand #1 { o m o o g }
   {
    \group_begin:
    \IfValueT {##1}
     { \cs_set:cpn { gaussler_mf_ \cs_to_str:N #1 _use:w } { \use:c { ##1 } } }
    \IfValueT {##3}
     { \tl_set:cn { l_gaussler_mf_ \cs_to_str:N #1 _sp_tl } { ##3 } }
    \IfValueT {##4}
     { \tl_set:cn { l_gaussler_mf_ \cs_to_str:N #1 _sb_tl } { ##4 } }
    \IfValueT {##5}
     { \tl_set:cn { l_gaussler_mf_ \cs_to_str:N #1 _arg_tl } { ##5 } }
    \tl_set:Nx \l_gaussler_tmp_tl
     {
      \IfNoValueTF {##5}
       { \exp_not:N \use:n }
       { \use:c { gaussler_mf_ \cs_to_str:N #1 _use:w } }
       {
        \exp_not:n { ##2 }
        \tl_if_empty:cF { l_gaussler_mf_ \cs_to_str:N #1 _sp_tl }
         { \sp{ \tl_use:c { l_gaussler_mf_ \cs_to_str:N #1 _sp_tl } } }
        \tl_if_empty:cF { l_gaussler_mf_ \cs_to_str:N #1 _sb_tl }
         { \sb{ \tl_use:c { l_gaussler_mf_ \cs_to_str:N #1 _sb_tl } } }
        \tl_if_empty:cF { l_gaussler_mf_ \cs_to_str:N #1 _arg_tl }
         { ( \tl_use:c { l_gaussler_mf_ \cs_to_str:N #1 _arg_tl } ) }
       }
     }
    \exp_last_unbraced:NV
    \group_end:
    \l_gaussler_tmp_tl
   }
 }
\cs_generate_variant:Nn \gaussler_newmfcmd:N { c }

\ExplSyntaxOff

\begin{document}

\newmathfunctioncommand{fun}

\newmathfunctioncommand{otherfun}

$\fun{f}[i][j]$ % Should output f^{i}_{j}

$\fun{f}[i][j]{x}$ % Should output f^{i}_{j}(x)

$\fun{f}[\fun{g}{x}]{t}$ % Should output f^{g(x)}(t) 

$\fun[otherfun]{f}[i][j]{x}$ % Should output \otherfun{ f^{i}_{j}(x) }

$\fun[otherfun]{f}[i][j]{x}{t}$
    % Should output \otherfun{ f^{i}_{j}(x) }{t},
    % i.e., f^{i}_{j}(x)(t)

\mathfunctionsetup{fun}[a][b][otherfun]

$\fun{g}{x}{t}$ % Should output \otherfun { g^{a}_{b}(x) } { t },
                % i.e., g^{i}_{j}(x)(t)

\mathfunctionsetup{fun}[a][b][fun]

$\fun{g}{x}[p][q]{r}$   % Should output \fun { g^a_b(x) }[p][q]{r},
                        % i.e., g^{a}_{b}(x) ^{p}_{q}(r) 
\end{document}

相关内容