Hello, David,
Well, gen-class certainly supports creating static methods with type
hints and overloaded arities. An example using gen-class as part of ns:
(ns gen-class-test.StaticTest
(:gen-class :methods [^:static [foo [ints int] String]
^:static [foo [longs long] String]
^:static [foo [chars char] String]
^:static [foo [shorts short] String]
^:static [foo [booleans boolean] String]
^:static [foo [floats float] String]
^:static [foo [doubles double] String]
^:static [foo ["[Ljava.lang.Object;" Object] String]
^:static [foo ["[Ljava.lang.String;" String] String]
^:static [foo ["[Ljava.lang.String;" int] String]
^:static [foo [boolean] String]
^:static [foo [char] String]
^:static [foo [short] String]
^:static [foo [int] String]
^:static [foo [long] String]
^:static [foo [float] String]
^:static [foo [double] String]
^:static [foo [Object] String]
^:static [foo [String] String]]
:main false))
This will generate a class with the following signature:
public class gen_class_test.StaticTest extends java.lang.Object{
public static {};
public gen_class_test.StaticTest();
public java.lang.Object clone();
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public static java.lang.String foo(int[], int);
public static java.lang.String foo(long[], long);
public static java.lang.String foo(char[], char);
public static java.lang.String foo(short[], short);
public static java.lang.String foo(boolean[], boolean);
public static java.lang.String foo(float[], float);
public static java.lang.String foo(double[], double);
public static java.lang.String foo(java.lang.Object[], java.lang.Object);
public static java.lang.String foo(java.lang.String[], java.lang.String);
public static java.lang.String foo(java.lang.String[], int);
public static java.lang.String foo(boolean);
public static java.lang.String foo(char);
public static java.lang.String foo(short);
public static java.lang.String foo(int);
public static java.lang.String foo(long);
public static java.lang.String foo(float);
public static java.lang.String foo(double);
public static java.lang.String foo(java.lang.Object);
public static java.lang.String foo(java.lang.String);
}
Now, when it comes to what this class is doing, it is calling the
Clojure function -foo with the arguments from the static method
invocation. In particular:
1. All primitive arguments will be boxed.
2. The number of arguments for -foo must match the number of arguments
for the static method invocation. For multiple arities, you can have
a variadic function or a function with multiple arities.
3. Unfortunately, there is no way to call a different function for each
arity/type.
However, you can make -foo a multimethod. The following works as an
implementation for the above:
(defmulti -foo
(fn [& args]
(apply vector (map class args))))
; one-arg invocations
(defmethod -foo [Boolean] [_] "boolean")
(defmethod -foo [Character] [_] "char")
(defmethod -foo [Short] [_] "short")
(defmethod -foo [Integer] [_] "int")
(defmethod -foo [Long] [_] "long")
(defmethod -foo [Float] [_] "float")
(defmethod -foo [Double] [_] "double")
(defmethod -foo [Object] [_] "Object")
(defmethod -foo [String] [_] "String")
; two-arg invocations
(defmethod -foo [(class (boolean-array 0)) Boolean] [_ _] "booleans")
(defmethod -foo [(class (char-array 0)) Character] [_ _] "chars")
(defmethod -foo [(class (short-array 0)) Short] [_ _] "shorts")
(defmethod -foo [(class (int-array 0)) Integer] [_ _] "ints")
(defmethod -foo [(class (long-array 0)) Long] [_ _] "longs")
(defmethod -foo [(class (float-array 0)) Float] [_ _] "floats")
(defmethod -foo [(class (double-array 0)) Double] [_ _] "doubles")
(defmethod -foo [(class (into-array [""])) String] [_ _] "Strings")
(defmethod -foo [(class (to-array [])) Object] [_ _] "Objects")
(defmethod -foo [(class (into-array [""])) Integer] [_ _] "Strings + int")
Perhaps there is a better way to do it, but this is the best I could
come up with. I hope it helps.
Sincerely,
Daniel