I've been perusing Stu Halloway's beta of "Programming Clojure" and I came across the following example:
(defn describe-class [c] {:name (.getName c) :final (java.lang.reflect.Modifier/isFinal (.getModifiers c))}) As demonstrated by the *warn-on-reflection* flag, Clojure is unable to determine a type for c, therefore all (or rather, almost all) of the calls made upon it must be handled reflectively. The performance "solution" suggested in the book is just to annotate the c parameter with a type: (defn describe-class [#^Class c] ...) This is a perfectly valid solution, but it seems a little ugly to me. The thought that I had is perhaps the Clojure compiler could actually infer this type automatically. Languages like ML and Haskell have been doing this for decades. Traditionally, Hindley-Milner isn't applied to object-oriented languages (or rather, languages which deal with uncontrolled OO constructs), but from what I understand, most of the reasoning behind this does not apply to Clojure. For example, Clojure doesn't have structural or parametric types because of its dynamic nature. There would be no *need* to infer any type parameters on calls out to Java, so the type system could be treated as nominal. The algorithm I'm thinking of would be something like this: * Maintain a multi-map of method and field names to classes (this could be done incrementally based on what classes the compiler knows are in scope) * For each parameter with an unfixed type: * Traverse the FnExpr AST and find all Java member access to that parameter * For each access, obtain a set of possible classes from the scope multi-map * At each step, intersect the previous set of possible classes with the subsequent one (think: a fold) * Final set can be optimized by choosing the most-specific type (eliminating the inheritance case) * If the final set has size of 1, then the type has been inferred and can be used to avoid reflection * If the set has size 0, then fallback on reflection * If the set has size >1, either fallback on reflection or get more sophisticated Improvements on this could be added to the >1 case where the second pass could look for methods of a given name *and* a specific arity. Subsequent passes could also incorporate inferred types for the method parameters. It's not a complete inference algorithm, but it doesn't have to be. There's nothing stopping Clojure from falling back on reflection for unfixed types. The whole logic behind this dance is to avoid reflection as much as possible, producing a fairly serious optimization in Java-interop without requiring those ugly type annotations. I briefly looked at implementing this myself, but Clojure's compiler code is...well, it's a compiler. :-) At first glance, I couldn't even figure out where to place the appropriate hooks to kick off this process. A better question though is: has this been tried/considered before? What are your overall thoughts with regards to this? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---