drop-while for noobs

30 views
Skip to first unread message

Alan

unread,
Aug 9, 2010, 3:09:59 PM8/9/10
to Clojure
Hi all, I'm new to the group; I have some experience with both CL and
Java, though it's been a while for each. Anyway I really like Clojure
as a way of combining the best parts of the two languages, but I'm
still getting the hang of it and there are often things that confuse
me.

For example, I wanted to define a ring function, which takes as input
N objects, and returns a hash table mapping object N to object N+1
(mod N). I intended to use this to describe a compass object:
(ring :w :n :e :s) should result in {:w :n, :n :e, :e :s, :s :w}.

I could have done this with basic recursion or as a list comprehension
using (for), (count), and (rem), but it seemed there must be a more
elegant solution with lazy sequences, like maybe combining cycle and
map to gloss over the N==0 wraparound issue. What I came up with was
frankly a monstrosity; I don't have the source with me at work, but it
looked roughly like:

(defn ring [& elts]
(apply assoc {}
(map #(list
%1
(fnext (drop-while
(comp (partial or

(partial not= %1)

nil))
(cycle elts))
elts))))

Since then I've realized I could have used nth and map-indexed to get
a less ugly result, but I was baffled by the awkwardness of drop-
while: is there a reason it demands nil or not-nil, instead of
treating false and nil as logical false? Converting false to nil was a
real bear (and retyping this from memory I'm pretty sure my syntax for
comp/partial/or is wrong somewhere), and in my experience clojure is
too clever make me do crap like this; what am I missing?

Wilson MacGyver

unread,
Aug 9, 2010, 3:41:06 PM8/9/10
to clo...@googlegroups.com
you can do this using partition.

let's assume I first define a

user=> (def a [:w :n :e :s])
#'user/a

user=> (partition 2 1 (conj a (first a)))
((:w :n) (:n :e) (:e :s) (:s :w))

gives you the pairs you need.

then you just need to turn it into hash-map
by doing

(map #(apply hash-map %) (partition 2 1 (conj a (first a))))

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

--
Omnem crede diem tibi diluxisse supremum.

Armando Blancas

unread,
Aug 9, 2010, 4:01:26 PM8/9/10
to Clojure
It works with booleans:

user=> (drop-while neg? [-3 -2 -1 0 1 2 3 ])
(0 1 2 3)
user=> (class (neg? -5))
java.lang.Boolean

jv-l...@tx.rr.com

unread,
Aug 9, 2010, 4:10:56 PM8/9/10
to Clojure
On Aug 9, 2:09 pm, Alan <a...@malloys.org> wrote:
> Hi all, I'm new to the group

Welcome!

> I wanted to define a ring function, which takes as input
> N objects, and returns a hash table mapping object N to object N+1
> (mod N). I intended to use this to describe a compass object:
> (ring :w :n :e :s) should result in {:w :n, :n :e, :e :s, :s :w}.

Here's a quick way that seems pretty close to your original:

user> (def x [:w :n :e :s])
#'user/x

user> (zipmap x (rest (cycle x)))
{:s :w, :e :s, :n :e, :w :n}

- Jeff

Alan

unread,
Aug 9, 2010, 3:36:40 PM8/9/10
to Clojure
Also sorry the indentation is so awful. How do I get Google to let me
compose/edit in a fixed-width font?

Alan

unread,
Aug 9, 2010, 4:16:06 PM8/9/10
to Clojure
Weird. I wonder if I was using an outdated version of Clojure or (more
likely) assumed from (doc drop-while) that it wouldn't handle false
the way I wanted. When doc says "not nil" should I assume it means
"neither nil nor false", or should the doc for drop-while be updated?

user=> (doc drop-while)
-------------------------
clojure.core/drop-while
([pred coll])
Returns a lazy sequence of the items in coll starting from the first
item for which (pred item) returns nil.

Armando Blancas

unread,
Aug 10, 2010, 12:33:42 AM8/10/10
to Clojure
> When doc says "not nil" should I assume it means
> "neither nil nor false"

Nope, false won't be taken as nil; in boolean expressions nil
evaluates to false. drop-while's doc mentions only nil but since it's
the predicate's return value it should be clear enough, I think.

Michael Wood

unread,
Aug 10, 2010, 4:32:33 AM8/10/10
to clo...@googlegroups.com
On 9 August 2010 22:16, Alan <al...@malloys.org> wrote:
> Weird. I wonder if I was using an outdated version of Clojure or (more
> likely) assumed from (doc drop-while) that it wouldn't handle false
> the way I wanted. When doc says "not nil" should I assume it means
> "neither nil nor false", or should the doc for drop-while be updated?
>
> user=> (doc drop-while)
> -------------------------
> clojure.core/drop-while
> ([pred coll])
>  Returns a lazy sequence of the items in coll starting from the first
>  item for which (pred item) returns nil.

I think the docs should be fixed to refer to "logical false" like
other parts of the documentation, instead of "nil".

e.g.:

(find-doc "logical false")
[...]
clojure.core/when-not
([test & body])
Macro
Evaluates test. If logical false, evaluates body in an implicit do.
nil

--
Michael Wood <esio...@gmail.com>

Reply all
Reply to author
Forward
0 new messages