[racket-dev] take,drop,split-at, etc -- and argument order, again
Two days ago, Asumu Takikawa wrote:
> We were considering the following set of names:
>
> takef, dropf, takef-right, dropf-right, splitf, splitf-right
I did most of this, and there are three important comments:
1. Name: `splitf' is not right, since it's missing the "-at". I
eventually went with `splitf-at' (since adding the `f' at the end
makes it unreadable).
2. Argument order: I think that it is important to be able to switch
from (for example) `take' to `takef' and the index by a predicate.
For this analogy to work, the order of arguments needs to be the
same for both. Given that `take' etc already exist, it's the new
functions that need to change. This is unfortunate:
0. It goes against `take' in Haskell and in lazy (not new).
1. Clojure joins that other party.
2. It also goes against `member' and `find' where the list is the
second argument, so the "f" similarity between `findf' and
`takef' can be confusing.
Personally, I think that this has been a PITA for such a long time
and I'd prefer seeing `take' etc change to join the winning party.
I think that srfi-1 made a mistake, not just that it chose the path
that ended up being unpopular, because it made an inconsistent
choice with other functionality that it provides.
Regardless of this, if it's uniform interface vs good order, I
prefer going with the uniform interface and the existing bad
order. So I think that I should switch the order, protest myself
silently, and continue.
3. `takef-right' etc. I started implementing these, but maybe they
shouldn't. The following explanation is probably only for people
who are interested in what gets added (ie, Asumu), or maybe if you
like a dead-end puzzle. For the others, it's probably enough to
note that there are no such things in drfi-1/clojure/etc that I
see.
Here's why I think it might be useless:
For just `takef-right', it's possible to do something smart that
scans the list in order, keeping a pointer to the beginning of the
"current good block". This avoids a double scan *but* the payment
is in applying the predicate on all emlements. There might be a
point in that in some cases, but probably in most cases it's best
to apply it in reverse order, get the index, then do the usual
thing.
That's mildly useful in a completely unexciting way, but when it
gets to the other *f-right functions, it gets worse in that the
first approach won't work.
So for all of these, the best that I see is: reverse the list[*],
look for the place where the predicate flips to #f, then use one of
the non-f from-right functions to do the work. So they're all just
a little bit better than a reverese + non-f + reverse combination.
([*] Not a strict reverse, to make these functions work with
improper lists -- which is in-line with other questionable srfi-1
inheritance.)
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!