LATEX-L Archives

Mailing list for the LaTeX3 project


Options: Use Classic View

Use Proportional Font
Show Text Part by Default
Condense Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Content-Type: text/plain; charset=windows-1252
Date: Fri, 12 Jul 2013 17:56:40 +0200
Reply-To: Mailing list for the LaTeX3 project <[log in to unmask]>
MIME-Version: 1.0
Message-ID: <[log in to unmask]>
Content-Transfer-Encoding: 8bit
Sender: Mailing list for the LaTeX3 project <[log in to unmask]>
From: Michiel Helvensteijn <[log in to unmask]>
Parts/Attachments: text/plain (74 lines)
Hello all,

It occurs to me, as I write my new expl3 datastructure, that the
current convention for specifying and propagating 'global'ness of a
function (namely, by inserting a 'g' in the name somewhere) leads to
either code duplication or to the definition of boilerplace auxiliary
functions. It is also too easy to get copy-paste-happy and forget to
add a 'g' in an implementation somewhere.

I just wanted to suggest an alternative approach. It is compatible
with all existing code and might make implementations more readable.

Wherever functions now exist in pairs `\prop_put:Nnn` and
`\prop_gput:Nnn` I suggest the addition of a function
`\prop_sput:NNnn`, where 'global'ness is passed as the first parameter
(s stands for scoped). That is the one that would be directly
implemented —in terms of other s-functions. The other two are then
implemented in terms of it.

The choice of tokens for the first parameter are not important for
this idea. It might be one of `\pref_global:D` or `\tex_relax:D` to be
used directly at the lowest level, but I'm not yet familiar enough
with the l3 core to make a proper decision there.

To encapsulate that detail and to save typing, I furthermore suggest
that functions like `\cs_new_protected(_nopar)_scoped:NpnNN` are made
available. To demonstrate their use, I compare the current `\prop_put`
definitions with the new ones I propose:

-------------------- Current code --------------------
\cs_new_protected_nopar:Npn \prop_put:Nnn
  { \@@_put:NNNnn \tl_set:Nx \tl_put_right:Nx }
\cs_new_protected_nopar:Npn \prop_gput:Nnn
  { \@@_put:NNNnn \tl_gset:Nx \tl_gput_right:Nx }
\cs_new_protected:Npn \@@_put:NNNnn #1#2#3#4#5
    \tl_set:Nn \l_@@_internal_tl
      { \s_@@ \tl_to_str:n {#4} \s_@@ { \exp_not:n {#5} } }
    \@@_split:NnTF #3 {#4}
      { #1 #3 { \exp_not:n {##1} \l_@@_internal_tl \exp_not:n {##3} } }
      { #2 #3 { \l_@@_internal_tl } }
-------------------- Proposed code --------------------
\cs_new_protected_nopar_scoped:NpnNN \prop_sput:NNnn #1#2#3#4
    \tl_set:Nn \l_@@_internal_tl
      { \s_@@ \tl_to_str:n {#3} \s_@@ { \exp_not:n {#4} } }
    \@@_split:NnTF #2 {#3}
      { \tl_sset:NNx #1 #2 { \exp_not:n {##1} \l_@@_internal_tl
\exp_not:n {##3} } }
      { \tl_sput_right:NNx #1 #2 { \l_@@_internal_tl } }
  \prop_put:Nnn  \prop_gput:Nnn

Some of the above (like the naming-scheme and the argument specifiers)
might even be automatically derived, but for the purpose of this
example I didn't want to go that far.

Note that `\tl_sset:NNx` and `\tl_sput_right:NNx` are now spelled out
in their proper place, so the reader doesn't have to go back and forth
to understand what's going on. There is no need for auxiliary
functions and errors of omission are unlikely, since omitting #1 would
lead to an error.

I understand it's a radical change. But it could be introduced
gradually. In any case I'd be interested in discussing the pros and
cons of the approach.