有关为数学宏创建快捷方式的 expl3 命令的帮助

有关为数学宏创建快捷方式的 expl3 命令的帮助

我正在尝试创建一个命令\projlib_math_define_shortcut:nnn来定义数学字母的快捷方式。理想情况下,它应该能够使用类似\projlib_math_define_shortcut:nnn { mathcal } { cal, mc } { A, B, C },它应该这样做:

  1. 创建两个快捷方式,\cal\mc\mathcal
  2. 在本例中,为给定的字母创建快捷方式,\calA以及\mcA\mathcal{A}等。

为此,我使用了clistexpl3 结构。我认为是我对#####的错误使用导致了错误(Illegal parameter number in definition of \__clist_map_1:w.)。我当前的代码列在下面的 MWE 中。你能告诉我为什么它会产生错误以及如何修复它吗?

\documentclass{article}

\usepackage{amssymb}

\ExplSyntaxOn

% \projlib_math_define_shortcut:nnn { math command } { shortcut name(s) } { shortcut member(s) }
\cs_new:Nn \projlib_math_define_shortcut:nnn
  {
    \clist_set:Nn \l_tmpa_clist { #2 }
    \clist_set:Nn \l_tmpb_clist { #3 }
    \clist_map_inline:Nn \l_tmpa_clist
      {
        % create \shortcut{*}
        \tl_if_blank:eF { ##1 }
          {
            \tl_if_exist:cF { ##1 }
              {
                \tl_gset:cn { ##1 }
                  {
                    \ensuremath { \tl_use:c { #1 } { ###1 } }
                  }
              }
          }
        % create \shortcut*
        \clist_map_inline:Nn \l_tmpb_clist
          {
            \tl_if_exist:cF { ##1 ###1 }
              {
                \tl_gset:cn { ##1 ###1 }
                  {
                    \ensuremath { \tl_use:c { #1 } { ###1 } }
                  }
              }
          }
      }
  }

\projlib_math_define_shortcut:nnn { mathbb } { bb }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\projlib_math_define_shortcut:nnn { mathfrak } { mf, frak }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\projlib_math_define_shortcut:nnn { mathcal } { mc, cal }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

% \projlib_math_define_shortcut:nnn { mathbb } { }
%   {
%     N, Z, Q, R, C, F, A
%   }

\ExplSyntaxOff

\begin{document}

\fraka

\bbA

% \C

\end{document}

答案1

我不确定为什么要为同一个命令定义几个不同的快捷方式,因为它们会造成混淆。另外,你应该不是在包中提供快捷方式,因为用户可能对 的含义有不同的看法\mfb,例如 可能的含义,并且由于不明确的原因(包已经提供)他们无法使用它。因此,为此目的定义一个用户级命令并记录其用法。

在任何情况下我都会忽略\ensuremath:允许\calA{}使用文本模式而不是更清晰、更语义的模式,你什么也得不到$\calA$

您还希望避免 TeX 定义如此多的标记列表变量,并且\tl_use:c { cal } { A }从概念的角度来看这也是有争议的。

让我们看看:考虑到\macro接受一个参数,您想要定义一个快捷前缀,比如pre,并且对于列表中的每个字母,比如X,您想要\preX代表\macro{X}

所以你想要的是

\cs_new_protected:Npn \preX { \macro{X} }

可以通过以下方式实现

\cs_new_protected:cpn { preX } { \macro{X} }

因此,这里是代码:我没有在同一个函数中执行所有操作,而是将映射分成两部分。

\documentclass{article}
\usepackage{amsmath,amssymb}

\ExplSyntaxOn

\cs_new_protected:Nn \projlib_math_define_shortcut:Nnn
 {% #1 is the math command
  % #2 is a list of prefixes
  % #3 is a list of letters
  \clist_map_inline:nn { #2 }
   {
    \__projlib_math_define_shortcut_do:Nnn #1 { ##1 } { #3 }
   }
 }

\cs_new_protected:Nn \__projlib_math_define_shortcut_do:Nnn
 {% #1 is the math command
  % #2 is a prefix
  % #3 is a list of letters
  \clist_map_inline:nn { #3 }
   {
    \cs_new_protected:cpn { #2##1 } { #1{##1} }
   }
 }

\projlib_math_define_shortcut:Nnn \mathbb { bb }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
%    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\projlib_math_define_shortcut:Nnn \mathfrak { mf, frak }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\ExplSyntaxOff

\begin{document}

$\bbA+\bbZ+\mfA+\mfb+\frakY$

\end{document}

在此处输入图片描述

如果您更喜欢使用{mathfrak}而不是\mathfrak(但我不明白为什么),您可以使用\exp_not:c

\documentclass{article}
\usepackage{amsmath,amssymb}

\ExplSyntaxOn

\cs_new_protected:Nn \projlib_math_define_shortcut:nnn
 {% #1 is the math command name
  % #2 is a list of prefixes
  % #3 is a list of letters
  \clist_map_inline:nn { #2 }
   {
    \__projlib_math_define_shortcut_do:nnn { #1 } { ##1 } { #3 }
   }
 }

\cs_new_protected:Nn \__projlib_math_define_shortcut_do:nnn
 {% #1 is the math command name
  % #2 is a prefix
  % #3 is a list of letters
  \clist_map_inline:nn { #3 }
   {
    \cs_new_protected:cpx { #2##1 } { \exp_not:c { #1 }{##1} }
   }
 }

\projlib_math_define_shortcut:nnn {mathbb} { bb }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
%    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\projlib_math_define_shortcut:nnn {mathfrak} { mf, frak }
  {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }

\ExplSyntaxOff

\begin{document}

$\bbA+\bbZ+\mfA+\mfb+\frakY$

\end{document}

其他一些值得注意的事项。

  1. 如果将一个映射嵌套在另一个映射中,则需要双倍的字符数#,不加一。

  2. 这样做\clist_set:Nn \l_tmpa_clist { #2 }是浪费,因为你可以使用\clist_map_inline:nn { #2 } { ... }

  3. 映射期间无需检查当前项是否为空,因为\clist_map_inline:nn无论如何都会忽略空项。

答案2

如果不使用 expl3,宏具有更紧凑的形式:

\def\mydefmath #1#2 #3{\expandafter\def\csname #2#3\endcsname{#1{#3}}}
\def\Letters{ABCDEFGHIJKLMNOPQRSTUVWXYZ}
\def\letters{abcdefghijklmnopqrstuvwxyz}
\def\mydefall #1#2 #3{\def\tmp{\mydefmath #1#2 }\expandafter\mydefallA#3{}}
\def\mydefallA #1{\ifx^#1^\else \tmp#1\expandafter\mydefallA\fi}

\mydefall \mathbb   bb   \Letters
\mydefall \mathfrak mf   \Letters
\mydefall \mathfrak mf   \letters
\mydefall \mathfrak frak \Letters
\mydefall \mathfrak frak \letters
\mydefall \mathcal  mc   \Letters
\mydefall \mathcal  cal  \Letters
\mydefall \mathscr  ms   \Letters
\mydefall \mathscr  scr  \Letters

%% testing:

\meaning\msC  % -> \mathscr{C}
\meaning\bbD  % -> \mathbb{D}
\meaning\mfa  % -> \mathfrak{a}

\end
 

答案3

根据@egreg上面的精彩回答,以下是完整版本:

\documentclass{article}
\usepackage{amsmath,amssymb,mathpazo}

\ExplSyntaxOn

\cs_new_protected:Nn \projlib_math_define_shortcut:Nnn
% #1 is the math command
% #2 is a prefix
% #3 is a list of letters
  {
    \tl_if_blank:eTF { #2 }
      {
        % create \shortcut*
        \clist_map_inline:nn { #3 }
          {
            \cs_if_exist:cF { ##1 }
              {
                \cs_new_protected:cpn { ##1 } { #1 {##1}  }
              }
          }
      }
      {
        \clist_map_inline:nn { #2 }
          {
            % create \shortcut{} and \shortcut*
            \__projlib_math_define_shortcut_do:Nnn #1 { ##1 } { #3 }
          }
      }
  }

\cs_new_protected:Nn \__projlib_math_define_shortcut_do:Nnn
  {
    % create \shortcut{}
    \cs_if_exist:cF { #2 }
      {
        \cs_new_protected:cpn { #2 } { #1 }
      }
    % create \shortcut*
    \clist_map_inline:nn { #3 }
      {
        \cs_if_exist:cF { #2 ##1 }
          {
            \cs_new_protected:cpn { #2 ##1 } { #1{##1} }
          }
      }
  }

 \projlib_math_define_shortcut:Nnn \mathbb { bb }
 {
   A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1
 }

\projlib_math_define_shortcut:Nnn \mathbb { }
 {
   N, Z, Q, R, C, F, A
 }

\projlib_math_define_shortcut:Nnn \mathfrak { mf, frak }
 {
   A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
   a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
 }

\projlib_math_define_shortcut:Nnn \mathcal { mc, cal }
 {
   A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
 }

\projlib_math_define_shortcut:Nnn \mathscr { ms, scr }
 {
   A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
 }

\ExplSyntaxOff

\begin{document}

$\bbA+\bbZ+\mfA+\mfb+\frakY$

$\C \N \Q \R \F \bb1$

\end{document}

在此处输入图片描述

相关内容