What is the Clojure way to build

2 views
Skip to first unread message

Michael Harrison (goodmike)

unread,
Jul 20, 2010, 10:44:25 AM7/20/10
to Clojure
I'm working on a project that involves calculating statistical
distance between the elements of a set. This is conceptually like a
distance chart between cities that often appears on a travel map, or
even a child's multiplication table with the numbers 1 - 10 running
across the top and down the left of the table and the products of the
numbers in the middle.

All the sample code I've seen for doing something like this is
imperative: an outer loop running over the whole set of items, and an
inner loop running over the items between the outer loop's item and
the end of the set. The calculated distance between the outer loop's
current item and the inner loop's current item gets stuck in a 2-D
array.

I know it's possible to do something like this by going down to java
interop, but I feel there must be a more appropriately Clojure way to
handle this. I'm not sure how to find it, though. It seems like a math
or statistics problem that must be common enough that there is a right
way to tackle it. Do any of you laziness and FP wizards have
suggestions?

Thanks!
Michael

Mark Rathwell

unread,
Jul 20, 2010, 11:13:13 AM7/20/10
to clo...@googlegroups.com
There are several ways to do it, but one example using list comprehension:

(let [nums [1 2 3]]
  (for [n1 nums]
    (for [n2 nums]
      (* n1 n2))))

=> ((1 2 3) ( 2 4 6) (3 6 9))

 - Mark


--
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

Michael Harrison (goodmike)

unread,
Jul 20, 2010, 11:59:15 AM7/20/10
to Clojure
I've edited the title because I forgot to include a description of
what I'm trying to do in the original post's title.

Mark, thanks for the example.

mh

On Jul 20, 11:13 am, Mark Rathwell <mark.rathw...@gmail.com> wrote:
> There are several ways to do it, but one example using list comprehension:
>
> (let [nums [1 2 3]]
>   (for [n1 nums]
>     (for [n2 nums]
>       (* n1 n2))))
>
> => ((1 2 3) ( 2 4 6) (3 6 9))
>
>  - Mark
>
> On Tue, Jul 20, 2010 at 10:44 AM, Michael Harrison (goodmike) <
>
> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>

Michał Marczyk

unread,
Jul 20, 2010, 7:04:35 PM7/20/10
to clo...@googlegroups.com
A single `for` will suffice:

(let [nums (range 1 4)]
(for [x nums y nums]
(* x y)))

If you wanted to build a map from pairs of elements of the input
collection to the matching values of your distance function, you could
do something like

(into {} (for [x xs y xs] [[x y] (distance x y)]))

You might want to replace [x y] with (hash-set x y) in the likely case
of distance being commutative.

Note also that if you're building the table to avoid recalculating the
distances, you might be better served by memoization; see (doc
memoize) at the REPL.

Sincerely,
Michał

Reply all
Reply to author
Forward
0 new messages