1

I have started writing some packages for my own personal use based on LaTeX3. I would like to achieve a clear separation between interfaces and implementation. Here is an example of some code (from two packages merged into the 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}

output of the MWE

At the moment, the commands are not related to each other. However, an alphabet is a set of characters. Therefore, I think that the implementation of \Set should take care of the braces and the spacing between the items, whereas \Alphabet only wraps the items as characters.

Does the LaTeX3 philosophy allow to call a public commands from another package inside the implementation (e.g., \__inft_alphabet:n calls \Set), or is it better to have implementation functions that are not protected (i.e., inf-theor relies on some internal functions of math-sets)?

  • 1
    it would be best if the math-set had a public (expl3) interface that could be used by other expl3 packages and (separately) document interfaces defined by xparse for both packages – David Carlisle Nov 15 '17 at 21:59
  • @DavidCarlisle I have posted an answer based on your advice. – Matthias Nov 16 '17 at 17:03
2

Based on the comment by David Carlisle I think this would be the way to go.

\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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.