Can I use a name of the lambda as the parameter passed "outside of parentheses"? - intellij-idea

I can write a lambda expression outside of parenthesis, but I cannot put it there by name. I have tried many ways:
val plus3: (Int,Int,Int)->Int = {a,b,c->a+b+c}
println(apply3(1,2,3){a,b,c->a+b+c}) // OK
println(apply3(1,2,3){plus3}) // Type mismatch. Required: Int, Found: (Int,Int,Int)->Int
println(apply3(1,2,3){(plus3)}) // Type mismatch. Required: Int, Found: (Int,Int,Int)->Int
println(apply3(1,2,3)plus3) // unresolved reference
println(apply3(1,2,3){plus3()}) // value captured in a closure
println(apply3(1,2,3){(plus3)()}) // value captured in a closure
What is the syntax to put a name there (outside of parenthesis)?
I don't know why, but in the documentation there is not a word on the theme. It says we could put lambda there, but not a word about a variable or constant that denotes that lambda.

I don't know why, but in the documentation there is not a word on the theme.
Yes, there is:
In Kotlin, there is a convention that if the last parameter to a function is a function, and you're passing a lambda expression as the corresponding argument, you can specify it outside of parentheses
plus3 is an identifier and not a lambda expression, so you can't specify it outside of parentheses.
The type of plus3 is (Int,Int,Int->Int). The same as of {a,b,c->a+b+c}. Look again at the messages that I am getting from Kotlin compiler.
You mean the error messages when you pass { plus3 }? By Kotlin rules { plus3 } is a lambda which ignores its argument (if any) and returns plus3. So the rule applies, and apply3(1,2,3){plus3} means the same as apply3(1,2,3,{plus3}).
It sees plus3 as Int.
Exactly the opposite: it expects to see an Int as the return value of the lambda and sees plus3 which is (Int,Int,Int) -> Int.
So, the problem here is not of the high philosophical nature, but seems pure syntactic.
That was exactly my point: the rule is purely syntactic, it's applied before the compiler knows anything about type or value of plus3, and so it doesn't know or care whether this value happens to be a lambda.
The rule could instead say
In Kotlin, there is a convention that if the last parameter to a function has a function type, you can specify it outside of parentheses
in which case apply3(1,2,3) plus3 would work. But it doesn't.

Placing a lambda expression outside of a function call's parentheses is the same as placing it inside the parentheses like this:
println(apply3(1, 2, 3, { a, b, c -> a + b + c }))
From here, we can simply assign the lambda to a val (as you have done) which results in:
val plus3: (Int, Int, Int) -> Int = { a, b, c -> a + b + c }
println(apply3(1, 2, 3, plus3))

Related

How to (force) overloading of plus for integers in Kotlin?

I would like to make plus mean something else, than addition. For example, creation of lazy expressions for computational graph. Unfortunately, class extensions cant override member functions. The following code will print 3:
operator fun Int.plus(other: Int) = listOf(this, other)
fun main() {
println( 1 + 2 )
}
Is is possible to force overriding?
No it is not possible. 1 + 2 is lowered into 1.plus(2), and there is a well defined order in how the compiler finds an appropriate plus method. Specification:
If a call is correct, for a callable f with an explicit receiver e
of type T the following sets are analyzed (in the given order):
Non-extension member callables named f of type T;
Extension callables named f, whose receiver type U conforms to type T, in the current scope and its upwards-linked scopes, ordered
by the size of the scope (smallest first), excluding the package
scope;
[...]
[...]
When analyzing these sets, the first set which contains any
applicable callable is picked for c-level partition, which gives us
the resulting overload candidate set.
So the plus method that is declared in Int is always found first, and the search stops there. Any extension you define will be ignored.
Hypothetically, if the built-in Int.plus is an implicitly imported extension function, then your code would have worked! Implicitly imported extensions are #6 on that list :)
My workaround for this situation is to use the "declare functions with almost any name by adding backticks" feature:
infix fun Int.`+`(other: Int) = listOf(this, other)
fun main() {
println( 1 `+` 2 )
}
This wouldn't work for some names that have reserved characters like square brackets, angle brackets, slashes, and dot (not an exhaustive list).

Kotlin: what does annotation (acc: S, T) -> S mean?

I'm very new to Kotlin. I looked at Kotlin's source code and I saw this prototype:
public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S
I understand that operation is a method, 'acc' is one its arguments, 'acc' is of type S and the return value of operation is of type S. However, what does the T inside list of arguments mean?
Where is its arguments?
Naming the function parameters in a function type is optional. The names are only significant for documentation purposes.
What the above says is that reduce expects a function taking an S (the accumulated value) and a T (the current element). They gave the S the name acc, but didn't give the T any name.
(acc: S, T) -> S is a type.
In Kotlin, functions are first-class types.  Some types have a simple name, such as String or Int.  Others need parameters, such as List<URL> or Map<Int, String>.  Function types have even more complicated names, of the form:
        (params) -> returnType
So a function which takes a single Int parameter and returns a String would have the type (Int) -> String.
You can also give names to the parameters if you want, e.g. (count: Int) -> String, though the name is ignored.
So in your example, the reduce() method takes a single parameter, called operation.  That parameter is a function which itself takes two parameters (the first called acc of type S, and the second of type T with no name), and returns a value of type S.
What's particular confusing in your case is that S and T are type parameters: they refer to types that aren't known yet.  When the reduce() method is called, the caller will specify them (or the compiler will infer them).  That's what the <S, T : S> after the fun means: the method needs two type parameters: S, and T (which must be S or a subtype).

Could someone, please, explain me the implementation of the following "Kotlin Literal high order function"?

I am a newbie in Kotlin, I just started to learn it,
I get the following code example about literal/high order function:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
println ( myHigherOrderFun { "The Number is $it" })
prints "The Number is 5"
Which I have difficulty to understand: the function myHigherOrderFun get a lambda function as parameter but i can't understand, where is the (Int) input parameter? I see is passed in functionArg(5)... but i can't realize how is possible that?
Thanks in advance.
To start from the beginning, in Kotlin functions are first-class types, just like numbers and Strings and stuff.  So a function can take another function as a parameter, and/or return a function as its result.  A function which does this is called a ‘higher-order function’.
And that's what you have in your example!  The line:
fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)
defines myHigherOrderFun() as a function which takes one parameter, which is itself a function taking a single Int parameter and returning a String.  (myHigherOrderFun() doesn't specify an explicit return type, so it's inferred to be a String too.)
The next line is probably where things are less clear:
println(myHigherOrderFun{ "The Number is $it" })
The first non-obvious thing is that it's calling myHigherOrderFun() with a parameter.  Because that parameter is a lambda, Kotlin lets you omit the usual (…), and use only the braces.
The other non-obvious thing is the lambda itself: { "The Number is $it" }. This is a literal function taking one parameter (of unspecified type).
Normally, you'd have to specify any parameters explicitly, e.g.: { a: Char, b: Int -> /* … */ }.  But if there's exactly one parameter, and you aren't specifying its type, then you can skip that and just refer to the parameter as it.  That's what's happening here.
(If the lambda didn't reference it, then it would be a function taking no parameters at all.)
And because the lambda is being passed to something expecting a function taking an Int parameter, Kotlin knows that it must be an Int, which is why we can get away without specifying that.
So, Kotlin passes that lambda to the myHigherOrderFun(), which executes the lambda, passing 5 as it.  That interpolates it into a string, which it returns as the argument to println().
Many lambdas take a single parameter, so it gets used quite a lot in Kotlin; it's more concise (and usually more readable) than the alternative.  See the docs for more info.

LiveData map transformations in kotlin

Transformations.map in LiveData transformations take two arguments :
#NonNull LiveData source
#NonNull final Function func
I tried to make the function like this:
val localLiveData = #some live data of type LiveData<User>
Transformations.map(localLiveData, s->{return s.name = "Hi"})
but this shows error cannot unresolved "s"
finally i got it working by this :
Transformations.map(localLiveData) {
s.name = "Hi"
return#map s
}
How this thing is working map has only one argument? (noob in kotlin)
Most of the problems here are with Kotlin's lambda syntax, which is slightly different from that of some other languages.
In Kotlin, a lambda must have braces.  But the -> is optional in some cases (if the lambda takes no parameters; or if it takes one and you're referring to it with the dummy name it).
This is one reason why your first version fails; it would need the s -> moved inside the braces.  (Another is that in Kotlin, an assignment is not an expression, and doesn't return a value, so you can't use it in a return.)
Your second works because in Kotlin, if the last parameter is a lambda, it can be moved outside the parenthesis.  (This allows for higher-order functions that look like language syntax.  In fact, if the lambda is the only parameter, you can omit the parentheses entirely!)
I don't know LiveData, but I wonder if the return#map is doing the right thing: it will return not just from the lambda, but from the map() method itself.  (Such non-local returns aren't needed very often, and can be confusing.)
Also, a lambda doesn't need an explicit return; it returns the value of its last expression.
So I suspect that a more concise version would be:
Transformations.map(localLiveData) { it.name = "Hi"; it }

How do I read / interpret this Kotlin code effectively?

I know how to read/interpret Java code and I can write it. However being new to kotlin I find code like below hard to read. Perhaps I am missing key concepts in the language.
But, how would you go about interpreting this code? Where do you propose one to start reading it in order to understand this piece of code quickly and efficiently? Left to right? Right to left? Break down parameters first? Look at return values?
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
So, like Java this is a generic function. It has two type parameters T which is of type 'Any' ('Any' is like 'Object' in Java) and R. The input parameter is a nullable T, as denoted by the question mark. Nullable types mean that the value can be null. The other function parameter is a function that takes in a T (non nullable type) and returns R. The return type of the function is a nullable R. The body of the function says that if input is not null, call and pass that to the callback and return that value. If input is null, then null is what gets returned.
Let's dissect the function definition piece by piece:
inline: Indicates that the code of the function will be copied directly to the call site, rather than being called like a normal function.
fun: We're defining a function.
<T : Any, R>: The function takes two generic type parameters, T and R. The T type is restricted to the Any type (which is Kotlin's Object-type). That might seem redundant, but what it actually says is that T cannot be a nullable type (Any?).
ifNotNull: The name of the function.
input: T?: The first parameter of type T?. We can put the ? on the T type here because we restricted it to non-nullable types in the type declaration.
callback: (T) -> R: The second parameter is of type (T) -> R, which is a function type. It's the type of a function that takes a T as input and returns an R.
: R?: The function returns a value of type R or null.
return input?.let(callback): The function body. The let function takes a function parameter, calls it with its receiver (input), and then returns the result of the function. The ? after input says that let will be called only if input is not null. If input is null, then the expression will return null.
The function is equivalent to this Java method (except for the inlining and nullable types):
public <T, R> R ifNotNull(final T input, final Function<T, R> callback) {
if (input == null) {
return null;
}
return callback.apply(input);
}
Matt's answer explains everything well in one go; I'll try to look at how you might go about reading such code.
Skipping over the first word for now, the most important thing is the second word: fun.  So the whole thing is defining a function.  That tells you what to expect from the rest.
The braces tell you that it's a block function, not a one-liner, so the basic structure you're expecting is: fun name(params): returnType { code }.  The rest is filling in the blanks!  (This fits the general pattern of Kotlin declarations, where the type comes second, after a colon.  The Java equivalent would of course be more like returnType name(params) { code }.)
As with Java, the stuff in angle brackets is giving generic parameters, so we can skip that for now and go straight to the next most important bit, which is the name of the function being defined: ifNotNull.
Armed with those, we can read the rest.  inline is a simple modifier, telling you that the function will be inlined by the compiler.  (That enables a few things and restricts a few others, but I wouldn't worry about that now.)
The <T : Any, R> gives the generic parameter types that the function uses.  The first is T, which must be Any or a subtype; the second is R, which is unrestricted.
(Any is like Java's Object, but can't be null; the topmost type is the related Any?, which also allows null.  So except for the nullability, that's equivalent to the Java <T extends Object, R>.)
Going on, we have the function parameters in parentheses.  Again, there are two: the first is called input, and it's of type T?, which means it accepts any value of type T, and also accepts null.  The second parameter is called callback, and has a more complicated type, (T) -> R: it's a function which takes a T as its parameter, and returns an R.  (Java doesn't have function types as such, so that probably looks strangest.  Java's nearest equivalent is Function<R, T>.)
After the parentheses comes the return type of this function itself, R?, which means it can return either an R or null.
Finally, in braces is the actual code of the function.  That has one line, which returns the value of an expression.  (Its effect is to check whether the value of input is null: if so, it returns the null directly.  Otherwise, it calls the callback function given in the parameter, passing input as its parameter, and returns its result.)
Although that's a short declaration, it's quite abstract and packs a lot in, so it's no wonder you're finding it hard going!  (The format is similar to a Java method declaration — but Kotlin's quite expressive, so equivalent code tends to be quite a bit shorter than Java.  And the generics make it more complex.)  If you're just starting to learn Kotlin, I'd suggest something a bit easier :-)
(The good news is that, as in Java, you don't often need to read the stdlib code.  Although Kotlin's doc comments are rarely up to the exemplary level of Java's, they're still usually enough.)