Whats the difference between these two function callings in kotlin? - kotlin

The first way
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
print(add(a = 2, b = 3))
}
The second way
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
print(add(2, 3))
}
The end result of the two functions is the same but i was wondering if there is any internal difference between the two ways of function calling.

In the first case you're explicitly stating to which field of the add() method constructor you're assigning the value.
In this way the order in which you put the values doesn't matter, as long as each value is explicitly assigned to a parameter. For example, in this case you can also write:
print(add(b=3, a=2))
still works.
As instead, in the second way you are forced to follow the order in which the fields are written in the method implementation (the first value is implicitly assigned to a, the second to b and so on)

For this example there is no difference, because you are adding the arguments in order
add(a=2,b=3): here a is going to take 2 and b is going to take 3
add(2,3): and here a is the first argument so it's going to take the first passed argument which is 2 and the same for b
But here is the difference (a + b == b + a so I add minus function to see the difference because a - b != b - a) :
fun minus(a : Int,b:Int):Int{
return a-b;
}
fun main()
{
print(minus(a=2,b=3)) // a = 2, b = 3 -> a - b = 2 - 3 = -1
print(minus(b=2,a=3)) // a = 3, b = 2 -> a - b = 3 - 2 = 1
print(minus(2,3)) // a = 2, b = 3 -> a - b = 2 - 3 = -1
}
So if you add minus(a=2,b=3) you are saying that a is going to take 2 and b is going to take 3,
and here minus(2,3) you are saying that the first parameter (a) is going to take 2 and the second parameter (b) is going to take 3
But let's say for some reason you change the order of the parameters of your function:
fun add(b : Int,a:Int):Int{
return a+b;
}
Now if you add minus(a=2,b=3) you are saying that a is going to take 2 and b is going to take 3 so nothing changes for this case and your code will work fine.
But here minus(2,3) you are saying that the first parameter (b) is going to take 2 and the second parameter (a) is going to take 3 so you will not get the same result before changing the order of the parameters of the function. So adding parameter name when you call a function is a best practice to say that you want this value for that exact argument.
Also there's other example, let's say that you have a function that has default values:
fun test(a : Int = 10, b:Int = 5):Int {
return a+b;
}
So the you can call it like that test() without passing any argument, but let's say that you want to change only b to 15, if you write test(15), a is going to take 15 not b so here you need to specify that the 15 is for b: test(b = 15)

There is no difference, the only difference is readability by using named arguments in the first example.
The fun thing about using named arguments when calling your method is that you can also change the order or even leave out some of the values if they are default i.e:
fun add(a :Int,b: Int):Int {
return a+b;
}
Can also be written with a default value like so:
fun add(a :Int = 2,b: Int = 3, c: Int = 4):Int {
return a+b+c;
}
Now you can skip some of the values like so:
fun main() {
print(add(a = 2, c = 3))
}
// So we did 2 + 3 + 3
// prints 8
// Notice we skipped b

Related

Expecting member declaration (this happens when using a variable from another class)

The code here works:
fun main(){
val pizza = random()
print(pizza.num)
}
class random{
val num = 5
}
But the code here does not work
fun main(){
val pizza = random()
print(pizza.num)
}
class random{
val num = 5
num = 7
}
The only difference is that in the last line of code I reassign the variable num. The only thing I did was change this variable from 5 to 7.
Why is this causing errors?
Note This is the online IDE I was using: https://developer.android.com/training/kotlinplayground
2 things:
Firstly, you can't reassign vals. you need to change that to var
Secondly, you can't do assignments directly in a class body, only declarations.
However, you could put it in an init block like this to get the desired result:
class random{
var num = 5
init {
num = 7
}
}
you might want to read the documentation about kotlin classes here

Extract value out of Kotlin arrow Either type and assign it to const

It would be a basic question, but I couldn't figure out a solution. I need to initialize a constant out of the right-side value of below either type.
val test: Either<String, Int> = 1.right()
I tried something like below but it shrinks the scope of the constant.
when(test) {
is Either.Right -> {val get:Int = test.b}
is Either.Left -> println(test.a)
}
I want that get to be scoped outside of when statement. Is there any way to do it or Arrow Either is not made for this purpose?
The important question is: what should happen if the Either is Left. In this example it is created close to where it's used, so it is obvious to you as a developer. But to the compiler what is inside the Either can be either an Int or a String.
You can extract the value using for example fold:
val x = test.fold({ 0 }, {it}) // provide 0 as default in case the Either was a `Left`
// x = 1
another option is getOrElse
val test = 1.right()
val x = test.getOrElse { 42 } // again, default in case it was a `Left`
// x = 42
You can also work with it without unwrapping it:
val test = 1.right()
val testPlus10 = test.map { it + 10 } // adds 10 to `test` if it is `Right`, does nothing otherwise
val x = testPlus10.getOrElse { 0 } // unwrap by providing a default value
// x = 11
For more example check the official docs.
Recommended reading: How do I get the value out of my Monad

Why does `variable++` increment the variable but `variable + 1` does not?

Here's the problem in which I encountered this issue:
The function should compare the value at each index position and score a point if the value for that position is higher. No point if they are the same. Given a = [1, 1, 1] b = [1, 0, 0] output should be [2, 0]
fun compareArrays(a: Array<Int>, b: Array<Int>): Array<Int> {
var aRetVal:Int = 0
var bRetVal:Int = 0
for(i in 0..2){
when {
a[i] > b[i] -> aRetVal + 1 // This does not add 1 to the variable
b[i] > a[i] -> bRetVal++ // This does...
}
}
return arrayOf(aRetVal, bRetVal)
}
The IDE even says that aRetVal is unmodified and should be declared as a val
What others said is true, but in Kotlin there's more. ++ is just syntactic sugar and under the hood it will call inc() on that variable. The same applies to --, which causes dec() to be invoked (see documentation). In other words a++ is equivalent to a.inc() (for Int or other primitive types that gets optimised by the compiler and increment happens without any method call) followed by a reassignment of a to the incremented value.
As a bonus, consider the following code:
fun main() {
var i = 0
val x = when {
i < 5 -> i++
else -> -1
}
println(x) // prints 0
println(i) // prints 1
val y = when {
i < 5 -> ++i
else -> -1
}
println(y) // prints 2
println(i) // prints 2
}
The explanation for that comes from the documentation I linked above:
The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:
Store the initial value of a to a temporary storage a0;
Assign the result of a.inc() to a;
Return a0 as a result of the expression.
...
For the prefix forms ++a and --a resolution works the same way, and the effect is:
Assign the result of a.inc() to a;
Return the new value of a as a result of the expression.
Because
variable++ is shortcut for variable = variable + 1 (i.e. with assignment)
and
variable + 1 is "shortcut" for variable + 1 (i.e. without assignment, and actually not a shortcut at all).
That is because what notation a++ does is actually a=a+1, not just a+1. As you can see, a+1 will return a value that is bigger by one than a, but not overwrite a itself.
Hope this helps. Cheers!
The equivalent to a++ is a = a + 1, you have to do a reassignment which the inc operator does as well.
This is not related to Kotlin but a thing you'll find in pretty much any other language

Curry functions - How to call 3 (or multiple) functions?

I am trying to curry a function in kotlin such that i can call it like this
myAdditionFunction(1)(2)(3)
this call would return 6 because 1+ 2 + 3 = 6
i just need it to perform an addition over all the numbers. actually i really want it to do a builder
pattern in the future but still trying to see how curry functions work. Here is what i have so far:
fun myAdditionFunction(x: Int) { { y: Int -> x + y }
this works for two parameters. so myAdditionFunction(1)(2) will print 3.
i want it to work for 3 or multiple : here is what i have tried for 3 paramters:
fun myAdditionFunction(x: Int) {
var sum = 0
return { y: Int ->
sum = x + y
sum }
}
How do i carry the sum forward and how to make it take a third inner function ?? it wont compile.
but it will not compile
I'm not exactly sure what's going on in either of your examples, and neither compiled on my machine (Kotlin 1.3.10).
However, you can do lambda expressions, as they allow arbitrarily deep nesting. So for 2 variables, you could have
val myAdditionFunction = {x: Int -> {y: Int -> x + y}}
And for three variables, you can go a level deeper:
val myAdditionFunction = {x: Int -> {y: Int -> {z: Int -> x + y + z}}}
Just for reference, a lambda expression (aka anonymous function) is in the form:
val functionName = {argument1: type -> return_value}
I think something can't be an Int and a function simultaneously. Maybe use an extention function on Int class?
operator fun Int.invoke(x: Int) = this + x
val a = 1(2)(3)
With Lionel Briand's great idea to create an operator extension function invoke on Int, you just need another function curry as entry point
operator fun Int.invoke(x: Int) = this + x
fun curry(x: Int) = x
and you can do exactlty what you wanted:
curry(1)(2)(3)(4) // will return 10

Error in Print prime number using high order functions in kotlin

val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
val secNum:Unit = listNumber1to100.forEach {it}
println(listNumber1to100.asSequence().filter { it%(listNumber1to100.forEach { it })!=0 }.toList())
I have an error in reminder sign!
This is Error: None of the following functions can be called with the arguments supplied
In your first approach, the error appears in this line:
it%(listNumber1to100.forEach { it })
A Byte, Double, Float, Int, Long or Short is prefered right after the % operator, however, forEach is a function which the return type is Unit.
In your second approach, you have the correct expression in isPrime(Int). Here are some suggestions for you:
listNumber1to100 is excluding 100 in your code, if you want to include 100 in listNumber1to100, the lambda you pass to takeWhile should be changed like this:
val listNumber1to100 = listNumbers.takeWhile { it <= 100 }
listNumber1to100.asSequence() is redundant here since listNumber1too100 is itself a TakeWhileSequence which implements Sequence.
isPrime(Int) is a bit confusing since it is check for isComposite and it does not work for every input it takes(it works for 1 to 99 only). I will rewrite it in this way:
fun isPrime(num: Int): Boolean = if (num <= 1) false else !(2..num/2).any { num % it == 0 }
Since prime number must be positive and 1 is a special case(neither a prime nor composite number), it just return false if the input is smaller or equal to 1. If not, it checks if the input is divisible by a range of number from 2 to (input/2). The range ends before (input/2) is because if it is true for num % (num/2) == 0, it is also true for num % 2 == 0, vise versa. Finally, I add a ! operator before that because a prime number should not be divisible by any of those numbers.
Finally, you can filter a list by isPrime(Int) like this:
println(listNumber1to100.filter(::isPrime).toList())
PS. It is just for reference and there must be a better implementation than this.
To answer your question about it, it represents the only lambda parameter inside a lambda expression. It is always used for function literal which has only one parameter.
The error is because the expression: listNumber1to100.forEach { it } - is not a number, it is a Unit (ref).
The compiler try to match the modulo operator to the given function signatures, e.g.: mod(Byte) / mod(Int) / mod(Long) - etc.
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
fun isPrime(num: Int): Boolean = listNumber1to100.asSequence().any { num%it==0 && it!=num && it!=1 }
println(listNumber1to100.asSequence().filter { !isPrime(it)}.toList())
I found this solution and worked
But why can I have a non-number here in the right side of reminder