Will Robertson skrev: > Hi Lars, > > On 06/08/2009, at 10:52 PM, Lars Hellström wrote: > >> The xdoc2l3 preprocessing is more about doing things to an argument >> after you've grabbed it, than about changing the conditions under >> which it is grabbed. > > [...] > >> and refer to the scratch variables \l_tmpa_tl, \l_tmpb_tl, etc. where >> the values are needed, we can have #1, #2, etc. be these cleaned-up >> values throughout the body. > > [...] > >> Just bear in mind that what seems esoteric today may be standard >> practice for the programming technique you'll learn tomorrow. > > Sorry for the slow reply; your idea finally clicked in my brain a few > days ago and the idea has kinda stuck. Well, I've been slow on reading as well, mostly for weather-related reasons. > So let's say we want to define \foo that takes an argument but has to > sanitise it in some way before processing it: > > \DeclareDocumentCommand \foo {m} { > \my_sanitise:Nn \l_sanitised_tl {#1} > \foo_internal:V \l_sanitised_tl > } > \cs_new:Nn \my_sanitise:Nn { > % do something with #1 and save it in \l_sanitised_tl The #1 of \foo, yes. > } > \cs_new:Nn \foo_internal:n { > % do whatever \foo is supposed to do with #1 Which may make use of #1 in several places, some of which may be smack in the middle of a complex call of some other user-level command, whose implementation we know very little about... > } > \cs_generate_variant:Nn \foo_internal:n {V} I thought O was the appropriate variant for expanding a token list control sequence? > From my not in-depth understanding of xdoc2l3, this can be dramatically > simplified (I imagine) with something like > > \DeclareDocumentCommand \foo { ?{\my_sanitise:n} } { > % do whatever \foo is supposed to do with #1 > } Yes. The way I coded it, you would have to declare something as a "processor", and then be free to combine said processor with other processors in the specification of an argument; the reason for this was partly that processors would leave their result "up ahead" as a mandatory argument that the next processor could operate on. For example, the processing of an (x,y) argument (xparse "c") would probably be in two steps: (x,y) grab and handle delimiters {x,y} split at comma {{x}{y}} The most general-purpose processor I defined was "x", but unfortunately the in-source description of that seems to be wrong (copied from "t" and only partially rewritten). I believe I gave a more user-oriented description in a posting to LATEX-L, however. > Just to confirm -- have I got this thing sort of right? :) > > With this sort of example, it seems pretty clear that this can save a > lot of code that's just shuffling arguments around. (In the same way > that manual optional argument processing consists of lots of > intermediate functions that simply pass their arguments around.) Exactly! I might add, that with some processing at argument-grabbing time, it also becomes interesting to do some argument checking and error reporting there: it is easier to understand _where_ a mandatory coordinate argument was expected if you get an error message where the token stream is cut off at precisely the position where the coordinate was expected. Lars Hellström PS: Just to be clear, I don't particularly like (x,y) arguments, but in this posting they made a good example.