fun lazyProperty(initializer: () -> Int): Int {
val result: Lazy<Int> = lazy(initializer)
return result.value
}
fun main(args: Array<String>) {
// 1.
val bar: Int = lazyProperty({ 1 + 1 })
// 2.
val foo: Int = lazyProperty() {
42
}
println("bar $bar, foo: $foo")
}
I recently stumbled over the syntax of calling a function in Kotlin and I just don't get it:
the fist option is clear - it's a lambda, but the second one looks not like a usual syntax of calling a function with the required parameter. The brackets where normally params should be placed are empty and instead the function-parameter comes in the body of the caller! How is it possible and what for is it needed?
This is another valid way of passing a lambda. According to the docs:
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:
lock (lock) {
sharedResource.operation()
}
You can choose whichever approach you prefer.
This is just convention. If the last param of a function is a function, you can pass the lambda outside the parentheses. In your case you have the following options:
val bar: Int = lazyProperty({ 1 + 1 })
val bar: Int = lazyProperty() { 1 + 1 }
val bar: Int = lazyProperty { 1 + 1 }
All three options are the same.
If your function would have a second parameter (at first position), than the calls could look like this:
fun lazyProperty(x: Int, initializer: () -> Int): Int {...}
val bar: Int = lazyProperty(7, { 1 + 1 })
val bar: Int = lazyProperty(7) { 1 + 1 }
If your function would have a second parameter (at second position), than the calls could look like this:
fun lazyProperty(initializer: () -> Int, x: Int): Int {...}
val bar: Int = lazyProperty({ 1 + 1 }, 7)
So always try to keep the Lambda at the last position of your function.
Related
In JavaScript, the destructuring of an object is something common.
const foo = {
a: 1
b: 2
c: 3
};
const {a, b, c } = foo;
console.log(a)
1
Is something like this possigle with KotlinJS React?
interface FooProps : Props {
var a: Int
var b: Int
var c: Int
}
val Foo = FC<FooProps> { props ->
val(a, b, c) = props
...
}
This is not working. It gives me
Destructuring declaration initializer of type FooProps must have a 'component1()' function
Kotlin supports destructuring declarations, however they work in a different way than JavaScript.
In particular, you can destructure an object like this:
val (property1, property2, property3, ..., propertyN) = object
assuming that object contains certain methods:
operator fun component1()
operator fun component2()
...
operator fun componentN()
Example:
class Person(val name: String, val dateOfBirth: LocalDate) {
operator fun component1(): String = name
operator fun component2(): LocalDate = dateOfBirth
}
val johnDoe = Person("John", LocalDate.of(1980, JANUARY, 1))
val (name, dob) = johnDoe
println("$name -> $dob") // prints John -> 1980-01-01
Use can make use of extension functions to implement this behaviour on classes you don't own. Example:
operator fun String.component1(): Int = this.length
operator fun String.component2(): Char = this.first()
val someString = "Hello, world"
val (length, firstChar) = someString
println("$length -> $firstChar") // prints 12 -> H
Suppose we have the following code:
#ExperimentalCoroutinesApi
fun ProducerScope<DownloadableDataDto<out User>>.findInteresting(input: ReceiveChannel<DownloadableDataDto<out User>>,
communitiesCount: Int,
userCountMap: MutableMap<User, Int> = ConcurrentHashMap()) = createProducer(input) {
if (userCountMap.compute(it.data!!) { _, value ->
if (value == null) 1 else value + 1
} == communitiesCount) send(it)
}
This code checks if a user is a part of all of the communitiesCount communities. But this logic is enclosed inside a createChannel() higher order function, which I would not want to test at the moment. Is there a way to test only the internals? I assume I could probably extract that to a separate function as well, right?
And if I do it that way, let's say we have this instead:
#ExperimentalCoroutinesApi
fun ProducerScope<DownloadableDataDto<out User>>.findInteresting(input: ReceiveChannel<DownloadableDataDto<out User>>,
communitiesCount: Int,
userCountMap: MutableMap<User, Int> = ConcurrentHashMap()) = createProducer(input) {
sendIfInteresting(it, communitiesCount, userCountMap)
}
#ExperimentalCoroutinesApi
private suspend fun ProducerScope<DownloadableDataDto<out User>>.sendIfInteresting(userDto: DownloadableDataDto<out User>,
communitiesCount: Int,
userCountMap: MutableMap<User, Int>) {
if (userCountMap.compute(userDto.data!!) { _, value ->
if (value == null) 1 else value + 1
} == communitiesCount) send(userDto)
}
How would I mock the send(userDto) call? I can mock the ProducerScope object, but how would I call the real sendIfInteresting() method?
I am from a background of Javascript trying to learn some Kotlin.
I know i can define my function by
fun add(a: Int , b: Int): Int{
return a+b
}
I am trying this
val add = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
//How do i return from this function
}
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
This is not even "a way to define Kotlin functions".
In JavaScript, all functions are reified: they are first-class values you can refer to from variables and pass around. Not so in Kotlin, just as in many other languages like Java, C++, Objective C and so on.
A function is just a declaration, you can call it but you can't otherwise directly refer to it. Separate language features allow you to create functional objects that delegate to these functions, and you can pass these objects around.
Therefore,
fun add(a: Int , b: Int): Int {
return a + b
}
is a function declaration and
val add = {a: Int, b: Int ->
a + b
}
is four things:
declaration of a variable add
declaration of an anonymous implementation of the functional type (Int, Int) -> Int
instantiation of this anonymous type, resulting in a functional object
assignment of the object to the variable add.
The object has a method invoke(a: Int, b: Int): Int whose implementation you have given in the block:
fun invoke(a: Int, b: Int): Int {
return a + b
}
You can call it explicitly:
val result = add.invoke(a, b)
and on top of that Kotlin defines syntax sugar that allows you to omit the explicit .invoke.
You don't need the explicit return there
val add = { a: Int, b: Int ->
a + b
}
add(2, 3) // => 5
Hopefully this will work.
val onChange = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
println("Sunm ${a+b}")
//How do i return from this function
}
Log.v("Response", add(4,3))
Output
V/Response: Sum 7
You can't return values in kotlin like this, it will give error of type mismatch as you havn't declared any return type :
fun add(a: Int , b: Int){
return a+b
} //wrong
we declare return type in kotlin as :
fun add(a: Int , b: Int) : Int{
return a+b
}
Secondly,
val add = { a:Int ,b : Int ->
}
this is not a function, its a declaration of value assignment
In kotlin we declare function by adding "fun" before your function name as
//you can add access modifiers(private,public,protected) if needed just before "fun"(by default its public)
fun add (){ //if it returns any value then add ": {datatype}" just right of "()"
//your code here
}
Hope it helped you :)
I know a standard fun just like Code 0.
The Code 1 is a sample code from webpage, I can't understand completely the
fun convertFromDomain(forecast: ForecastList) = with(forecast) {...}
Why is the symbol = added to the fun? and is the return value of the fun convertFromDomain unit ?
Code 0
fun My(forecast: ForecastList):Boolean {
...
return true;
}
Code 1
data class ForecastList(val id: Long, val city: String, val country: String, val dailyForecast: List<Forecast>) {
val size: Int
get() = dailyForecast.size
operator fun get(position: Int) = dailyForecast[position]
}
data class Forecast(val id: Long, val date: Long, val description: String, val high: Int, val low: Int,
val iconUrl: String)
fun convertFromDomain(forecast: ForecastList) = with(forecast) {
val daily = dailyForecast.map { convertDayFromDomain(id, it) }
CityForecast(id, city, country, daily)
}
Block body
Consider this function:
fun sum(a: Int, b: Int): Int {
return a + b
}
The behaviour is defined in a block body. It has an explicit return type (Int) and an explicit return statement. Both are mandatory here. If you don't specify a return type explicitely it will be Unit by default and since the inferred type of a + b is Int it won't compile.
Expression body
If you write it like this
fun sum(a: Int, b: Int) = a + b
you don't need to specify the return type because it can be inferred from the expression.You don't need a return statement either because the last expression is returned. What follows the = sign is called an expression body.
So, both functions do the same thing. The second one is only written more concise.
Note
A common mistake is to use them both at once like this:
fun sum(a: Int, b: Int) = { a + b }
What this would do becomes clear, if you specify the returned type explicitely:
fun sum(a: Int, b: Int): () -> Int = { a + b }
You would actually return a lambda of type () -> Int which is surely not what you want.
A function has usually the following form in kotlin:
fun name([parameters])[: return_type] {
// function-body
}
e.g.
fun doubleTheValue(number: Int): Int {
return number * 2
}
If your function-body is just a single-expression, you can use a shorter version of the function declaration
fun name([parameters])[: return_type] = [expression]
e.g.
fun doubleTheValue(number: Int): Int = nummber * 2
fun doubleTheValue(number: Int) = nummber * 2 // type can also be inferred
So it's nothing special, just a shorter version of a function declaration.
Traditional way to define a function is just like what you write in Code 0, which consists of function name, parameters, return type and the block body. In Kotlin, function can be defined with an expression body and the return type can be inferred from the expression body.
Suppose there is a function which convert Boolean to Int, in traditional way:
fun Boolean.toInt(): Int {
return if (this) 1 else 0
}
It can be simplified to:
fun Boolean.toInt() = if (this) 1 else 0
where the return type is inferred as Int because 1 and 0 are both Int which will be returned from the expression if (this) 1 else 0.
Let's say I have:
fun addInvoker(adder: () -> Int = ::add): Int{
return adder()
}
fun add(num1:Int = 1, num2:Int = 1): Int{
return num1 + num2
}
I get an error since ::add has two parameters, but the signature of addInvoker requires it to have zero parameters. However, if I change it to:
fun addInvoker(adder: (Int, Int) -> Int = ::add): Int{
return adder()
}
fun add(num1:Int = 1, num2:Int = 1): Int{
return num1 + num2
}
Then I can't invoke adder(), i.e. invoking add with its default arguments.
So, is there some way I can make ::add the default argument to invokeAdder but still invoke add with adder(), thus invoking it with the default args?
You can make a lambda of your add which will be no-argument function and will call add with its default arguments: { add() }.
Complete code:
fun addInvoker(adder: () -> Int = { add() }): Int {
return adder()
}
fun add(num1: Int = 1, num2: Int = 1): Int {
return num1 + num2
}
In Kotlin, functions with default arguments have no special representation in the type system, so the only option is to make wrappers passing only part of arguments to them:
val add0: () -> Int = { add() }
val add1: (Int) -> Int = { add(num1 = it) }
val add2: (Int) -> Int = { add(num2 = it) }