Generating a vigenere square in LaTeX3 I'm trying to generate a vigenere square using expl3. My aim is to provide an easy interface for different alphabets and different scaling. Therefore I chose a tabular-based approach which seemed very easy to customize.

Points I would especially appreciate feedback to:


Is using tabular a good idea or might it be very bad (e.g. when the user customizes array stretches)?
Am I abusing expl3 at any point (local vs. global)?
the user interface in general (key-value approach)


Code:

\documentclass{article}
\usepackage[landscape]{geometry}
\usepackage{xparse}

\ExplSyntaxOn
\keys_define:nn { vigenere }
    {
        font        .code:n    = { \cs_set_eq:NN \__vigenere_font: #1 },
        font   .default:n = { \small },
        font   .initial:n = { \small },
        tabcolsep .dim_set:N = \l__vigenere_tabcolsep_dim,
        tabcolsep .initial:n = { 3pt },
        alphabet  .tl_set:N  = \l__vigenere_alphabet_tl,
        alphabet  .initial:n = { 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 }
    }
\NewDocumentCommand { \printvigeneretabular } { O{} }
    {
        \group_begin:
        \keys_set:nn { vigenere } { #1 }
        \clist_set:NV  \l_tmpa_clist \l__vigenere_alphabet_tl
        \clist_clear:N \l_tmpb_clist
        \tl_clear:N    \l_tmpa_tl
        \int_step_inline:nnnn { 1 } { 1 } { \clist_count:N \l_tmpa_clist }
            {
                \tl_put_right:Nx \l_tmpa_tl { c| }
            }
        \__vigenere_font:
        \dim_set_eq:NN \tabcolsep \l__vigenere_tabcolsep_dim
        \expandafter\tabular\expandafter{\expandafter|\l_tmpa_tl}
            \hline
            \bool_while_do:nn { \int_compare_p:n { \clist_count:N \l_tmpa_clist &gt; 0 } }
                {
                    \clist_use:Nnnn \l_tmpa_clist { &amp; } { &amp; } { &amp; }
                    \clist_if_empty:NF \l_tmpb_clist
                        { &amp; \clist_use:Nnnn \l_tmpb_clist { &amp; } { &amp; } { &amp; } }
                    \clist_gpop:NN \l_tmpa_clist \l_tmpa_tl
                    \clist_gput_right:NV \l_tmpb_clist \l_tmpa_tl
                    \\\hline
                }
        \endtabular
        \group_end:
    }
\ExplSyntaxOff

\begin{document}
 \printvigeneretabular\par
 \printvigeneretabular[font=\tiny,alphabet={1,2,3,4,5,6,7,8,9,10},tabcolsep=1pt]
\end{document}
About your points:


The interface seems pretty clear.
If you fear about the \arraystretch parameter being abused, you're right: on a double spaced document all tables come out horribly and local remedies are often necessary. Maybe adding a stretch key could help for these cases.
Yes, you're abusing local and global assignments.


Some comments about the code: 


There is no point in the key alphabet to set a tl variable, which is then converted to a clist
There's no need to set a .default:n for the font key: the value specified with .default:n would be used if the key is called without assigning a value
\int_step_inline:nnnn can be done more simply using the * feature of tabular
Never use \expandafter in expl3 code
You should not use global assignments on local variables
\clist_gpop:NN should be \clist_gpop_left:NN (but I changed it into \seq_pop_left:NN)
One can do with a simpler loop, using \prg_replicate:nn


I'd also prefer to prepare the table body outside the table, with sequences instead of clists, which are less efficient.



\documentclass{article}
\usepackage[landscape]{geometry}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand { \printvigeneretabular } { O{} }
 {
  \vigenere_tabular:n { #1 }
 }

% keys
\keys_define:nn { vigenere }
 {
  font      .code:n       = { \cs_set_eq:NN \__vigenere_font: #1 },
  font      .initial:n    = { \small },
  tabcolsep .dim_set:N    = \l__vigenere_tabcolsep_dim,
  tabcolsep .initial:n    = { 3pt },
  alphabet  .clist_set:N  = \l__vigenere_alphabet_clist,
  alphabet  .initial:n    = { 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 }
 }

% variables
\tl_new:N \l__vigenere_tablebody_tl
\seq_new:N \l__vigenere_alphabet_seq

% internal function
\cs_new_protected:Nn \vigenere_tabular:n
 {
  \group_begin:
  % set the keys
  \keys_set:nn { vigenere } { #1 }
  % make a sequence from the alphabet
  \seq_set_from_clist:NN \l__vigenere_alphabet_seq \l__vigenere_alphabet_clist
  % set the font and the tabcolsep
  \__vigenere_font:
  \dim_set_eq:NN \tabcolsep \l__vigenere_tabcolsep_dim
  % prepare the table body
  \tl_clear:N \l__vigenere_tablebody_tl
  \prg_replicate:nn { \seq_count:N \l__vigenere_alphabet_seq }
   {
    \tl_put_right:Nx \l__vigenere_tablebody_tl
     {
      \seq_use:Nn \l__vigenere_alphabet_seq { &amp; }
      \exp_not:n { \\ \hline }
     }
    \seq_pop_left:NN \l__vigenere_alphabet_seq \l_tmpa_tl
    \seq_put_right:NV \l__vigenere_alphabet_seq \l_tmpa_tl
   }
  % make the table
  \tabular { | *{\clist_count:N \l__vigenere_alphabet_clist }{ c| } }
  \hline
  \tl_use:N \l__vigenere_tablebody_tl
  \endtabular
  \group_end:
 }
\ExplSyntaxOff

\begin{document}

\printvigeneretabular

\printvigeneretabular[font=\tiny,alphabet={1,2,3,4,5,6,7,8,9,10},tabcolsep=1pt]

\end{document}