我已经开始基于 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}
目前,这些命令彼此之间没有关联。但是,字母表是字符集。因此,我认为的实现\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}