How to "name" a byte array class/type for multi-method dispatch?

530 views
Skip to first unread message

Frank Siebenlist

unread,
Mar 24, 2010, 2:02:28 PM3/24/10
to Clojure, Frank Siebenlist
The following repl session shows my attempt to dispatch a multimethod on "type":

...
user> (defmulti mm type)
#'user/mm
user> (type "a")
java.lang.String
user> (defmethod mm java.lang.String [s] (println "string"))
#<MultiFn clojure.lang.MultiFn@41e3a0ec>
user> (mm "a")
string
nil
user> (type (.getBytes "a"))
[B
user> (defmethod mm [B [b] (println "bytes"))
; Evaluation aborted.
user> (def ba-type (type (.getBytes "a")))
#'user/ba-type
user> (defmethod mm ba-type [b] (println "bytes"))
#<MultiFn clojure.lang.MultiFn@41e3a0ec>
user> (mm (.getBytes "a"))
bytes
nil
user>
...

It works easily for the string, but for a native java byte array, type (or class) gives me back this "[B", which I'm unable to use as a dispatch value for the defmethod.
I can, however, assign the value to a reference and us that to dispatch on successfully - but that feels like a hack.

Is there a way to express the byte array type in a different way than "[B" that would work?

Thanks, Frank.


ataggart

unread,
Mar 24, 2010, 6:03:50 PM3/24/10
to Clojure
For type-hinting #^"[B" works, but for obtaining and passing the class
to defmethod, the best I can come up with is (Class/forName "[B").

On Mar 24, 11:02 am, Frank Siebenlist <frank.siebenl...@gmail.com>
wrote:

Frank Siebenlist

unread,
Mar 24, 2010, 6:39:47 PM3/24/10
to clo...@googlegroups.com, Frank Siebenlist
Right - not very different from the (class (byte-array 1)) that I came up with in the mean time... all not very clojuresque.

-FS.

> --
> 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
>
> To unsubscribe from this group, send email to clojure+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.

ataggart

unread,
Mar 24, 2010, 9:54:47 PM3/24/10
to Clojure
The java version would look like:
Class c = byte[].class;

But since the clojure way to obtain a class is simply to use its name
literal, e.g.:
user=> (type String)
java.lang.Class
the only way to get the class of an array would involve either a
function call or a change to the reader. And java doesn't make it
easy since all array-class stuff, such as Class.isArray(), is native
code. The best I've come up with is:
user=>
(defn #^Class array-class
"Returns the Class of an array of component type c"
[#^Class c]
(when c (class (java.lang.reflect.Array/newInstance c 0))))
user=> (array-class String)
[Ljava.lang.String;
which appears faster than using Class/forName with a created string.
But since one *can* type a literal byte array class in java, I'd
imagine there's some way to implement this with bytecode magic, rather
than going through java.lang.reflect.Array.

On Mar 24, 3:39 pm, Frank Siebenlist <frank.siebenl...@gmail.com>
wrote:

ataggart

unread,
Mar 24, 2010, 10:27:57 PM3/24/10
to Clojure
Ok, after looking into how clojure resolves class literal symbols, it
turns out it is already smart enough to recognize symbol names that
start with "["; the problem is it's a pain to type such symbols into
code.

Your code can work this way:
user=> (defmethod mm (resolve (symbol "[B")) [b] (println "bytes"))
#<MultiFn clojure.lang.MultiFn@6ee3849c>
user=> (mm (.getBytes "a"))
bytes
nil

In the end though, it turns out to be just another way to call (Class/
forName "[B").

Frank Siebenlist

unread,
Mar 24, 2010, 10:49:59 PM3/24/10
to clo...@googlegroups.com, Frank Siebenlist
Nice research - so is it then the reader that doesn't allow us to escape the "[B" such that we can write it such that it can be interpreted as a symbol [B ?

-Frank.

ataggart

unread,
Mar 24, 2010, 11:37:02 PM3/24/10
to Clojure
Nope, though thinking further on it, I'm really not a fan of people
having to know java's class name encoding scheme for arrays.
Personally, I'd prefer writing (array-class String), or have some
clojure-specific syntax to denote an array of a class (though some
would say clojure has enough syntax as-is).

On Mar 24, 7:49 pm, Frank Siebenlist <frank.siebenl...@gmail.com>

Reply all
Reply to author
Forward
0 new messages