tags:

views:

212

answers:

4

let's try some calls to the "type" function :

user=> (type 10)
java.lang.Integer

user=> (type 10.0)
java.lang.Double

user=> (type :keyword?)
clojure.lang.Keyword

and now with an anonymous function :

user=> (type #(str "wonder" "what" "this" "is"))
user$eval7$fn__8

A) what does this mean "user$eval7$fn__8" ? B) and what type is a function ?

the source for "type" is :

user=> (source type)
(defn type
  "Returns the :type metadata of x, or its Class if none"
  {:added "1.0"}
  [x]
  (or (:type (meta x)) (class x)))
nil

so a function needs to have a specific part of meta data or be a class

checking the meta of an anonymous function yields nada :

user=> (meta #(str "wonder" "what" "this" "is"))
nil

trying a different approach :

user=> (defn woot [] (str "wonder" "what" "this" "is"))
#'user/woot
user=> (meta woot)
{:ns #<Namespace user>, :name woot}

C) seems there is some meta but i figured this is the meta of the symbol "woot", right ?

what about the second half of the "or" :

user=> (class #(str "wonder" "what" "this" "is"))
user$eval31$fn__32

user=> (class woot)
user$woot

what are these : "user$eval31$fn__32" and "user$woot" and where do they come from ?

checking out the "class" function yields:

user=> (source class)
(defn ^Class class
  "Returns the Class of x"
  {:added "1.0"}
  [^Object x] (if (nil? x) x (. x (getClass))))
nil

and further investigating yields :

user=> (.getClass #(str "wonder" "what" "this" "is"))
user$eval38$fn__39

user=> (.getClass woot)
user$woot

i don't get it. D) is this a hashcode : eval38$fn__39 ? E) is this a symbol : woot ?

F) why doesn't a function have a type ? isn't it supposed to be an IFn or something ?

+1  A: 

I am a clojure novice but i am going to be bold. First we have two different meaning for "type" of a function, one, the java interfaces and classes of clojure internals and otoh the type of the function as a programming concept. Taking the second approach the type of a function would be the type of its return value (or its params types and return value type):

1) i guess all functions implements the IFn interface, whatever their current class

2) the class name automatic generated by clojure diffs if the function is anonymous or named, but it seems in both cases are inner classes (tipically theirs names are separated by $ and go from outer classes to inner ones)

3) the type of the returned value can be in the :tag key of function metadata if you annotate it in function definition. F.e. the function class you expose have Class as its returned type cause in its def there is a ^Class before the name.

I am assuming you are familiar with java (or a similar oop lang), sorry if not

jneira
i'm a java developer, so we're ok there :) my question is : why would you assume "the type of a function would be the type of its return value" ? (i mean functions in clojure are first-class objects, so they have a soul of their own :P )
Belun
jum because the distinction between two possible senses of "type of a function". It's clear for me now you talk about the type of the function as the type of the java object in clojure/jvm internals and not the type of signature of the function. Sorry for confusion
jneira
+13  A: 

A function is of type clojure.lang.IFn, which is a Java interface.

Every Clojure function is compiled into a Java class which implements clojure.lang.IFn. The name user$eval7$fn__8 is the "binary class name" of that class, i.e., its internal name in the JVM.

Stuart Sierra
why isn't the type of a function : clojure.lang.IFn ?
Belun
Because when class a implements class b it's type is still a not b.
Hamza Yerlikaya
+2  A: 

Here's the description in the API docs

Returns the :type metadata of x, or its Class if none

What you are seeing ("user$eval7$fn__8") is the name of the internally generated inner class created by Clojure to implement the anonymous function you have defined.

As you may have noticed, Clojure doesn't follow standard Java class naming conventions :-)

Note that the class implements the interface clojure.lang.IFn - this applies to all Clojure functions.

mikera
+5  A: 

Clojure is built on the JVM.

The JVM doesn't support first-class functions, or lambdas, out of the box. Every Clojure function, once it is compiled, becomes its own anonymous class from the perspective of the JVM. Each function is, technically, it's own type.

The class it becomes implements IFn, but when you retrieve it's type, it gives you the name of the anonymous class which is different every time.

levand