On Thu, Nov 6, 2008 at 9:34 AM, Will Robertson <[log in to unmask]> wrote: > Taking a look at how \let:NN and friends are implemented strongly tempted my > "clean up" urge. Rather than delay it for the "big future refactor" that's > going to happen at some stage, I thought it small enough to address > immediately. [...] > Here's the offending code: > > \def_protected_long_new:Npn \let:NN #1{\let:NwN #1=~} > \def_new:Npn\let:cN #1 {\exp_after:NN\let:NN\cs:w#1\cs_end:} > \def_new:Npn\let:Nc{\exp_args:NNc\let:NN} > \def_new:Npn\let:cc{\exp_args:Ncc\let:NN} > > Yielding concerns: > - Why is \let:NN long? \let:NN\par\GAL_normal_par: General remark: Almost all of the kernel ought to be "long". You just never know what is input at the user level. I had one case where the code would grab the first three characters (excluding \) of a csname, then form a new to use in some tests. All went well until the the csname to be tested was \parens. Same situation with some \AtBeginDocument redefinitions that wound up containing \par. \exp_args:No, which was used at some point in this process, did not like that one bit. So it was made long. In summary, the kernel should not prevent user lever input - that's for user level macros to do that. Currently, there is a long way to go in the kernel in this respect (no pun intented) and it makes me think that perhaps it would be better to change the logic of the naming. The common case ought to be the the easiest to type so I'd propose \def:Npn = \tex_long:D \tex_def:D \def_restricted:Npn = \tex_def:D tlp's should of course still use the restricted version as they take no arguments. > - Shouldn't the variants be protected as well? See below. > - I'd be surprised if \let:cN *really* needs to be hand-optimised, given > the definition of \exp_args:Nc : It doesn't need it, it's just the matter of how early on the expansion module is defined and utilized. > I'd like to propose this change: > > \def_protected_new:Npn \let:NN #1 { \let:NwN #1=~ } > \def_protected_new:Npn \let:cN { \exp_args:Nc \let:NN } > \def_protected_new:Npn \let:Nc { \exp_args:NNc \let:NN } > \def_protected_new:Npn \let:cc { \exp_args:Ncc \let:NN } > > Any comments? Question is if you want to have the non-NN variants to be protected. If you do, then funny things can happen expansion-wise if you have active characters in the c-argument. Case in question: An active character appears in the c-argument (say, a colon in a reference label). If such a character uses the \ifincsname feature to turn normal in critical places, this will not kick in if \let:cN is protected and you can wind up with some strange things in place. If the functions are non-protected, they will perform argument expansion as usual and then stop once \let:NN is met. For the reasons listed above, I think the current implementation is correct. -- Morten