On Thu Jul 16 14:40:14 2015, PEVANS wrote:
Show quoted text> Consider perhaps
>
> head_before { COND } LIST # excludes terminating element
> head_upto { COND } LIST # includes terminating element
>
> tail_since { COND } LIST # includes initiating element
> tail_after { COND } LIST # excludes initiating element
Thinking further, it's still a bit too subtle whether or not these names imply that the terminating element is included or not, so I think maybe it's best to be really clear in the names:
head_upto { COND } LIST
head_upto_including { COND } LIST
tail_since_including { COND } LIST
tail_since { COND } LIST
As well as head/tail there's also what Haskell calls "drop" - I.e. scan over the headmost items until some matching item, and then take the remaining elements after that. For completeness there'd also be the analogous one, scanning backwards over the list and returning the headmost items "before" the matching one, though in practice that would be rare enough people can play games with reverse() on the dropping function. The dropping one still needs a name though.
drop_upto + drop_upto_including ?
but then does "including" drop that item, and thus its return value "excludes" it? Naming after a negative action like that doesn't help the "including" prefix. Maybe better to suggest it's the rest of the list, perhaps
rest_since + rest_since_including
but then we're using 'since' to still refer to a scan from the beginning of the list here, rather than from the end, which is what it means for 'tail'.
Additional thoughts: rather than having pairs of inclusive+exclusive functions, it might be nicer if the test function could return a three-way value of "keep going"/"stop but include this element"/"stop and exclude this element", but there doesn't seem to be a convenient "natural" value in perl that could represent this. It isn't the undef/defined-but-false/true of e.g. wantarray, nor is it the -ve/zero/+ve of <=>.
Finally, it might be the case that since List::Util now adds head() and tail() as functions and there is a feature to add first_index and rfirst_index, some of these behaviours can be expressed using these new functions if the LIST is available in a variable:
head_upto { COND } LIST == head( first_index { COND } LIST, LIST)
head_upto_including { COND } LIST == head(1 + first_index { COND } LIST, LIST)
rest_since { COND } LIST == tail(-1 - first_index { COND } LIST, LIST)
rest_since_including { COND } LIST == tail( - first_index { COND } LIST, LIST)
tail_since_including { COND } LIST == tail( - rfirst_index { COND } LIST, LIST)
tail_since { COND } LIST == tail(-1 - rfirst_index { COND } LIST, LIST)
The tail variants are a little more subtle due to the negative number indexing feature of tail(); plus all cases still require that temporary variable.
If added here though, they do suggest adding a rest() function to List::Util acting like
rest(INDEX, LIST) === LIST[INDEX .. $#LIST]
--
Paul Evans