[racket-dev] take,drop,split-at, etc -- and argument order, again

From: Eli Barzilay (eli at barzilay.org)
Date: Sat Mar 9 10:28:15 EST 2013

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!

Posted on the dev mailing list.