I have a model with an optional higher-order function (() -> Unit)?
When I want to call that function, I'm wondering, how can I call it even been an optional.
I know this works
model.action?.invoke()
There is something similar to Swift?, where I could do:
model.action?()
I know, I can do too:
model.action?.let { action() }
Maybe this last one is the "better" way to go.
Do you know some "better" way?
Thanks
It's a matter of one's personal preference, but I'd stay with the first variant, i.e.
model.action?.invoke()
Simply because it's just the safe call of invoke operator and it does not have the burden of adding higher-level function (i.e. let) into the expression.
Btw, in some cases if you write something like model.action?.let { it() } in Idea (at least it works for Android Studio which is based on Idea), you'll get a warning saying that let is useless here and you can safely replace it with the plain safe call.
You may use the standard library function let as follows:
val actionResult = model.action?.let { it() }
Note that the receiver of let (model.action) is exposed as it inside the lamda.
Alternatively, and preferably IMO, invoke the function like this:
model.action?.invoke()
If the function returns unit, I’d use also, not let. The former is a side-effecting construct, the latter for returning a value.
Related
This might be a very silly question, but I am logging the methods that are triggered in my app as strings. When an issue is submitted, I would like to automatically input the text of the strings as parameters for methods. E.g:
For method:
fun assignPot(potType: PotType, ball: DomainBall, action: PotAction) {...}
I'd like to somehow call method:
assignPot(FOUL(2, BLUE(5), SWITCH))
From String:
"FOUL(2, BLUE(5), SWITCH)"
The only workaround I can think of is to split the string and create a when -> then function to get actual classes from strings, but I wondered if there's a more concise way for this.
This is not what you want to do. You should design your app in a way that prevents users from providing input similar to actual code.
However, you can achieve this. Complex parsings like this oftenly use regex-based approaches.
As you said, you should map your string part to class. If your PotType is enum, you can do something like
val re = Regex("[^A-Za-z\s]")
val reNumbers = Regex("[^0-9\s]")
// get classes
val classNames = originalString.replace(re, "").split(" ")
// get their constructor numerical arguments
val classArgs = originalString.replace(reNumbers, "").split(" ")
After that you can implement mapping with when expression. You probably will use some collection of Any type.
As you see, this sadly leads you to parsing code by code. Concise way to solve is to implement your own script compiler/interpreter and use it in your application :) That will later lead you to dealing with security breaches and so on.
If you are logging problematic method calls and want to repeat them immediately after issue is submitted, you probably want to programatically save the calls to lambdas and call them when you receive an issue log.
I am learning how to use the coroutines in kotlin. looking at some examples in the internet i found that within the context f the also operator the reference
it
is used. i could not find any explanation about the meaning of
it
please provide some brief explanantion about what does "it" mean
when you use the also method, it has 1 parameter.
Think of it in Java kinda like this:
foo.also(int it) {
// do stuff
}
In Kotlin, the it parameter is implicit (sometimes you might want to use it sometimes you don't).
If you want to rename it to something more readable you can
foo.also { newName ->
// do stuff with newName
}
Or just use it like it is
foo.also {
// do stuff with $it
}
So therefore when you are using a method (or a closure/lambda) if it has 1 parameter, then the implicit name of that parameter is always it.
Basically it represents the lambda parameter
let's say you want to perform anything on the variable but do to check the nullity first, you can do it like
var str:String?=null // str is of string type
now you can use it fail safe
str?.let{it:String// youll see like this
// now you can access str as **it**
}
it is the implicit name of a single parameter
For more information about it and this in scoping functions like also
We are trying to understand calling a function in Kotlin
The function looks like this
fun onSIMPLE(view: View){
val snack = Snackbar.make(view,"This is a simple Snackbar", Snackbar.LENGTH_LONG)
snack.show()
}
And the call is made this way
btnSB2.setOnClickListener {onSIMPLE(it)}
What we do not understand is how does one know to use the keyword "it"?
Who ever created the keyword "it" must have never searched the Web
We plugged every reasonable keyword in the ( ) to solve the issue
YES we also looked at the documentation
Is there a better way to construct the function or make the call?
it is the implicit name for a single parameter lambda. You can override as you wish, e.g:
btnSB2.setOnClickListener { view -> onSIMPLE(view)}
setOnClickListener expects a lambda as a parameter, using a Java-like approach, this should look like this:
btnSB2.setOnClickListener({
v:View -> onSIMPLE(it)
})
Also, if the lambda is the last parameter for a given function, it can be specified outside of the parenthesis, which would look like this:
btnSB2.setOnClickListener {
v:View -> onSIMPLE(it)
}
It is common for lambda functions to have a single parameter. For these functions, Kotlin maintains the it keyword. Knowing this, the code becomes:
btnSB2.setOnClickListener {
onSIMPLE(it)
}
I have created a custom view in android. one of the methods has a signature like this:
fun show(CategoryFilterModel model) {/*...*/}
and it works fine. and now i'd like to create a overloaded function which would look like this if i did it by adding it to the custom view class:
fun show(ShopFilterModel model) {/*...*/}
Notice the type is different so this is a method overload.
a thought came to me that i could instead use an extension in kotlin to add another method to the class.
so it would like something like this:
fun MyCustomView.show(ShopFilterModel: model){
}
is this advised or should i only add utility methods with extensions ? Are there any overheads ?
It’s not only for utilities, as you can read in this great answer, which lists pretty much all use cases.
Imho, if you have control over that class you want to extend with a method, there’s no problem to add the method directly to it as opposed to doing it with an extension method. Yet, technically you can consider doing this. Please be aware that calling such an extension function from Java isn’t very idiomatic because it will be compiled to a static function. If it’s ever going to be invoked from Java, I’d rather use ordinary methods when possible.
It´s a good idea to use kotlin extensions all over the code?
I miss a lot the extensions from iOS, but this is a good way to use those kind of things in android?
Refering to http://antonioleiva.com/kotlin-android-extension-functions/
Is there a better solution for this?
To expand a little bit more on Andrey Breslav's answer a bit, Kotlin extension functions do compile down to static java methods, so most general purpose extension functions carry no overhead. But there is one edge case you need to look out for that Jake Wharton calls out in the first few min of this talk at Google IO.
That is when you pass in higher order functions (lambdas), as a parameter to the extension function like so:
fun View.doSomething(block: () -> Unit) {
//do something
}
This code would take a performance hit because lambda's under the hood have to create an anonymous class under the hood which can eat up methods and cause class loading. This is a very simple fix by adding the inline keyword to the function which will essentially inline your code into all of this call sites functions so you will not take a performance hit each time the extension function is called.
inline fun View.doSomething(block: () -> Unit) {
//do something
}
Extension functions in Kotlin are compiled to normal Java methods. For example, when you define a function in your package it turns into a static method in a Java class. There's no overhead compared to simply calling a static utility