Created
December 6, 2009 19:31
-
-
Save hutch/250364 to your computer and use it in GitHub Desktop.
Question, answered, on how to dispatch a multimethod in Clojure based on a deftype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ a link to the whole thread: http://tr.im/GRyQ ] | |
Hi, | |
I'm new to Clojure, not new to lisp (CL and scheme), and having a | |
thoroughly good time. I've been having a go at the new deftype stuff | |
and using a clone of the new branch from the git repository (up-to- | |
date as of this message being posted). So far everything I've tried | |
has worked very nicely, except for one thing. | |
I've put three files up as a gist: http://gist.github.com/250364 that | |
illustrate (I hope) my question. | |
So. I've defined a type 'Foo -- inevitably foo, sorry -- and I want to | |
define a very simple multimethod that dispatches on the class of its | |
single argument. I understand that defmethod needs a fully ns | |
qualified name to dispatch properly. I was hoping there was a shorter | |
way of doing this than play.foo.Foo, maybe using some sort of alias- | |
based technique like those in Stuary Halloway's book (p233 and | |
thereabout). | |
I've got six variations in there, and I know full well that most of | |
these should not work, but I put them in anyway. | |
I believe that I'm AOT compiling everything (I'm compiling the ./src/ | |
play/foo.clj file and the class files are on disk, so...) | |
It turns out that dispatching on play.foo.Foo is the only way that | |
works. I was hoping ::f/Foo or f/Foo would work too (maybe my alias is | |
wrong??). Especially since, with aliasing in the user namespace, I can | |
create a play.foo.Foo using f/Foo | |
Obviously, I have a workaround, but that's going to get ugly fast with | |
a real namespace name, not to mention making re-naming the namespace | |
harder than it should be. | |
If someone could help me out I'd appreciate it. | |
Thanks, | |
Bob |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Requires the clojure new branch because it is using the new deftype | |
(ns play.foo) | |
(alias 'f 'play.foo) | |
(deftype Foo [a] | |
:as this | |
clojure.lang.IPersistentMap) | |
(defmulti foo-print class) | |
(defmethod foo-print :default [thing] (println (format "don't know how to foo-print a %s" (class thing)))) | |
(defmethod foo-print ::f/Foo [foo] (println (format "::f/Foo %s" (.toString foo)))) | |
(defmethod foo-print ::f.Foo [foo] (println (format "::f.Foo %s" (.toString foo)))) | |
(defmethod foo-print f/Foo [foo] (println (format "f/Foo %s" (.toString foo)))) | |
(defmethod foo-print ::Foo [foo] (println (format "::FOO %s" (.toString foo)))) | |
(defmethod foo-print ::play.foo/Foo [foo] (println (format "::play.foo/Foo %s" (.toString foo)))) | |
(defmethod foo-print play.foo/Foo [foo] (println (format "play.foo/Foo %s" (.toString foo)))) | |
(defmethod foo-print play.foo.Foo [foo] (println (format "play.foo.Foo %s" (.toString foo)))) | |
(foo-print (Foo "foo in foo.clj")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (load "go-foo") | |
play.foo.Foo play.foo.Foo@127028e5 | |
make them... | |
x1: play.foo.Foo@a5995ff4 | |
x2: play.foo.Foo@a5995e35 | |
x3: null | |
x4: null | |
x5: play.foo.Foo@a5995cef | |
foo-print them... | |
play.foo.Foo play.foo.Foo@a5995ff4 | |
play.foo.Foo play.foo.Foo@a5995e35 | |
don't know how to foo-print a null | |
don't know how to foo-print a null | |
play.foo.Foo play.foo.Foo@a5995cef |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; this file is really src/play/foo.clj (I changed the name to keep the gist happy) | |
(ns play.foo) | |
(deftype Foo [a] | |
:as this | |
clojure.lang.IPersistentMap) | |
; The issue is resolved here. The answer (thanks to Meikel Brandmeyer on the Clojure mailing list) is to use | |
; 'type' as the dispatch function rather than 'class'. | |
(defmulti foo-print type) | |
(defmethod foo-print String [s] (println (format "String '%s'" s))) | |
(defmethod foo-print :default [thing] (println (format "don't know how to foo-print a %s" (class thing)))) | |
(defmethod foo-print ::Foo [foo] (println (format "::FOO %s" (.toString foo)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(compile 'play.foo) | |
(use 'play.foo) | |
(alias 'f 'play.foo) | |
(println "\nmake them...") | |
; x1, x2, and x5 will succeed with play.foo.Foo the result of (class) | |
; x3 and x4 will both be nil (with no exceptions) | |
(def x1 (play.foo/Foo 1)) | |
(def x2 (Foo 2)) | |
(def x3 (::f/Foo 3)) ;; nil | |
(def x4 (::f.Foo 4)) ;; nil | |
(def x5 (f/Foo 5)) | |
(println (format "x1: %s" x1)) | |
(println (format "x2: %s" x2)) | |
(println (format "x3: %s" x3)) | |
(println (format "x4: %s" x4)) | |
(println (format "x5: %s" x5)) | |
(println "\nfoo-print them...") | |
(foo-print x1) | |
(foo-print x2) | |
(foo-print x3) | |
(foo-print x4) | |
(foo-print x5) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment