Kotlin: Unusual behavior when dealing with sets - kotlin

I have a simple data class which stores x and y coordinates of a position. My use case is that a single object of this class will be created and updated, and I need to maintain a set of unique coordinates.
I've simplified my use case in the following code where adding the pos object directly to the set vs passing the copy of the object result in different behavior (please see the comment in the code).
My initial hunch was that it could be because Java/Kotlin is passing the object by reference and the Set.add compares on reference. However, that doesn't seem to be true, if I set the pos.x or pos.y to any other value then the set.contains method returns false.
Question:
If the comparison is by reference then why does it fail when setting to a value other than what is given in the below code? If comparison is by hash code then why does the setByCopy not return true in the original case?
data class Pos(var x: Int = 0, var y: Int = 0)
fun main() {
val pos = Pos(0, 0)
val set = mutableSetOf<Pos>()
val setByCopy = mutableSetOf<Pos>()
pos.x = -9
pos.y = -6
set.add(pos)
setByCopy.add(pos.copy())
println(pos.hashCode())
pos.x = -8
pos.y = -37
// setting pos.y to any other value (e.g -35) will cause set.contains(pos) to return false.
println(set.contains(pos)) // true, but expected false.
println(setByCopy.contains(pos)) // false
}

As usual, modifying an element that's already in a set produces undefined behavior. This is not explicitly documented in Kotlin, but carries over from Java, where it's documented:
Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.
This means that anything can happen: it can work or not work randomly.

You're creating two objects, pos and then a separate one we'll call pos2. When you invoke copy() on an instance of a data class, you get a completely separate instance with its properties initialised to the same data.
Then you add each instance to a separate Set. Even though set contains pos and setByCopy contains pos2, if you call setByCopy.contains(pos) then that will return true because of how equality works for sets and data classes:
boolean contains(Object o)
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
That o.equals(e) bit is important - a data class automatically generates an equals() implementation based on its data, i.e. the properties in the constructor. So Pos(0, 0) == Pos(0, 0) is true even though they're different instances, because they contain the same data.
This is why setByCopy.contains(pos) is true - not because it contains that object, but because it contains an object that is equal to it.
When you update pos with different numbers, now pos and pos2 have different values for their data properties - they're no longer equal, so setByCopy.contains(pos) returns false.
set.contains(pos) still evaulates to true because that set contains the pos object. When you updated that object, the reference in the set is pointing to that same object, so of course it's equal to itself! If you wanted to create a distinct, separate instance that doesn't change when you update pos, then that's what copy() is for

Related

Kotlin val difference getter override vs assignment

I started playing arround with Kotlin and read something about mutable val with custom getter. As refered in e.g here or in the Kotlin Coding Convention one should not override the getter if the result can change.
class SampleArray(val size: Int) {
val isEmpty get() = size == 0 // size is set at the beginning and does not change so this is ok
}
class SampleArray(var size: Int) {
fun isEmpty() { return size == 0 } // size is set at the beginning but can also change over time so function is prefered
}
But just from the perspective of usage as in the guidelines where is the difference between the following two
class SampleArray(val size: Int) {
val isEmpty get() = size == 0 // size can not change so this can be used instad of function
val isEmpty = size == 0 // isEmpty is assigned at the beginning ad will keep this value also if size could change
}
From this answer I could see that for getter override the value is not stored. Is there something else where the getter override is different form the assignment? Maybe with delegates or latinit?
In your second example size is immutable value and therefore both ways are valid.
However variant with overridden getter get() = size == 0 has no backing field and therefore size == 0 is evaluated every time you access isEmpty variable.
On the other hand, when using initializer = size == 0 the expression size == 0 is evaluated during construction (check exactly when and how here - An in-depth look at Kotlin’s initializers) and stored to the backing field, of which value is then returned when you access the variable.
The key difference here is that in val isEmpty get() = ... the body is evaluated each time the property is accessed, and in val isEmpty = ... the expression on the right hand side gets evaluated during the object construction, the result is stored in the backing field and this exact result is returned each time the property is used.
So, the first approach is suitable when you want the result to be calculated each time, while the second approach is good when you want the result to be calculated only once and stored.

Is Kotlin "pass-by-value" or "pass-by-reference"?

As I know Java is pass-by-value from this post. I am from Java background I wonder what Kotlin is using for passing values in between. Like in Extensions or Methods etc.
Every time I hear about the "pass-by-value" vs "pass-by-reference" Java debate I always think the same. The answer I give: "Java passes a copy (pass-by-value) of the reference (pass-by-reference)". So everyone is happy. I would say Kotlin does the same as it is JVM based language.
UPDATE
OK, so it's been a while since this answer and I think some clarification should be included. As #robert-liberatore is mentioning in the comments, the behaviour I'm describing is true for objects. Whenever your methods expect any object, you can assume that the JVM internally will make a copy of the reference to the object and pass it to your method. That's why having code like
void doSomething(List<Integer> x) {
x = new ArrayList<Integer>()
}
List<Integer> x = Arrays.asList(1, 2, 3);
doSomething(x);
x.length() == 3
behaves like it does. You're copying the reference to the list, so "reassigning it" will take no effect in the real object. But since you're referring to the same object, modifying its inner content will affect the outer object.
This is something you may miss when defining your attributes as final in order to achieve immutability. You won't be able to reassign them, but there's nothing preventing you from changing its content
Of course, this is true for objects where you have a reference. In case of primitives, which are not a reference to an object containing something but "something" themselves, the thing is different. Java will still make a copy of the whole value (as it does with the whole reference) and pass it to the method. But primitives are just values, you can't "modify its inner values". So any change inside a method will not have effect in the outer values
Now, talking about Kotlin
In Kotlin you "don't have" primitive values. But you "do have" primitive classes. Internally, the compiler will try to use JVM primitive values where needed but you can assume that you always work with the boxed version of the JVM primitives. Because of that, when possible the compiler will just make a copy of the primitive value and, in other scenarios, it will copy the reference to the object. Or with code
fun aJvmPrimitiveWillBeUsedHere(x: Int): Int = x * 2
fun aJvmObjectWillBeUsedHere(x: Int?): Int = if (x != null) x * 2 else 1
I'd say that Kotlin scenario is a bit safer than Java because it forces its arguments to be final. So you can modify its inner content but not reassign it
fun doSomething(x: MutableList<Int>) {
x.add(2) // this works, you can modify the inner state
x = mutableListOf(1, 2) // this doesn't work, you can't reassign an argument
}
It uses the same principles like Java. It is always pass-by-value, you can imagine that a copy is passed. For primitive types, e.g. Int this is obvious, the value of such an argument will be passed into a function and the outer variable will not be modified. Please note that parameters in Kotlin cannot be reassigned since they act like vals:
fun takeInt(a: Int) {
a = 5
}
This code will not compile because a cannot be reassigned.
For objects it's a bit more difficult but it's also call-by-value. If you call a function with an object, a copy of its reference is passed into that function:
data class SomeObj(var x: Int = 0)
fun takeObject(o: SomeObj) {
o.x = 1
}
fun main(args: Array<String>) {
val obj = SomeObj()
takeObject(obj)
println("obj after call: $obj") // SomeObj(x=1)
}
You can use a reference passed into a function to change the actual object.
The semantics is identical to Java.
In Java, when you have an instance of an object, and you pass it to a method, that method can change the state of that object, and when the method is done, the changes would have been applied to the object at the call site.
The same applies in Kotlin.
For primitives value is passed, and for non-primitives a reference to the object is passed. I'll explain with an example:
The code:
fun main() {
var a = 5
var b = a
a = 6
println("b = $b")
}
prints: b = 5
Kotlin passes the value of a to b, because a is a primitive. So changing a afterwards won't impact b.
The code:
fun main() {
var a = Dog(5)
var b = a
a.value = 6
println("b = ${b.value}")
}
class Dog (var value: Int)
prints b = 6, because this time a is not a primitive and so the reference to the object (Dog) was passed to b and not its value. Therefore changing a would affect all objects that point to it.
In Java primitive types like int, float, double, boolean are passed to a method by value, if you modify them inside the receiver method they doesn't change into the calling method. But if the property/variable type isn't a primitive, like arrays of primitives or other classes when they are changed inside the method that receive them as parameter they also change in the caller method.
But with Kotlin nothing seems to be primitive, so I think all is passed by reference.
This might be a little bit confusing.
The correct answer, IMHO, is that everything passes by reference, but no assignment is possible so it will be similar to passing by value in C++.
Note that function parameters are constant, i.e., they cannot be assigned.
Remember that in Kotlin there are no primitive types. Everything is an object.
When you write:
var x: Int = 3
x += 10
You actually create an object of type Int, assign it the value 3, and get a reference, or pointer, named x.
When you write
x += 10
You reassign a new Int object, with the value 13, to x. The older object becomes a garbage (and garbage-collected).
Of course, the compiler optimizes it, and creates no objects in the heap in this particular case, but conceptually it is as explained.
So what is the meaning of passing by reference function parameters?
Since no assignment is possible for function parameters, the main advantage of passing by reference in C++ does not exist in Kotlin.
If the object (passed to the function) has a method which changes its internal state, it will affect the original object.
No such method exists for Int, String, etc. They are immutable objects.
No copy is ever generated when passing objects to functions.
Bear in mind, am quite new to Kotlin. In my opinion, primitives are passed-by-value, but objects are passed-by-reference.
A primitive passed to a class works by default, but if you pass an object from a list, for example, and that object changes, the class object changes too. Because, in fact, it is the same object.
Additionally, if objects gets removed from the list, the class object IS STILL A REFERENCE. So it can still change due to references in other places.
Example below explaines. You can run it here.
fun main() {
val listObjects = mutableListOf(ClassB(), ClassB(), ClassB())
val listPrimitives = mutableListOf(111, 222, 333)
val test = ClassA()
test.ownedObject = listObjects[0]
test.ownedPrimitive = listPrimitives[0]
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listObjects[0].isEnabled = true
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
listPrimitives[0] = 999
println("ownedObject: " + test.ownedObject.isEnabled +", ownedPrimitive: " +
test.ownedPrimitive)
}
class ClassA {
var ownedObject: ClassB = ClassB()
var ownedPrimitive: Int = 0
}
class ClassB {
var isEnabled = false
}
Since Kotlin is a new language for JVM, like Java it is pass-by-value. The confusing part is with object, at first it looks like that it is passed-by-reference but the actuality is that the reference/pointer itself is pass-by-value (a copy of a reference is passed to a method) hence when a method receives a reference to an object, the method can manipulate the original object.

What is the purpose of Unit-returning in functions

From the Kotlin documentation:
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value — Unit.VALUE. This value does not have to be returned explicitly:
fun printHello(name : String?) : Unit {
if (name != null)
print("Hello, $name!")
else
print("Hi there!")
// We don't need to write 'return Unit.VALUE' or 'return', although we could
}
What is the purpose of Unit-returning in functions? Why is VALUE there? What is this VALUE?
The purpose is the same as C's or Java's void. Only Unit is a proper type, so it can be passed as a generic argument etc.
Why we don't call it "Void": because the word "void" means "nothing", and there's another type, Nothing, that means just "no value at all", i.e. the computation did not complete normally (looped forever or threw an exception). We could not afford the clash of meanings.
Why Unit has a value (i.e. is not the same as Nothing): because generic code can work smoothly then. If you pass Unit for a generic parameter T, the code written for any T will expect an object, and there must be an object, the sole value of Unit.
How to access that value of Unit: since it's a singleton object, just say Unit
The main reason why Unit exists is because of Generic reasons.
Let's use the example from the Kotlin docs.
class Box<T>(t: T) {
var value = t
}
We can have
var box = Box(Unit)
This is why Unit returns a value so the Kotlin can infer it from the type passed into class initialization. Of course, you could also explicitly write it like this,
var box = Box<Unit>(Unit)
but all the same, it must have a return value.
Now, the void keyword in Java in Kotlin is Nothing. Nothing is the last but one type in the type hierarchy in Kotlin with the last one being Nothing? (Nullable Nothing). This does not return any value at all. Because it doesn't return any value at all, we can't pass it as a type in the above code.
var box = Box(Nothing) //This will return an Error
UNIT actually contains valuable information, it basically just means "DONE". It just returns the information to the caller, that the method has been finished. This is a real piece of information so it can be seen as the return value of a method.

F# Object constructor

After recently picking up a bit of C# after a long time of F#, I came to realise that 'object constructors' are a nice way of tricking oneself into believing they are dealing with a functional object.
Consider:
let x = new Something()
x.Key <- 1
x.Value <- 2
This feels very unclean because of the very obvious mutation of values. Especially if we keep our objects write once, it feels very unnecessary In C#, it is possible to initialise the object like this:
var x = new Something() { Key = 1, Value = 2 };
This looks nicer and actually it felt like I was using a record (almost), obviously its just sugar but its nice sugar.
Q. Assuming we have no control over `Something' (pretend its from some C# library), is it possible, in F# to use this shorthand initialisation, if not, why?
Yes, you can do that. It would look something like this:
let x = new Something(Key = 1, Value = 2)
The syntax is detailed in Constructors (F#) under the section "Assigning Values to Properties at Initialization".
Yes, F# support use cases similar to C# object initializers but F# approach is somewhat more generic.
F# specification 14.4 Method Application Resolution says:
(after method is successfully resolved) Build the resulting elaborated expression by following these steps:
For each NamedActualArgs whose target is a settable property or field, assign the value into the
property.
meaning that you can do things that C# doesn't allow
type Something() =
member val Key = 0 with get,set
member val Value = "" with get,set
static member Create() = Something()
let a = Something(Key = 1, Value = "1") // create instance with constructor, set properties afterwards
let b = Something.Create(Key = 1, Value = "1") // create instance using factory method, set properties afterwards

Difference between value parameter and reference parameter?

Difference between value parameter and reference parameter ? This question is asked sometime by interviewers during my interviews. Can someone tell me the exact difference that is easy to explain with example? And is reference parameter and pointer parameter are same thing ?
Thanks
Changes to a value parameter are not visible to the caller (also called "pass by value").
Changes to a reference parameter are visible to the caller ("pass by reference").
C++ example:
void by_value(int n) { n = 42; }
void by_ref(int& n) { n = 42; }
void also_value(int const& n); // Even though a reference is used, this is
// semantically a value parameter---though there are implementation
// artifacts, like not being able to write "n = 42" (it's const) and object
// identity (&n here has different ramifications than for by_value above).
One use of pointers is to implement "reference" parameters without using a special reference concept, which some languages, such as C, don't have. (Of course you can also treat pointers as values themselves.)
The main difference is whether the object passed is copied. If it's a value parameter the compiler must generate such code that altering the function parameter inside the function has no effect on the original object passsed, so it will usually copy the object. In case of reference parameters the compiler must generate such code taht all operations are done on the original object being passed.
A pointer is a low-level way of representing a reference, so passing a pointer (by value) is how languages like C typically achieve pass by reference semantics.
The difference is pretty simple: direct parameters are passed by value, and the receiver receives a copy of what is passed; meaning that if the parameter is modified by the receiver, these changes will not be reflected back to the caller. (This is often called, appropriately enough, pass by value, or by copy.
There are basically three kinds of parameters; pointer, reference and direct.
The difference is pretty simple: direct parameters are passed by value, and the receiver receives a copy of what is passed; meaning that if the parameter is modified by the receiver, these changes will not be reflected back to the caller. (This is often called, appropriately enough, pass by value, or bycopy.
Pointers are also passed by value, but rather than sending the actual value, the caller sends the address of the value. This means that by following this pointer, the receiver can modify the argument. Note that changes made to the actual pointer still aren't reflected back to the caller.
The final form, call-by-reference, is sort of a middle ground between these two approaches. Essentially it can be thought of as a pointer that looks like a value.
It is worth mentioning that at the core of it all, parameters are always passed by value, but different languages have different ways of implementing reference semantics (see Kylotans answer).
// Example using C
// bycopy
int multiply(int x, int y) {
return x * y;
}
void multiply_p(int *x, int y) {
*x *= y;
}
int main () {
int i, j, k;
i = 20;
j = 10;
k = multiply(i,j); // k is now 200
multiply_p(&i, k); // i is now 4000 (200 * 20)
return 0;
}
Pseudocode:
Pass by Value:
void setTo4(value) { // value is passed by value
value = 4;
}
int x = 1;
setTo4(x);
// x is still 1
Pass by Reference:
void setTo4(value) { // value is passed by reference
value = 4;
}
int x = 1;
setTo4(x);
// x is 4