How to understand a fun with = in Kotlin? - kotlin

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.

Related

How to set return type of a function to mutableListOf in kotlin

I made a function which returns all factors of an integer. But the problem is that it gives an error that the return type is Unit instead of mutableListOf. my code:
fun get_factors(num: Int) {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
I tried doing:
fun get_factors(num: Int): mustableListOf {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
but it says mutableListOf not defined.
I just started learning Kotlin today so I am a total beginner with Kotlin. Please help me out with this.
You seem to have confused the type MutableList<Int>, with the function mutableListOf.
Since the type name is MutableList<Int>, you should do:
fun get_factors(num: Int) : MutableList<Int> {
...
}
Or, if the caller doesn't need to modify the list, you can just return List<Int> too:
fun get_factors(num: Int) : List<Int> {
...
}
I can see why this is confusing - to create an instance of a type, you normally just add () to the end of the type name, so if mutableListOf() creates a list, you'd think that mutableListOf is the type name. However, this is actually calling the global function called mutableListOf, which returns an instance of MutableList<T>.
One way to distinguish between these is to look at the first letter. Type names usually begin with a capital letter, whereas function names begin with a small letter.

Kotlin: Pass ranges in function as arguments

Hello is it possible to pass range in Kotlin function just like in python?
I've just started learning Kotlin but I am a little bit stuck
I wish i could pass somethind like
my_gauge = Gauge('test_name',1..200, 201..300, and etc.)
for example I have a Gauge object which rotates on the base
class Gauge(val gauge_name: String,
val red_value: Float,
val orange_value: Float,
val yellow_value: Float,
val green_value: Float,
var current_value: Float,
val min_value: Float,
val max_value: Float) {
val gauge_green = 0xFF66C2A5.toInt()
val gauge_yellow = 0xFFFDD448.toInt()
val gauge_orange = 0xFFF5A947.toInt()
val gauge_red = 0xFFD53E4F.toInt()
val min_rotation: Int = 0;
val max_rotation: Int = 300;
val ratio = max_rotation / max_value;
fun calculate_rotation(): Int {
return (current_value * ratio).toInt()
}
fun get_color(): Int {
if (current_value >= red_value) {
return gauge_red
}
if (current_value > orange_value) {
return gauge_orange
}
if (current_value > yellow_value) {
return gauge_yellow
}
return gauge_green
}
}
I've just realized that it wont work with this data instead it will be better to build my logic around ranges
So my question is How to pass ranges as a param in class/function (instead of floats)
PS: The function get_colors is not correct I will fix it once I can pass ranges with when(current_value) statement
Yes, the type of a range produced by .. is ClosedRange<T>:
fun foo(floatRange: ClosedRange<Float>) {
println(floatRange.random())
}
// Usage:
foo(1f..10f)
For integer ranges, you may prefer IntRange over ClosedRange<Int> because it allows you to use it without the performance cost of boxing by using first and last instead of start and endInclusive. There is no unboxed version for other number types.
Try this in simple way, you can use range according to data type IntRange, FloatRange, LongRange etc.
fun foo(range: IntRange){
for (a in range){
println(a)
}
}
// call this function by
foo(1..10)

What is the difference between these ways for defining functions?

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 :)

Kotlin: Function-param implementation in a body of a caller

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.

When is it possible to omit return type in Kotlin?

I have the following function in Kotlin:
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
which could be simplified to:
fun max(a: Int, b: Int) = if (a > b) a else b
In the previous definition, the returned type of the function has been omitted, and this is known as expression body. I am wondering if there exists other cases in which it is possible to omit the return type of a function in Kotlin.
Functions with block body must always specify return types explicitly, unless it's intended for them to return Unit.
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value - Unit. This value does not have to be returned explicitly
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}")
else
println("Hi there!")
// `return Unit` or `return` is optional
}
The Unit return type declaration is also optional. The above code is equivalent to
fun printHello(name: String?) {
...
}
when the return type is Unit
fun printHello(): Unit {
print("hello")
}
is the same as
fun printHello() {
print("hello")
}
also, is the same as
fun printHello() = print("hello")
Usually, a function must declare it's return type. But if some functions consist of a single expression then we can omit the curly braces and the return type and uses the = symbol before the expression rather than the return keyword. This type of functions are called Single Expression Functions.
Example:
fun add(a: Int, b: Int): Int {
return a + b
}
This code can be simplified to:
fun add(a: Int, b: Int) = a + b
The compiler will enforce you to do this.