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
Related
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
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
Let's say I have following class:
class Person() {
var age: Pair<String, Int> = Pair("person_age", 23)
// override getValue and setValue here
}
Now I want to capsulate the actual Pair and only want the user to read/write the second value of the pair. Is it possible to override the getValue and setValue methods so I can do something like this:
val p = Person()
p.age = 25
if(p.age <= 30)
Of course I can write own getter and setter methods for each property but one nice thing about Kotlin is that you have to write such less boilerplate code which will get lost then.
The following should probably already suffice:
class Person() {
var age : Int = 23 // public by default
private /* or internal */ fun toAgePair() = "person_age" to age // narrow visibility
}
So all your code accesses the age as you have shown:
val p = Person()
p.age = 25
if (p.age <= 30) ...
But if you require your Pair you just do the following instead:
p.toAgePair() // or skip that method and use: '"person_age" to p.age' instead
Alternatives to access the Pair content are: Pair.first, Pair.second or destructured, e.g.:
val myPair = Pair("person_age", 23)
// myPair.second = 25 // setting will not work however
myPair.let { (name, age) -> /* do something with it */ }
Or alternatively:
val p = Person()
val (name, age) = p.toAgePair()
// age = 25 // setting will not work however (and it wouldn't set the actual value inside the Pair if it would contain vars)
if (age < 30) // accessing is OK
However then you get access to both values which you probably didn't want in the first place, if I understood you correctly.
You could overcome the setting part using your own data class with a var but then again, you do not really gain something from it.
I wouldn't recommend you to use Pair at all. Maybe you could modify it (inherit from it, use extension functions) to suit your needs, but why try to change something as simple as Pair?. It is much easier and in this case also cleaner to just create your own class which suits your needs:
data class MyPair<out A, B>(
val first: A,
var second: B
)
val pair = MyPair("age", 1)
pair.second = 2
pair.first = 1 // error
This class has all important features which Pair has: generic types for first and second, and you can use destructuring declarations.
Now I want to capselate the actual Pair and only want the user to read/write the second value of the pair.
Assuming this means you want the first value to be final, but not the second one, there are some options.
If you only want one of the values to be writeable and readable, don't use a pair. It's not designed to be used like that. All the items of a Pair are vals.
If you want a Pair either way, can do this:
class Person(var age: Int = 23){
val pair: Pair<String, Int>
get() = Pair("person_age", age)
//Alternatively, if you don't want to use a property:
//fun getPair() = "person_age" to age
}
What this does is creating a final pair where the first value can't be modified, but the second can.
So now:
fun example(){
val person = Person()
person.age = 25;//Fine: Age is an int, and a var
//person.pair = Pair("something", 45)//fails: "Val cannot be reassigned
val pair = person.pair // Allowed. Accessing the pair still works
assert(pair.second == person.age) // This is true
}
However, if you're fine with a non-Pair solution, this works too:
data class Person (var age: Int, val string: String = "person_age")
fun example(){
val person = Person(23)
val (name, string) = person// Allowed! Just like with Pairs
person.age = 25; // Also allowed
//person.string = "something"//Not allowed
}
The n-touple unpacking is supported for data classes. If you don't have a data class, you need to declare an operator fun for each component you want to unpack. Example:
class Person (val string: String = "person_age", var age: Int){
operator fun component1() = string
operator fun component2() = age
}
But tbh, it sounds like the data class solution is the one you're looking for. It would lock the String to what it's initialized with, and because of the default value and its position, you can initialize it with a single positioned argument*
You could also use generics if you want to use the same class for multiple types.
* Assumes the code is in Kotlin. Positioned and default arguments don't work from Java code.
Here's how to overwrite a getter method in Kotlin
class Person {
var age: Int = 0
get() = if (field < 0) 0 else field
}
The attribute is accessed directly
fun main(args: Array<String>) {
val p = Person()
p.age = -28
println(p.age) //0
}
val cannot be reassigned compile time error var variable. Can't we change the array value?
Error
Array.kt:11:3: error: val cannot be reassigned
Code:
import java.util.Scanner
fun main(args: Array< String>){
println("Enter the no")
val scanner = Scanner(System.`in`)
var nos = Array<Int>(5){0}
var i : Int = 1
for (i in 1..3){
nos[i] = scanner.nextInt()
i = i+1
}
println("Given values $nos")
}
The for (i in 1..3) ... statement redefines i for the scope of its body, where it becomes a val (it's actually a separate variable that shadows the i declared outside the loop).
You can fix the code by using different names for these variables, or, in your case, by simply removing var i: Int = 1 and i = i + 1:
val scanner = Scanner(System.`in`)
var nos = Array<Int>(5) { 0 }
for (i in 1..3) {
nos[i] = scanner.nextInt()
}
println("Given values $nos")
UPD (answering to the comment): You can iterate in the opposite direction or using a non-unit step by building a progression with functions downTo and step, both described here in the reference.
var i : Int = 1
for (i in 1..3){
nos[i] = scanner.nextInt()
i = i+1
}
In this code you declared not one, but two variables with the name i because the for header creates its own declaration. Within the loop, only the version declared in the for header is visible, and that one is a val by definition.
Having said that, I'm unclear on what you were trying to achieve since everything looks like it would work just the way you want it without trying to update i in the loop.
I'm curious about what is the suggested way to define member functions in Kotlin. Consider these two member functions:
class A {
fun f(x: Int) = 42
val g = fun(x: Int) = 42
}
These appear to accomplish the same thing, but I found subtle differences.
The val based definition, for instance, seems to be more flexible in some scenarios. That is, I could not work out a straight forward way to compose f with other functions, but I could with g. To toy around with these definitions, I used the funKTionale library. I found that this does not compile:
val z = g andThen A::f // f is a member function
But if f were defined as a val pointing to the same function, it would compile just fine. To figure out what was going on I asked IntelliJ to explicitly define the type of ::f and g for me, and it gives me this:
val fref: KFunction1<Int, Int> = ::f
val gref: (Int) -> Int = g
So one is of type KFunction1<Int, Int>, the other is of type (Int) -> Int. It's easy to see that both represent functions of type Int -> Int.
What is the difference between these two types, and in which cases does it matter? I noticed that for top-level functions, I can compose them fine using either definition, but in order to make the aforementioned composition compile, I had to write it like so:
val z = g andThen A::f.partially1(this)
i.e. I had to partially apply it to this first.
Since I don't have to go through this hassle when using vals for functions, is there a reason why I should ever define non-Unit member functions using fun? Is there a difference in performance or semantics that I am missing?
Kotlin is all about Java interoperability and defining a function as a val will produce a completely different result in terms of the interoperability. The following Kotlin class:
class A {
fun f(x: Int) = 42
val g = fun(x: Int) = 42
}
is effectively equivalent to:
public class A {
private final Function1<Integer, Integer> gref = new Function1<Integer, Integer>() {
#Override
public Integer invoke(final Integer integer) {
return 42;
}
};
public int f(final int value) {
return 42;
}
public Function1<Integer, Integer> getG() {
return gref;
}
}
As you can see, the main differences are:
fun f is just a usual method, while val g in fact is a higher-order function that returns another function
val g involves creation of a new class which isn't good if you are targeting Android
val g requires unnecessary boxing and unboxing
val g cannot be easily invoked from java: A().g(42) in Kotlin vs new A().getG().invoke(42) in Java
UPDATE:
Regarding the A::f syntax. The compiler will generate an extra Function2<A, Integer, Integer> class for every A::f occurrence, so the following code results in two extra classes with 7 methods each:
val first = A::f
val second = A::f
Kotlin compiler isn't smart enough at the moment to optimize such kind of things. You can vote for the issue here https://youtrack.jetbrains.com/issue/KT-9831. In case you are interested, here is how each class looks in the bytecode: https://gist.github.com/nsk-mironov/fc13f2075bfa05d8a3c3
Here's some code showing how f and g are different when it comes to usage:
fun main(args: Array<String>) {
val a = A()
exe(a.g) // OK
//exe(a.f) // does not compile
exe { a.f(it) } // OK
}
fun exe(p: (Int) -> Int) {
println(p(0))
}
Where f and g are:
fun f(x: Int) = 42
val g = fun(x: Int) = 42
You can see that g is an object that can be used like a lambda, but f cannot. To use f similarly, you have to wrap it in a lambda.