Calling method in Java that mutates passed argument

10 views
Skip to first unread message

Steffen Glückselig

unread,
Feb 20, 2009, 1:59:59 PM2/20/09
to Clojure
I was trying to use Clojure to verify the behavior some method in
Java.

Namely I wanted to quickly check whether Collections.sort does the
sorting I need.

So I came up with:

(let [list '("1" "KB" "K6" "2" "EÜ" "EZ" "ES")]
(do
(java.util.Collections/sort list)
list))

But since Collections/sort mutates the list in place I cannot get a
result.

Is there a way in Clojure to get at the result of operations like
these?



Steffen

Jason Wolfe

unread,
Feb 20, 2009, 2:18:32 PM2/20/09
to Clojure
Hmmm, that is weird ... I would expect the sort to throw an exception,
but it seems to complete happily. (If you try it with a vector
instead of a list, it will error).

Anyway, the typical way to do this would be to convert your Clojure
data structure to a mutable Java type first, then convert it back. In
this case, perhaps

(let [l (ArrayList. '(1 9 6 3 8 9))]
(Collections/sort l)
(seq l))

The nice thing about this is that there is only one real conversion --
the creation of the ArrayList. Calling "seq" on the result just
creates a view on the ArrayList, which is now effectively immutable
since after you exit the "let" nobody has write access to it.

-Jason

Jeffrey Straszheim

unread,
Feb 20, 2009, 2:19:04 PM2/20/09
to clo...@googlegroups.com
The Clojure collections are immutable, which is their entire reason for existing.  However, there is nothing stopping you from creating a plain old Java collection in Clojure.

(let [list (ArrayList. '("Fred" "mary" "sue")]
  (do
    (java.util.Collections/sort list)
    list))

Should work.

Chouser

unread,
Feb 20, 2009, 2:30:33 PM2/20/09
to clo...@googlegroups.com
On Fri, Feb 20, 2009 at 1:59 PM, Steffen Glückselig <goo...@gungfu.de> wrote:
>

With a little poking around I found what you need. First, what args
is sort actually taking?

user=> (use '[clojure.contrib.repl-utils :only (show)])
nil

user=> (show java.util.Collections "sort")
=== public java.util.Collections ===
[11] static checkedSortedMap : SortedMap (SortedMap,Class,Class)
[12] static checkedSortedSet : SortedSet (SortedSet,Class)
[40] static sort : void (List)
[41] static sort : void (List,Comparator)
[47] static synchronizedSortedMap : SortedMap (SortedMap)
[48] static synchronizedSortedSet : SortedSet (SortedSet)
[53] static unmodifiableSortedMap : SortedMap (SortedMap)
[54] static unmodifiableSortedSet : SortedSet (SortedSet)
nil

user=> (show java.util.Collections 40)
#<Method public static void java.util.Collections.sort(java.util.List)>

Ah, a java.util.List. But I seem to recall that being an interface,
so I need something else that's concrete and mutable, but implements
List. I seem to recall something called ArrayList...

user=> (isa? java.util.ArrayList java.util.List)
true

Good enough, now how do you make one?

user=> (show java.util.ArrayList)
=== public java.util.ArrayList ===
[ 0] <init> ()
[ 1] <init> (Collection)
[ 2] <init> (int)
[..snip..]

So it can take a collection, like a clojure vector:

user=> (def lst (java.util.ArrayList. ["1" "KB" "K6" "2" "EÜ" "EZ" "ES"]))
#'user/lst

And finally, the sort:

user=> (java.util.Collections/sort lst)
nil

Bleh... not functional at all, are we? Oh well:

user=> lst
#<ArrayList [1, 2, ES, EZ, EÜ, K6, KB]>

And there you go.

--Chouser

Rich Hickey

unread,
Feb 20, 2009, 3:18:01 PM2/20/09
to Clojure


On Feb 20, 2:18 pm, Jason Wolfe <jawo...@berkeley.edu> wrote:
> Hmmm, that is weird ... I would expect the sort to throw an exception,
> but it seems to complete happily. (If you try it with a vector
> instead of a list, it will error).
>

Fixed in svn 1298 - thanks for the report.

Rich
Reply all
Reply to author
Forward
0 new messages