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. Best, -- www.mhelvens.net