field initialization with `val myVal: (long: Long) -> Unit)` what does it means? - java

I'm new to using Kotlin, so far seems amazing, however I don't quite understand what's going on here:
class MyCallbackListener(val clickListener: (myLong: Long) -> Unit){
fun onClick(myObject: MyObjectClass) = clickListener(myObject.longField)
}
So, here's what I do understand:
I am creating a class that contains a method which receives a MyObjectClass
When I call onClick(someObject) I am actually indicating to call clickListener(someObject.longField)
I should use this callback method like this:
MyCallbackListener{ myLong ->
//Do Something with mylong, which will be myObject.longField }
Unit is a Kotlin type vaguely like void
However, I don't really understand the val clickListener: (myLong: Long) -> Unit part.
It looks like I am declaring a final field for the class which will be of type (myLong: Long) -> Unit but that does not make a lot of sense.
Why or how is this enabling me to pass in the lambda for the listener?
What's exactly going on here?
I come from a Java background so it could help if you could provide equivalent code, but that is not strictly necessary

What you're looking at is a function type.
(myLong: Long) -> Unit is the type of a function that takes a single Long parameter, and returns nothing useful.  — In fact, the myLong parameter name is irrelevant here; it could be written more simply as (Long) -> Unit.
(Yes, Kotlin's Unit type is roughly equivalent to Java's void: it's what functions return if they don't have anything useful to return.  That's not to be confused with Nothing, which is the return type for functions that never return at all, e.g. because they have an infinite loop or always throw an exception.)
So the caller has to provide a function for that parameter.  You'd typically give a lambda, e.g.:
MyCallbackListener({ myLong -> println(myLong) })
(Note that that could be written more simply as MyCallbackListener(){ println(it) }, since if the last parameter is a lamdba it can be passed outside the brackets, and it is a keyword which can be used for the single parameter of a lambda.)
But you could instead give a function reference, e.g.:
MyCallbackListener(SomeClass::printLong)
Or an anonymous function, e.g.:
MyCallbackListener(fun(myLong: Long) { println(myLong) })
Or even an instance of an object implementing that function.
This doesn't have an exact equivalent in Java, because Java doesn't have first-class functions; it simply implements lambdas as instances of a functional interface (one with a Single Abstract Method) that the compiler infers.  (First-class functions are more powerful and more general, though this example doesn't really demonstrate that.)

You understand everything correctly. In Kotlin you can pass functions/lambdas as objects and (myLong: Long) -> Unit is a declaration of a function type. Constructor of MyCallbackListener receives a function/lambda that has a single parameter of Long type and which does not return anything. Then, when you initialize an object of MyCallbackListener, you pass this lambda as shown in your example.
If you are more familiar to Java then (myLong: Long) -> Unit is something similar to Function<Long, Void> or Consumer<Long>.

Related

Can you explain why the first unwrapped method reference does not compile?

In this example, passing a method reference to Stream.of does not work but once it's wrapped it works. I can't quite get my head around why this is. Isn't the method reference equivalent to the functional interface?
public class A {
String a() {
return "";
}
void b() {
Stream.of(this::a); // won't compile
Stream.of(wrap(this::a)); // will compile
}
static <T> Supplier<T> wrap(Supplier<T> f) {
return f;
}
}
Stream.of has the following signature:
public static<T> Stream<T> of(T t)
The following example will compile because you explicitly providing a type information for T.
Stream<Supplier<String>> a = Stream.of(this::a);
The first example Stream.of(this::a); equivalent to:
Object a = this::a;
where Object is not a functional interface and will not compile.
Providing with a functional interface this example compiles:
Runnable a = this::a;
Stream.of(a);
In the second example, wrap provides a functional interface Supplier
Stream.of(T) expects an Object and you pass to it a method reference in the first statement. But an Object parameter is not a functional interface, so it cannot accept a method reference or a lambda that is not specifically typed.
With lambda, it would produce also an error : Stream.of(()->this.a()).
A simpler example could be Stream.of(()-> "foo") that will just not compile.
But if you type the method reference or the lambda it works :
Stream.of((Supplier<String>) this::a)
or
Stream.of((Supplier<String>) () -> this.a())
In the working statement you pass to Stream.of(T) a parameter that is a Supplier<String>. That refers to a functional interface but that is typed as in the previous working examples, so it is valid as parameter that expects an Object.
this::a is contextless and could mean different things. You need to provide some context to help the compiler to figure out what you actually meant by this::a.
Stream.<Supplier<String>>of(this::a);
Though, that Stream<Supplier<String>> doesn't seem to be what you wanted. If you need a Stream<String>, use Stream.generate: no extra type information needed since the method takes a Supplier<T> (no ambiguity here).
Stream.generate(this::a);
On a side note, both statements expect you to save their results into variables. Defining variables of the right type often facilitates resolving such issues.
Stream<Supplier<String>> s1 = Stream.of(this::a);
Stream<String> s2 = Stream.generate(this::a);
All credit to #J-Alex and #Holger for their precious comments.

Generic type <T> parameter BEFORE the function name

What is the usage of the <T> type parameter before the function name in Kotlin?
Example:
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1]
this[index1] = this[index2]
this[index2] = tmp
}
Referring to the first <T> above.
I've tried to look through the Kotlin docs regarding generics as well as the Java Generics however they mostly just touch on the 2nd <T> not the first.
It is used to indicate that generics are used and not some type T is referenced.
Have a look at this completly valid example
fun <String> MutableList<String>.swap(index1: Int, index2: Int)
Now this can be called on any MutableList<*> and not only MutableList<String>. If you would not write <String> after the fun keyword, how would kotlin know that in fact you were referencing a generic and not kotlin.String?
The same goes for the example you've shown. The <> after the fun just introduces a new generic parameter, else kotlin would complain that it wouldn't know the type T
(Here's another approach.)
Consider a normal, non-generic function:
fun myFun(a: Int, b: String) {
// …use a and b…
}
What are a and b?  They don't mean anything yet.  They're simply saying ‘When you call this function, you must pass these values’.  You'd expect the body of the function to refer to them in some way; that's when they get used.
Now consider a generic function:
fun <T, U> myFun(/* …use T and U… */) {
// …
}
It's the same with T and U.  Those are parameters, too — type parameters.  Just like with value parameters, declaring type parameters doesn't mean anything by itself, but gives placeholders for types that must be passed (explicitly or inferred) when calling the function.  (The <…> declaration also gives a place to specify any constraints or variance, e.g. <T : Number> or <out T>.)  And you'd normally use those type parameters later on — in this case, in the rest of the function signature.
To add to Lino's answer, imagine this definition has invisible braces after type parameter declaration:
fun <T> \*{*\ MutableList<T>.swap(index1: Int, index2: Int) {...} \*}*\
So it's properly lexically scoped. If that <T> went after function name, you'd lose this property, complicate the parser, and only make code less readable for humans.
It would also be hard to remember to put <T> before name for extension functions, but after it for member functions. Bad enough that it has to be done for classes!
Scala does put [T] after the method name, but that's because it has a very different syntax for the feature corresponding to extension methods. Scala 3 will go for the complicated parser approach, probably because Kotlin-like syntax would not fit with any other syntax.
The first <T> introduces a generic type parameter to the function, as you know. The second <T> it's part of MutableList<T>, the receiver of the extension function that your code is defining: an extension function is defined as
fun [GenericTypeList] ReceiverType.FunctionName([ParametersList]) [: ReturnType] { ... }
as you can see in the official documentation I linked above. The receiver type is the type you add the extension function to (extension functions are syntactic sugar for something like (Java's) static method invocations). In you example you're adding an extension function to generic MutableList<T>, so defining the receiver you provides a generic type specification (which requires the generic type parameter represented by the first <T>).
I hope my explanation can bel clear and exaustive for you!
"T" representing generic type/class you passing to the function. Your question is about the "T" at returning of the function. So it suppose return the type/class based on what you passing in to function.

Why can't the var keyword in Java be assigned a lambda expression?

It is allowed to assign var in Java 10 with a string like:
var foo = "boo";
While it is not allowed to assign it with a lambda expression such as:
var predicateVar = apple -> apple.getColor().equals("red");
Why can't it infer a lambda or method reference type when it can infer the rest like String, ArrayList, user class, etc.?
This has nothing to do with var. It has to do with whether a lambda has a standalone type. The way var works is that it computes the standalone type of the initializer on the RHS, and infers that.
Since their introduction in Java 8, lambda expressions and method references have no standalone type -- they require a target type, which must be a functional interface.
If you try:
Object o = (String s) -> s.length();
you also get a type error, because the compiler has no idea what functional interface you intend to convert the lambda to.
Asking for inference with var just makes it harder, but since the easier question can't be answered, the harder one cannot either.
Note that you could provide a target type by other means (such as a cast) and then it would work:
var x = (Predicate<String>) s -> s.isEmpty();
because now the RHS has a standalone type. But you are better off providing the target type by giving x a manifest type.
From the Local-Variable Type Inference JEP:
The inference process, substantially, just gives the variable the type of its initializer expression. Some subtleties:
The initializer has no target type (because we haven't inferred it yet). Poly expressions that require such a type, like lambdas, method references, and array initializers, will trigger an error.
Because a lambda expression by itself does not have a type, it can not be inferred for var.
... Similarly, a default rule could be set.
Sure, you can come up with a way to work around this limitation. Why the developers made the decision not to do that is really up to speculation, unless someone who was part of the decision making can answer here. (Update: answered here.) If you're interested anyway, you could ask about it on one of the openjdk mailing lists: http://mail.openjdk.java.net/mailman/listinfo
If I were to guess, they probably didn't want to tie lambda inference in the context of var to a specific set of functional interface types, which would exclude any third party functional interface types. A better solution would be to infer a generic function type (i.e. (Apple) -> boolean) that can than be converted to a compatible functional interface type. But the JVM does not have such function types, and the decision to not implement them was already made during the project that created lambda expressions. Again if you're interested in concrete reasons, ask the devs.
To everyone who is saying this is impossible, undesired, or unwanted, I just want to point out that Scala can infer the lambda's type by specifying only the argument type:
val predicateVar = (apple: Apple) => apple.getColor().equals("red")
And in Haskell, because getColor would be a standalone function not attached to an object, and because it does full Hindley-Milner inference, you don't need to specify even the argument type:
predicateVar = \apple -> getColor apple == "red"
This is extraordinarily handy, because it's not the simple types that are annoying for programmers to explicitly specify, it's the more complex ones.
In other words, it's not a feature in Java 10. It's a limitation of their implementation and previous design choices.
As several people have already mentioned, what type should var infer and why should it?
The statement:
var predicateVar = apple -> apple.getColor().equals("red");
is ambiguous and there is no valid reason why the compiler should pick Function<Apple, Boolean> over Predicate<Apple> or vice versa assuming the apple identifier in the lambda represents an Apple isntance.
Another reason is that a lambda in its own doesn't have a speakable type hence there is no way for the compiler to infer it.
Also, "if this was possible" imagine the overhead as the compiler would have to go through all the functional interfaces and determine which functional interface is the most appropriate each time you assign a lambda to a var variable.
To answer this we have to go into details and understand what a lambda is and how it works.
First we should understand what a lambda is:
A lambda expression always implements a functional interface, so that when you have to supply a functional interface like Runnable, instead of having to create a whole new class that implements the interface, you can just use the lambda syntax to create a method that the functional interface requires. Keep in mind though that the lambda still has the type of the functional interface that it is implementing.
With that in mind, lets take this a step further:
This works great as in the case of Runnable, I can just create a new thread like this new Thread(()->{//put code to run here}); instead of creating a whole new object to implement the functional interface. This works since the compiler knows that Thread() takes an object of type Runnable, so it knows what type the lambda expression has to be.
However, in a case of assigning a lambda to a local variable, the compiler has no clue what functional interface this lambda is implementing so it can't infer what type var should be. Since maybe it's implementing a functional interface the user created or maybe it's the runnable interface, there is just no way to know.
This is why lambdas do not work with the var keyword.
Because that is a non-feature:
This treatment would be restricted to local variables with initializers, indexes in the enhanced for-loop, and locals declared in a traditional for-loop; it would not be available for method formals, constructor formals, method return types, fields, catch formals, or any other kind of variable declaration.
http://openjdk.java.net/jeps/286
In a nutshell, the types of a var and lambda expression both need inference, but in opposite way. The type of a var is inferred by the initializer:
var a = new Apple();
The type of a lambda expression is set by the context. The type expected by the context is called the target type, and is usually inferred by the declaration e.g.
// Variable assignment
Function<Integer, Integer> l = (n) -> 2 * n;
// Method argument
List<Integer> map(List<Integer> list, Function<Integer, Integer> fn){
//...
}
map(List.of(1, 2, 3), (n) -> 2 * n);
// Method return
Function<Integer, Integer> foo(boolean flag){
//...
return (n) -> 2 * n;
}
So when a var and lambda expression are used together, the type of the former needs to be inferred by the latter while the type of the latter needs to be inferred by the former.
var a = (n) -> 2 * n;
The root of this dilemma is Java cannot decide the type of a lambda expression uniquely, which is further caused by Java's nominal instead of structural type system. That is, two types with identical structures but different names are not deemed as the same, e.g.
class A{
public int count;
int value(){
return count;
}
}
class B{
public int count;
int value(){
return count;
}
}
Function<Integer, Boolean>
Predicate<Integer>

Java: implicit type conversion, or implicit toString() invocation

In my Java application I created methods that return Either<String, T> objects.
This is because in some places I invoke these methods as the parameter of (3rd party) methods that expect a String parameter as input.
While in other places I invoke these methods as the parameter of (3rd party) methods that expect some other parameter type (T) as input.
So depending on the place where I invoke the methods that I created, the code looks like:
their.thirdPartyExpectsString(my.calculateEither().getLeft());
their.thirdPartyExpectsString(my.calculateEither() + "");
or
their.thirdPartyExpectsDouble(my.calculateEither().getRight());
(I defined Either.toString() as Either.getLeft()).
Pay attention, I cannot change the 3rd party code (anyway not without bytecode manipulation), and I would like to keep my design in which I return Either from my methods.
Is there a way to simplify my code and make it look like
their.thirdPartyExpectsString(my.calculateEither());
their.thirdPartyExpectsDouble(my.calculateEither());
I.e., not having to add the getLeft()/getRight() or + "" all the time?
Actually, it does not bother me much if I will have to do
their.thirdPartyExpectsDouble(my.calculateEither().getRight());
because I don't have to do it often. But I would like to get rid of the need to call getLeft() or + "" when my.calculateEither() returns a Left (a String).
Given an either, it's not hard to see if it represents Right or Left, simply by checking which side has a null.
But the problem is with the type conversion, i.e. the compilation error when thirdPartyExpectsString() expects a String but gets an Either.
I was able to catch the return value of my.calculateEither() by AspectJ but I could not see a way how to use something like #AfterReturning advice to make the compiler understand that I want to return my.calculateEither().getLeft(), i.e a String....
Any ideas?
Add the following method to your implementation of the Either class:
#SuppressWarnings("unchecked")
public <T> T whichever() {
return (T) (isLeft() ? getLeft() : getRight());
}
Note that I'm purposefully ignoring the warning about the unchecked cast, and indeed will cause a ClassCastException if you use it in a place where the external API you interface with expects a left value but you invoke it on an Either instance which contains a right value. This method will do an implicit cast based on where you use it. It will cast to a T type where you pass it to another method which expects an argument of type T or you try to assign the method return value to a variable of type T.
So the following demo code:
Either<String, Double> containsString = Either.<String, Double>left("first");
Either<String, Double> containsDouble = Either.<String, Double>right(2d);
their.expectsString(containsString.whichever());
their.expectsDouble(containsDouble.whichever());
their.expectsDouble(containsString.whichever());
will work well in the first invocation and will cause a ClassCastException in the third invocation, just an one would expect, because we consider it as an illegal use case.
In conclusion, it's nice to know that it will work in all places where the T type to which we are implicitly casting is assignable to the actual value contained by the Either object. Unfortunately, you will only find out at run time, should this not be the case.
Add a helper method. Since you cannot add new methods to their, you have to add a static to a class of your own.
Pseudo-code:
public static void thirdParty(Their their, Either either) {
if (either.isLeft())
their.thirdPartyExpectsString(either.getLeft());
else
their.thirdPartyExpectsDouble(either.getRight());
}
You can now call:
MyHelper.thirdParty(their, my.calculateEither())

Calling private Java methods in Scala

I regularly use the Scala REPL for rapid Java iteration and testing, but sometimes I want to trigger some private behavior of a class, and have to recompile the code in order to make the method visible. I'd like to be able to call private Java methods directly in the REPL, without needing to make code changes.
What I've got so far:
// Calls private Java methods
// We currently define an overload for every n-argument method
// there's probably a way to do this in one method?
def callPrivate(obj: AnyRef, methodName: String) = {
val method = obj.getClass().getDeclaredMethod(methodName)
val returnType = method.getReturnType
method.setAccessible(true)
println("Call .asInstanceOf[%s] to cast" format method.getReturnType.getName)
method.getReturnType.cast(method.invoke(obj))
}
def callPrivate(obj: AnyRef, methodName: String, arg: AnyRef) = {
val method = obj.getClass().getDeclaredMethod(methodName, arg.getClass())
method.setAccessible(true)
method.invoke(obj, arg)
}
Which can be used like:
scala> callPrivate(myObj, "privateMethod", arg).asInstanceOf[ReturnedClass]
But this requires defining a near duplicate method for every n-argument method type (and requires an external cast, but I suspect that's unavoidable). Is there any way to refactor this so that one function can handle any number of arguments?
Note: I'm using Scala 2.9.1, so I'm looking for solutions using Java Reflection. Answers using Scala Reflection are welcome, but don't address my problem directly.
DISCLAIMER: There has been a while since the last time I programmed in Scala and I don't have any kind of Scala environment around to test what I am showing you. So it might have small syntax errors here and there, bear with me. Hope the rest is useful
In theory you could provide our callPrivate method with an extra variable argument that specifies the method parameters:
def callPrivate(obj: AnyRef, methodName: String, parameters:AnyRef*) = {
val parameterTypes = parameters.map(_.getClass())
val method = obj.getClass.getDeclaredMethod(methodName, parameterTypes:_*)
method.setAccessible(true)
method.invoke(obj, parameters:_*)
}
There is a flaw however. This won't work if you have a method somewhere with a signature like this:
public X someMethod(A parameter);
and A is inherited (or implemented) by class B. If you try to invoke your Scala method this way callPrivate(someObject, "someMethod", new B()) it won't work mostly because the getDeclaredMethod lookup will search for someMethod(B) instead of someMethod(A) - even when new B() is of type A too!
So that's a naive implementation. You could potentially get all the valid types of all the method parameters and perform the getDeclaredMethodlookup with all the combinations for them, however there is one more caveat in that direction: You might bump with overloaded methods that accept different combinations of the same set of parameters and you will not know which one to call (i.e. you may have someMethod(A,B) and someMethod(B,A) and you won't be able to know which one should be invoked)
One way avoid that is to force the caller to provide you with tuples instead of raw instances, each tuple has the parameter value and the parameter type to be used. So it is up to the caller to specify which method he want to invoke.
def callPrivateTyped(obj: AnyRef, methodName: String, parameters:(AnyRef,Class[_])*) = {
val parameterValues = parameters.map(_._1)
val parameterTypes = parameters.map(_._2)
val method = obj.getClass.getDeclaredMethod(methodName, parameterTypes:_*)
method.setAccessible(true)
println("Call .asInstanceOf[%s] to cast" format method.getReturnType.getName)
method.invoke(obj, parameterValues:_*)
}
// for convenience
def callPrivate(obj: AnyRef, methodName: String, parameters:AnyRef*) = {
callPrivateTyped(obj, methodName, parameters.map(c => (c, c.getClass)):_*)
}
That should do the trick.
Also, one more thing: Keep in mind that the way you are using getDeclaredMethod will only return methods (with any scope) that are implemented in obj.getClass(), meaning that it won't return any inherited method. I don't know if that is by design, if not you will need to add a recursive lookup over the superclasses of your obj.

Categories

Resources