在 LaTeX3 中分解代码

在 LaTeX3 中分解代码

我已经开始基于 LaTeX3 编写一些供个人使用的软件包。我希望实现接口和实现之间的明确分离。以下是一些代码示例(来自合并到 MWE 的两个软件包)。

\documentclass{article}

\usepackage{expl3}
\usepackage{xparse}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{braket}


\ExplSyntaxOn

% -----------------------------------------------------------------------------
%  math-sets.sty
% -----------------------------------------------------------------------------

% INTERFACE

% \Set is already defined in package braket, but not needed with its original definition
\RenewDocumentCommand \Set { m o }
{ 
    \IfNoValueTF { #2 } { \SetExt { #1 } } { \SetInt { #1 }{ #2 } } 
}

% extensional definition of a set
\NewDocumentCommand \SetExt { m } 
{ 
    \left\{ \__mathset_format_cs_list:n { #1 } \right\} 
}

% intensional definition of a set
\NewDocumentCommand \SetInt { m m }
{ 
    \left\{ {#1} \mathrel{} \middle| \mathrel{} {#2} \right\} 
}

% IMPLEMENTATION

% formatting of a comma-separated list
\cs_new_protected:Npn \__mathset_format_cs_list:n #1
{
    \seq_set_from_clist:Nn \l_tmpa_seq {#1}
    \seq_use:Nn \l_tmpa_seq {,\,}
}


% -----------------------------------------------------------------------------
%  inf-theor.sty
% -----------------------------------------------------------------------------

% INTERFACE

% character 
\NewDocumentCommand \Char { O{\width} m } 
{
    \__inft_char:nn { #1 } { #2 } 
}

% alphabet = finite set of characters
\NewDocumentCommand \Alphabet { m } 
{ 
    \left\{ \__inft_alphabet:n { #1 } \right\} 
}

% IMPLEMENTATION

\cs_new_protected:Nn \__inft_char:nn
{
    \makebox[#1]
    { 
        \str_case_x:nnF { \tl_to_str:n {#2} }
        {
            { ##                } { \texttt{\#}            }
            { \c_underscore_str } { \scalebox{.87}{$\Box$} }
            { \c_tilde_str      } { $\varepsilon$          }
            {                   } { $\varepsilon$          }
        }
        { \texttt{#2} }
    }
}

\cs_new_protected:Nn \__inft_alphabet:n
{
    \seq_set_from_clist:Nn \l_tmpa_seq {#1}
    \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq 
        { \exp_not:n { \__inft_char:nn { \width} {##1} } }
    \seq_use:Nn \l_tmpb_seq { , \, }
}

\ExplSyntaxOff


% -----------------------------------------------------------------------------
%  Main document
% -----------------------------------------------------------------------------

\begin{document}

$\Set{}$ \qquad
$\Set{0}$ \qquad
$\Set{1, 2, 3, \dots}$ \qquad
$\Set{x}[x > 0]$

\bigskip

\Char{a} \qquad
\Char{#} \qquad
\Char{_} \qquad
\Char{~}  \qquad
\Char{} 

\bigskip

$\Alphabet{}$ \qquad
$\Alphabet{a, b, c}$ \qquad
$\Alphabet{A, B, #}$ \qquad
$\Alphabet{0, 1, _}$

\end{document}

MWE 的输出

目前,这些命令彼此之间没有关联。但是,字母表字符集。因此,我认为的实现\Set应该考虑括号和项目之间的间距,而\Alphabet只将项目包装为字符。

LaTeX3 理念是否允许从实现内部的另一个包调用公共命令(例如,\__inft_alphabet:n调用\Set),或者最好拥有不受保护的实现函数(即inf-theor依赖于某些内部函数math-sets)?

答案1

根据大卫·卡莱尔我认为这才是可行的方法。

\documentclass{article}

\usepackage{expl3}
\usepackage{xparse}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{braket}


\ExplSyntaxOn

% -----------------------------------------------------------------------------
%  math-sets.sty
% -----------------------------------------------------------------------------

% INTERFACE

\RenewDocumentCommand \Set { m o }
{ 
  \IfNoValueTF { #2 }
    { \mathset_set_ext:n  { #1 }       }
    { \mathset_set_int:nn { #1 }{ #2 } } 
}


% IMPLEMENTATION

\cs_new:Nn \mathset_set_ext:n
{
  \left\{ \__mathset_format_cs_list:n { #1 } \right\} 
}

\cs_generate_variant:Nn \mathset_set_ext:n { f }

\cs_new:Nn \mathset_set_int:nn
{
  \left\{ { #1 } \mathrel{} \middle| \mathrel{} { #2 } \right\} 
}

\cs_new_protected:Nn \__mathset_format_cs_list:n 
{
  \seq_set_from_clist:Nn \l_tmpa_seq { #1 }
  \seq_use:Nn \l_tmpa_seq { , \, }
}


% -----------------------------------------------------------------------------
%  inf-theor.sty
% -----------------------------------------------------------------------------

% INTERFACE

% character 
\NewDocumentCommand \Char { O{\width} m } 
{
  \inft_char:nn { #1 } { #2 } 
}

% alphabet = finite set of characters
\NewDocumentCommand \Alphabet { m } 
{ 
  \inft_alphabet:n { #1 }
}


% IMPLEMENTATION

\cs_new:Nn \inft_char:nn
{
  \makebox[#1]
  { 
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      { ##                } { \texttt{\#}            }
      { \c_underscore_str } { \scalebox{.87}{$\Box$} }
      { \c_tilde_str      } { $\varepsilon$          }
      {                   } { $\varepsilon$          }
    }
    { \texttt{#2} }
  }
}

\cs_new:Nn \inft_alphabet:n
{
  \seq_set_from_clist:Nn \l_tmpa_seq { #1 }
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq 
      { \exp_not:n { \inft_char:nn { \width} {##1} } }
  \mathset_set_ext:f { \seq_use:Nn \l_tmpb_seq { , } }
}

\ExplSyntaxOff


% -----------------------------------------------------------------------------
%  Main document
% -----------------------------------------------------------------------------

\begin{document}

$\Set{}$ \qquad
$\Set{0}$ \qquad
$\Set{1, 2, 3, \dots}$ \qquad
$\Set{x}[x > 0]$

\bigskip

\Char{a} \qquad
\Char{#} \qquad
\Char{_} \qquad
\Char{~}  \qquad
\Char{} 

\bigskip

$\Alphabet{}$ \qquad
$\Alphabet{a, b, c}$ \qquad
$\Alphabet{A, B, #}$ \qquad
$\Alphabet{0, 1, _}$

\end{document}

相关内容