In Kotlin we can't write:
arrayOf(1,2,3).forEach(println)
But we have to instead call forEach using ::println. This is because forEach expects a lambda, but println is a function. Why are these different types and is there any good reason why Kotlin doesn't automatically cast it for me like it does in Python?
Update:
There does seem to be a difference. Look at:
val addA: (Int)->Int = {it+1}
fun addB(i: Int) = i+1
fun main(args: Array<String>){
var x: Int=0
x.let(addA).let(::addB).let(::print)
}
The lambda doesn't need the ::, but the function does
I don't think that a lambda and a function are different types. The only type which exists is a function type and a lambda is one way of instantiating a function. Here in the documentation are all the ways to get an instance to a function type https://kotlinlang.org/docs/reference/lambdas.html#instantiating-a-function-type.
::println is a way if getting a reference to an existing declaration. So your question is why it is necessary to use ::. Maybe it is just to have a consistent way of getting a function reference in other cases as when you want a reference that point to a member of a particular instance as foo::toString.
Related
Is there any difference between these two Kotlin extension functions?
fun Any?.f(o: Any?) = 100
fun <T> T.g(o: T) = 100
Is it possible to rewrite g in such a way that the type of its argument and receiver are forced to be the same?
That is, 10.g(5) and "x".g("y") are OK, but 10.g("y") does not compile.
Edit:
Given this, I guess the answer to my second question is no, uless one adds additional arguments.
I believe this is not possible officially at the time of writing this answer (Kotlin 1.7.20).
However, internally Kotlin compiler supports such case, it allows to change the default behavior and use exact type parameters. This is controlled by the internal #Exact annotation and it is used in many places across the Kotlin stdlib.
With some hacking we can enable this behavior in our own code:
#Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun <T> #kotlin.internal.Exact T.g(o: #kotlin.internal.Exact T) = 100
Of course, this is purely a hack and it may stop working in future versions of Kotlin.
Update
Answering your first question on whether there is a difference between using Any and T. Generic functions make the most sense if the type parameter is not only consumed, but also passed somewhere further. For example, if the function returns T or it receives an object that consumes T:
fun main() {
var result = 5.g(7)
}
fun <T> T.g(o: T): T = if (...) this else o
In this case result is of type Int. If we use Any instead of T, result would have to be Any as well.
This question already has answers here:
Example of when should we use run, let, apply, also and with on Kotlin
(6 answers)
Closed 3 years ago.
We can write the code with or without let as follows.
var str = "Hello World"
str.let { println("$it!!") }
OR
var str = "Hello World"
println("$str!!")
What is the Actual use of let?.Is that more memory efficient or more readable?
let is one of Kotlin's Scope functions which allow you to execute a code block within the context of an object. In this case the context object is str. There are five of them: let, run, with, apply, and also. Their usages range from but are not exclusive to initialization and mapping.
They are all very similar but they differ in terms of how the context object is referenced and the value that is returned. In the case of let the context object is referenced by the it keyword as opposed to the this keyword. The return value is whatever is returned from the lambda code block. Other scope functions like apply will return the context object instead.
Because let returns whatever the lambda block evaluates to, it is most suited to performing a mapping of some kind:
var upperStr = str.let { it.toUpperCase()}
apply is a more suited function for what you are doing.
To answer your question as to which code is more preferable, it really depends on what you are using the scope function for. In the above case there is no reason to use let. If you are using IntelliJ it will give a warning saying the call to let is redundant. Readability here is a matter of preference, and may be preferred.
The let function is useful when you wish to perform a null safe operation on an Object by using the the safe call operator ?. When doing this the let code block will only be executed if the object is not null. Another reason to use let is if you need to introduce new variables for the operation but you want to confine them to the scope of the let block. This is true for all scope functions, so I reiterate that let is best used for a mapping operation.
Edit: The let function should incur no additional cost. Normally we would expect the lambda/Code-block to be compiled to a Function object but this is not the case for an inline function in Kotlin for which the compiler will emit code not dissimilar to the second code example you have given. See the documentation for more information.
One of usages you can check nullable types
var str: String? = null
str?.let { println("$it!!") }
it's equal
if (str != null) {
System.out.println(str);
}
in Java, but shorter and more useful
let takes the object it is invoked upon as the parameter and returns the result of the lambda expression.
Kotlin let is a scoping function wherein the variables declared inside the expression cannot be used outside.
One of the examples would be here :
fun main(args: Array<String>) {
var str = "Hello World"
str.let { println("$it!!") }
println(str)
}
You can find more information on Kotlin let function here
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 }
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.)
I try to write a type-safe wrapper for a JavaScript library.
I need to call a method from JavaScript with variable arguments
(e.g. method(args...)).
The Kotlin fun for this should work with variable arguments, too.
Because Kotlin supports a spread operator, I tried to use it, but Kotlin do not want this.
Example code:
val jsLibrary: dynamic = require("library") // library given by node's require here
fun method(vararg args: String) = jsLibrary.method(*args)
Edit: Forgot to write spread operator '*' in code already. Compiler returns error because of the spread operator.
The Kotlin compiler returns the error "Can't apply spread operator in dynamic call".
Any ideas how to implement a wrapper like this, or do I need any workaround?
Thanks for your help!
Use external fun with #JsModule annotation
#JsModule("library")
external fun method(vararg args: String): LibraryMethodReturnType
This will do require("library") for you under the hood. You'll have proper Kotlin types instead of dynamic right away. You'll have no "wrappers", meaning no extra JavaScript call at runtime.
There is a hacky solution if for you want to manually use require and dynamic types: use apply method to pass all the arguments as an array.
val jsLibrary: dynamic = require("library")
fun method(vararg args: String) = jsLibrary.method.apply(null, args)