[racket] Where Are List/Container Operations Headed?

From: Eli Barzilay (eli at barzilay.org)
Date: Sun May 15 20:56:44 EDT 2011

5 hours ago, Deren Dohoda wrote:
> Please forgive my ignorance on this matter.
> (cons value list)
> --- Well, makes intuitive sense to put the container second here.
> (map proc list)
> --- Reads like English.
> (foldl proc init list)
> --- Hmm, I guess the association with "map" makes this understandable.
> (take list 2)
> (drop list 2)
> --- OK, what? Why not (take 2 list)?

There are many reasons for such decisions.  First, as you've noted,
there is a reason to have the container last.  But similarly, there's
a better reason to have it first *in this case*, because it's using an
index into the list -- making it more like `list-ref'.

But `take' is a good function to consider here, because it gets even
more interesting...  Haskell has a `take' function that consumes the
number first and then the list -- and in that case there is yet
another reason for it.  The thing is that Haskell has only unary
functions[*], and if you apply a function on one argument, then it's a
partial application that results in a closure that waits for the
second one.  When you consider this, you realize that something like
(λ (l) (take l n)) is generally more useful than (λ (n) (take l n)),
and having the number as the first argument in Haskell allows you to
write something like (take 3) which behaves like the first.

When I implemented the lazy language, I followed Haskell's order,
mostly just to make it more slightly more compatible with Haskell
code, but at the same time there was a `take' that was implemented in
SRFI-1 that took the list first (for the above reason: it's a big API,
so it's a uniform decision in that context).  At some point we added
`take' into the core language (rather into `racket/list'), and the
natural choice was to use SRFI-1 -- which results in a discrepancy
with the lazy language's `take'...

So yes, there is some mixture of ideas, and finding the right path can
be frustrating -- but certainly the decisions are rarely random.
Slightly more specifically, I suspect that the order for `take' will
make more sense unless you're coming from Haskell (or using the lazy
racket language).

([*] As a side note, I find it infinitely amusing that many Haskellers
are unaware of that...)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.