This is a question about the expressiveness of Clojure vs other languages such as Haskell. The broader issue is solutions to the Expression Problem
This question reached the conclusion that in general Clojure protocols (and multimethods) were less expressive than Haskell typeclasses because protocols dispatched on first argument, and Haskell typeclasses could dispatch on return type. (Now I think this reasoning is really interesting, and have no interest in starting a language war. I'm just interested in clarity of thought).
As part of breaking this reasoning down - my question is - can't we make a Clojure multimethod that dispatches on return type (or type hint). I think we can put the following expression into a Clojure multimethod:
(= java.lang.String (:tag (meta #'my-string)))
where the function is:
(defn ^String my-string []
"hello world")
Edit: The point is that I can run:
(meta #'my-string)
and get the the following result without function evaluation:
{:arglists ([]), :ns #<Namespace push-price.core>, :name my-string, :column 1,
:line 1, :file "/private/var/folders/0l/x6hr0t1j2hvcmm_sqq04vdym0000gn/T/form-
init7576840885484540032.clj", :tag java.lang.String}
ie I have some information about the intended type of my function without evaluating it.
Edit 3 (24 Apr 2014):
Suppose I have the following types: (deftype string-type [])
(deftype int-type [])
Then I have the following functions defined in terms of these types:
(defn #^{:return-type string-type} return-string []
"I am returning a string")
(defn #^{:return-type int-type} return-int []
42)
Now I write a function to dispatch on their return type like so:
(defn return-type-dispatch [fn-arg]
(let [return-type (:return-type (meta fn-arg))]
(cond
(= return-type string-type)
"This function has a return type of the string type"
(= return-type int-type)
"This function has a return type of the integer type"
:else (str "This function has a return type of:" return-type))))
Then I write a macro to run it at compile-time
(defmacro compile-time-type-check-string []
(println (return-type-dispatch #'return-string)))
(compile-time-type-check-string)
Then I test it like so:
lein uberjar
This gives the following result:
$ lein uberjar
Compiling dispatch-type-compile-time.core
This function has a return type of:class dispatch_type_compile_time.core.string-type
...
So I appear to be dispatching on return type.