Kotlin Vertx Type Mismatch found Future<Unit> expected Handler<AsyncResult<Void>> - kotlin

I thought that in Kotlin, Unit was equivalent to Void. With Vert.x Service Discovery, it is not possible to pass a Future<Unit> to unpublish(String id, Handler<AsyncResult<Void>> resultHandler) (gives a type mismatch) yet it will accept Future<Void> without any problem. Why is this and is there a solution or will I just have to live with using Void?

Unit is not equivalent to Void, it is equivalent to void in kotlin.
In java, void is a keyword, but Void is a class. so the code below can't be compiled:
fun foo():Void{/**need return a Void instance exactly**/}
fun bar():Void{ return Unit; }
// ^--- type mismatch error
java applies the same rule, for example:
Void canNotBeCompiled(){
// must return a Void instance exactly.
}
Void foo(){
return Void.TYPE;
}
Void nil(){
return null;
}
Finally the Unit documentation also says:
The type with only one value: the Unit object. This type corresponds to the void type in Java.

Related

How to resolve "Not enough information to infer type variable" when one type variable not inferrable AND using wildcard on the other?

Trying to convert some Java code to Kotlin, the Java code includes a call to a library method TableUtils.dropTable which is implemented in Java. The Java method signature of this method is
public static <T, ID> int dropTable(ConnectionSource connectionSource, Class<T> dataClass, boolean ignoreErrors) throws SQLException
When calling the method from Java it compiles fine even though the type variable ID is not known. For example:
public void method(ConnectionSource connectionSource, Class<? extends IRecordObject> clazz) {
try {
TableUtils.dropTable(connectionSource, clazz, true); // this compiles fine
} catch (SQLException e) {
e.printStackTrace();
}
}
After converting to Kotlin, the corresponding function fails to compile because the type variable ID cannot be inferred:
fun method(connectionSource: ConnectionSource?, clazz: Class<out IRecordObject>) {
try {
TableUtils.dropTable(connectionSource, clazz, true) // compile error: "Not enough information to infer type variable ID"
} catch (e: SQLException) {
e.printStackTrace()
}
}
I don't know how I can explicitly specify the type variables, as one of them would be a wildcard, and you aren't allowed to use wildcards in type variables when calling functions. For example:
TableUtils.dropTable<out IRecordObject,Long>(connectionSource, clazz, true) // this also fails to compile, "Projections are not allowed on type arguments of functions and properties"
So how can I specify the type variable ID here to allow the code to compile in Kotlin?
The type ID is unused in the function signature, so it doesn't matter what it is. For the Kotlin version, you can literally put any type there to make the error go away. Whichever type you use will have no effect on the compiled code because of type erasure. You can use an underscore to allow T to be inferred.
fun method(connectionSource: ConnectionSource?, clazz: Class<out IRecordObject>) {
try {
TableUtils.dropTable<_, Unit>(connectionSource, clazz, true)
} catch (e: SQLException) {
e.printStackTrace()
}
}
I actually don't know how you can write out the type and make it work instead of using inference. The only way I can think to make it work is to make this function generic so you can use an invariant Class type:
fun <T: IRecordObject> method(clazz: Class<T>) {
JavaFoo.dropTable<T, Unit>(clazz, true)
}
I think the Java method signature should have used Class<? extends T> for more proper flexibility and probably should have omitted ID since it is effectively useless.

JUnit 5 and Arguments.of() with functions

Writing a JUnit 5 parameterized test and need to pass functions to the test using Arguments.of(), but there are 2 compile errors that I don't know how to fix. Any help would be appreciated.
The method of(Object...) in the type Arguments is not applicable for the arguments (boolean, String::length)
The target type of this expression must be a functional interface
public static Stream<Arguments> some() {
return Stream.of(Arguments.of(true, String::length));
}
#ParameterizedTest
#MethodSource
public <T> void some(final T input, final Function<String, Integer> length) {
}
The following works as expected.
public void sample() {
some(true, String::length);
}
Wrap the arguments in a helper method
Similar to the answer "wrap it in a class", but possibly less intrusive, is to use a helper method to pass the functional interface as a java.lang.Object.
For example, the first raw method reference, Math::ciel, in this parameterized test:
#ParameterizedTest
#MethodSource("testCases")
void shouldExerciseMethod(Function<Double, Double> method, Double expected) {
assertEquals(expected, method.apply(1.5d), 1.0E-8d);
}
static Stream<Arguments> testCases() {
return Stream.of(Arguments.of(Math::ceil, 2.0d),
Arguments.of(Math::floor, 1.0d));
}
causes this compilation error:
java: method of in interface org.junit.jupiter.params.provider.Arguments cannot be applied to given types;
required: java.lang.Object[]
found: Math::ceil,double
reason: varargs mismatch; java.lang.Object is not a functional interface
which you can get around by passing the arguments through a helper method:
static <T, U> Arguments args(Function<T, U> method, U expected) {
return Arguments.of(method, expected);
}
so:
static Stream<Arguments> testCases() {
return Stream.of(args(Math::ceil, 2.0d),
args(Math::floor, 1.0d));
}
My attempts to make the idiom more general using varargs failed with variations on the same error, so I have ended up overloading it whenever I need another signature.
The function needs to be wrapped in a class.
public static class P {
private final Function<String, Integer> mFunction;
public P(final Function<String, Integer> function) {
mFunction = function;
}
public Function<String, Integer> function() {
return mFunction;
}
}
public static Stream<Arguments> some() {
return Stream.of(Arguments.of(3, "abc", new P(String::length)));
}
#ParameterizedTest
#MethodSource
public <T> void some(final int expect, final String input, final P p) {
assertEquals(expect, p.function().apply(input));
}
I liked #adrian-redgers solution, but I think overloading a method for each signature needed is a bit overkill.
You only really need to convert the functional interface to an object. So the solution I implemented was:
/**
* Helps to use {#link org.junit.jupiter.params.provider.Arguments#of(Object...)}, as functional
* interfaces cannot be converted into an object directly.
*/
public class ArgumentsWrapper {
private ArgumentsWrapper() {
throw new IllegalStateException(
ArgumentsWrapper.class + " util class cannot be instantiated");
}
public static <T, U> Function<T, U> wrap(Function<T, U> function) {
return function;
}
}
Then, it can be used as:
public static Stream<Arguments> testMapAlarmTypeConfigWithLanguage() {
return Stream.of(
// Statically imported ArgumentsWrapper#wrap
Arguments.of(null, wrap(AlarmTypeConfig::getNameInEnglish)),
Arguments.of("en-us", wrap(AlarmTypeConfig::getNameInEnglish)),
Arguments.of("es-es", wrap(AlarmTypeConfig::getNameInSpanish)));
}

Kotlin: Is local function passed to inlined functions as parameter inlined?

When passing a lambda or anonymous function to inlined functions as a parameter, it's quite simple, the code is pasted to the calling position, but when passing a local function as a parameter, the result seems different(shown as below). I wonder if it's inlined? Why or why not?
For example:
inline fun foo(arg: () -> Int): Int {
return arg()
}
fun bar(): Int {
return 0
}
fun main(args: Array<String>) {
foo(::bar)
}
And decompiled Java code:
public final class InlinedFuncKt {
public static final int foo(#NotNull Function0 arg) {
Intrinsics.checkParameterIsNotNull(arg, "arg");
return ((Number)arg.invoke()).intValue();
}
public static final int bar() {
return 0;
}
public static final void main(#NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
bar();
}
}
bar() is not declared to be inlined. So why would you expect it to be inlined?!
In other words: it would be simply wrong that the signature of method A affects (implicitly) the signature of another method B.
Your idea would (somehow) affect "semantics" of bar() - just because you used bar() as argument to another method call.
As you can in the decompiled code, kotlin does not inline bar in your case, but it does inline it if it is declared as inline fun bar().
The rule is that lambdas are inlined when they are passed to an inlined function. In all other cases like passing a function reference or a lambda object, no inlining is done.

Call Kotlin inline function from Java

Exceptions.kt:
#Suppress("NOTHING_TO_INLINE")
inline fun generateStyleNotCorrectException(key: String, value: String) =
AOPException(key + " = " + value)
In kotlin:
fun inKotlin(key: String, value: String) {
throw generateStyleNotCorrectException(key, value) }
It works in kotlin and the function is inlined.
But when used in Java code, It just cannot be inlined,
and still a normal static method call (seen from the decompiled contents).
Something like this:
public static final void inJava(String key, String value) throws AOPException {
throw ExceptionsKt.generateStyleNotCorrectException(key, value);
// when decompiled, it has the same contents as before , not the inlined contents.
}
The inlining that's done by the Kotlin compiler is not supported for Java files, since the Java compiler is unaware of this transformation (see this answer about why reified generics do not work from Java at all).
As for other use cases of inlining (most commonly when passing in a lambda as a parameter), as you've already discovered, the bytecode includes a public static method so that the inline function can be still called from Java. In this case, however, no inlining occurs.
Yes, u can do it
In Kotlin file:
Builder.sendEvent { event ->
YandexMetrica.reportEvent(event)
}
.build();
In Java file:
Builder.sendEvent(new Function1<String, Unit>() {
#Override
public Unit invoke(String event) {
Log.i("TEST", event);
return null;
}
})
.build();

Why do I need to use as Callable on my closure for submitting to executors?

Why does the following groovy code pass?
Executor executor = Executors.newFixedThreadPool(1)
assert executor.submit({"some value"}).get() == null
assert executor.submit({"some value"} as Callable).get() == "some value"
When {} instanceof Closure implements GroovyCallable extends Callable ?
What black magic is the as keyword providing?
Well, it looks like a feature of groovy compiler to prefer Runnable interface in Closure before Callable to avoid Ambiguous method overloading call.
Please take a look at the discussions https://issues.apache.org/jira/browse/GROOVY-4311 and https://issues.apache.org/jira/browse/GROOVY-3295
To get some perspective on the problem, you can take a look at the similar Java code which will fail to compile:
class MyClosure implements Runnable, Callable<String> {
#Override public String call() throws Exception {
return "some value";
}
#Override public void run() {
}
}
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new MyClosure());