(third ..), (fourth ..), (nth 5 ..)

24 views
Skip to first unread message

jon

unread,
Apr 5, 2008, 10:08:32 PM4/5/08
to Clojure
Hi.. I may be having a "blonde moment" and missing an obvious
function?
In RT.java there's third() and fourth(), but nothing corresponding in
boot.clj
(fourth() is only used once, but third() gets used a bit).
As a newbie I did wonder why only (first) and (second) were included
(other lisps have up to tenth, right?).. and just assumed there was a
succinct alternative -- now I'm wondering what that is. Assuming no
prior knowledge, it seems intuitive (and visually parsable) to me that
in lieu of (or better than) (third) to (tenth) there would be a
function (nth 7 xs) that would return the 7th item of anything seq-
able or nil if out-of-bounds (no Exception throwing). It would
logically be one-based if it's to follow on after (first) and
(second).

In clojure, (nth ..) and (get ..) aren't far from matching that, but:
(get ..) doesn't work on sequences and has other semantics for maps,
is zero-based and has its arguments in the other order.
(nth ..) doesn't work on maps, can throw exceptions on non-sequences,
is zero-based and has its arguments in the other order.

So is there scope for a new standard library function for this
intuitive usage?
(don't know what to call it, because to my mind 'nth' is the ideal
name and the current 'nth' is more like an 'idx' (or 'ith') as is
tries to look up values by their "index").
Thanks, Jon.

---------------------------------------------------------
(def xs [1 2 3 4 5 6 7 8 9])

user=> (nth (seq xs) (dec 7))
7
user=> (first (nthrest xs (dec 7)))
7
user=> (first (drop (dec 7) xs))
7
user=> ((zipmap (iterate inc 1) xs) 7)
7
user=> (let [[_ _ _ _ _ _ x] (seq xs)] x) ; I like this one :)
7

Stuart Sierra

unread,
Apr 5, 2008, 11:32:07 PM4/5/08
to Clojure
On Apr 5, 10:08 pm, jon <superuser...@googlemail.com> wrote:
> So is there scope for a new standard library function for this
> intuitive usage?
> (don't know what to call it, because to my mind 'nth' is the ideal
> name and the current 'nth' is more like an 'idx' (or 'ith') as is
> tries to look up values by their "index").

It always bothered me in Common Lisp that
(nth 1 list) == (second list)
but I guess it's traditional.

You could define something like this:

(defn ord
"Returns the 'nth' (one-based) item in the
sequence, nil if it does not exist. 'ord'
is short for 'ordinal'."
[n coll]
(first (nthrest coll (dec n))))

user=> (def xs [1 2 3])
#<Var: user/xs>
user=> (ord 1 xs)
1
user=> (ord 2 xs)
2
user=> (ord 3 xs)
3
user=> (ord 4 xs)
nil
user=> (ord 0 xs) ; nonsensical but works for now
1

I also noticed that this doesn't raise an exception:
user=> (nth nil 2)
nil

-Stuart

Rich Hickey

unread,
Apr 6, 2008, 10:15:49 AM4/6/08
to Clojure
Thank goodness it doesn't (and first/rest etc) or speculative
destructuring (and many other Clojure idioms) would be impossible.

It is a CL influence to have semantics for many functions when applied
to nil rather than generate errors, and, once one knows the rules, it
can be used to great effect to produce elegant code.

I've mentioned this before:

http://people.cs.uchicago.edu/~wiseman/humor/large-programs.html

Rich
Reply all
Reply to author
Forward
0 new messages