To be clear, I'm perfectly ready to keep the old interface. I was mostly concentrating on the implementation, and some functions appeared more natural than the existing ones in that context. > > Then there is the issue of l3candidates, which I have not > > re-programmed yet, as well as the quicksort defined in l3prg.dtx > > one step at a time i'd say. I meant that there are some \seq_from_clist and \clist_from_seq functions in l3candidates which will have to be rewritten, and a \seq_quicksort, or something like that, which I haven't looked at. I'm _definitely not_ rewriting l3prg.dtx :). > > - I don't like the fact that \seq_(g)pop return its value locally, so > > I changed which functions are provided there to \seq_pop_with:Nn <seq> > > {<assignment code>}. > > Im not sure here. > > - the general design principle is that all functions that get values from > some data structure *always* store them *locally* in a variable. > > - the data structure itself could be local or global and a manipulation of > the structure could then be local or global too. Is there any example of data structure other than seq or prop? > On the other hand popping + using the value is a quite common usage, so to > have to always write > > \seq_pop_left_with:Nn \l_foo_seq {\tl_set:Nn \l_bar_tl} > > instead of > > \seq_pop:NN \l_foo_seq \l_bar_tl I see your point. Then perhaps renaming \seq_pop_left_with:Nn to \seq_pop_left_do:Nn, and leaving \seq_pop:NN as it is could make sense. Then if we just want to remove the left-most element and apply some function onto it, we can do \seq_pop_left_do:Nn \l_foo_seq {\foo:nn {<arg1>}} and to get a global return value we would do \seq_pop_left_do:Nn \l_foo_seq {\tl_gset:Nn \g_foo_tl} Basically, I'm just making an auxiliary function available to the user. > now having written that I noticed that it isn't true, this is violated in > l3prop where there are gget functions for key values, so hmmm ... still I > tend towards the rule above I guess I think that you are right: there should be a \..._pop_left:NN, which does something consistent between the various data structures. Choosing local return values is as good as anything. > not sure what you mean here. clearly if you loop directly over a sequence > then using mapping is preferable, but often when you do one element at a time the > actions are complex so that they don't quite fit into a mapping function I guess I was just stating the obvious to a TeX programmer: getting one element in the seq takes a time linear in the length of the seq. I.e., it is not much faster than mapping on every element. In terms of efficiency, it is _much_ better to do \seq_map_inline:Nn \l_foo_seq { <complicated code using #1 spanning several lines> } than \bool_until_do:nn {\seq_if_empty_p:N \l_foo_seq} { \seq_pop_left:NN \l_foo_seq \l_foo_tl <same complicated code using \l_foo_tl> } although the latter is probably clearer. > > - I expect the pop_right functions to be much faster for large > > sequences than simply storing the elements one by one. > > ??? Implementation detail. The naive way of doing things on the right-most element of the sequence is to remove elements one by one, and store them in a scratch register, until the last element is reached. That will be quadratic, and it turned out to be particularly tricky to get the linear version right. Anyways, unimportant here. > > - I'd like every "..._map_function:NN" to become > > "..._map_function:Nn", i.e. allow mapping several tokens at a time. It > > Personally I don't find this very intuitive; if you map a function you map a > function name and that would mean N. Besides you would lose the ability to > map a constructed function name ie "c" though that is something you would seldom > need I guess. My initial application was to be able to map a function with two arguments on two seq <a> and <b> at the same time. First I zipped the two seq into one seq whose item each have the form {<a_i>}{<b_i>}. Then I could map _expandably_ \seq_map_function:Nn \l_foo_zipped_seq {\exp_after:wN \foo_func:nn \use:n} where the \use:n unbraces its argument. Not a very convincing use. But Lars Madsen's examples with { \foo_func:nn {arg1} } are better. > I would rather do > > \cs_new:Npn \map_func:n #1 {<some tokens> \func:n #1} > ...map_function:NN \l_foo_seq \map_func:n That would be better as ...map_inline:Nn \l_foo_seq {<some tokens> \func:n {#1}} The key here is expandability. When it is not needed, map_inline:Nn and map_variable:NNn fit the bill nicely. The best might be to leave both the :NN and :Nn variants, synonyms of each other, hence taking little of TeX's memory. There is also the question of whether removing an elements once/all copies of it should be named as in l3clist or l3tl: \clist_remove_element:Nn \tl_remove_all_in:Nn \tl_remove_in:Nn I'd go for the tl version. Regards, -- Bruno