Problem: in many cases, the Clojure compiler has enough information about the type of a function argument to statically emit maximally efficient code on the JVM (i.e. without instance? checks, type casts or other forms of dynamic polymorphic dispatch). We are currently unable to do so in Clojure, which pushes developers with strong performance requirements to use some unidiomatic or convoluted workarounds.
Proposal is simply to allow functions to take type-hinted overloads of function arguments, e.g.
([^double x] (Math/floor x))
([^float x] (Math/floor (double x)))
([^String s] (count s)))
An "Object" version of the code with the correct arity will always be emitted, which will maintain compatibility with the IFn interface and ensure that the function can still be used in dynamic / interactive contexts. If the "Object" version is not explicitly provided, then it will be generated to use instance? checks that subsequently delegate to the appropriate typed version of the function (or throw an InvalidArgumentException if no match is found).
Matching rules would be the same as Java.
This will be backwards compatible with all existing uses of defn. In particular, it should extend / enhance / supercede the existing handling of primitive functions.
In the future, this technique might be used alongside core.typed to ensure that the most efficient function version is chosen based on type inference.