Dear all. Why does Kotlin force parameter variable...
# getting-started
g
Dear all. Why does Kotlin force parameter variables to be constants,
val
? Kotlin does not have a concept of a "pointer to a const", therefore I can change the referenced value, unless it is immutable. I mean,
val
parameter variable does not amount to much unless the referenced value is immutable.
v
Can you show an example? Parameters have neither
var
nor
val
, if you try to use it, you get
... on function parameter is prohibited
g
Yes, they are implicitly
val
and Kotlin does not allow to make them
var
.
v
Well, probably because it is anyway bad practice to assign a value to a function parameter and was often the source of bugs in languages which allow it. πŸ€·β€β™‚οΈ
g
I can modify the referenced value, unless it's immutable.
v
Yes, of course
g
What is the difference between assign a different value to a parameter and changing the referenced value?
I think none.
v
That's totally different
One would assign a value to the parameter, the other modifies the object that was passed in
g
how so? What's important is the data. I can change the data both by assigning a different value or modifying referenced data.
v
... no
πŸ™‚
We probably have to agree to disagree here.
g
not really
v
Oh, so you agree to me? Great πŸ™‚
g
C has a concept of pointer to a constant data.
if parameter variable type is constant pointer to a constant data , then I can neither re-assign the variable, nor modify the data it points to.
v
Well, Kotlin is not C, but Kotlin πŸ™‚
g
That was to your comment "it's totally different"
v
You can hardly compare a high-level object oriented language to a low-level non-object oriented language
g
It's not different, people thought about it and thought about a special construct for that, namely pointer to constant data.
v
That was to your comment "it's totally different"
Doesn't really rely to that. Even with that statement it doesn't change that it is something completely different. πŸ™‚
We are not talking about C with pointers, we are talking about Kotlin
g
It's the way to define at call site that something should not be modified. That is, to make a parameter really constant. Which is equivalent to constant reference to immutable data in Kotlin.
v
Again, that is in C
In Kotlin you cannot call site immutability
I'm not aware of any object-oriented language where you can
If you want the situation changed, feel free to open a YouTrack issue in the "Language Design" subsystem of the Kotlin project. πŸ™‚
πŸ‘ 1
g
What I mean, is that unless the reference is immutable, constant variable does not make the variable really constant.
v
Noone assumes that the variable is constant just because the parameter cannot be written to
No
val
-thing in Kotlin is immutable
It's always just that variable / field / property
g
But what is the point of making the parameter
val
then?
v
As I said, to disallow assigning a different value to the parameter. It is a parameter, not a variable.
g
ok, I cannot assign a different value, but I can modify the value. Which is effectively the same thing.
v
Probably to prevent bugs that happened often in languages that allow it, but that is just a guess, I don't know what the language designers intended. πŸ™‚
βž• 1
ok, I cannot assign a different value, but I can modify the value. Which is effectively the same thing.
No, that's a completely different thing
g
What are the situations in which it would make a difference?
v
And as I said, we probably have to agree to disagree on this, because you will not change my mind as it makes not sense to me what you say, and neither will you change your opinion, so πŸ€·β€β™‚οΈ
What are the situations in which it would make a difference?
They are just completely different things to do
One is changing the instance you refer to, one is changing what instance you refer to. That's just completely different things.
With your argumentation
val
would make sense nowhere, also not on fields / properties.
Because also there you can change the instance details if it is not immutable, so why should you not be able to change the referred to value?
g
val
parameter to me seems like a guarantee that if you modify it, you modify the same object.
val
parameter does not mean that you won't modify the parameter value.
s
Something that can sometimes help if you're coming to Kotlin (or Java) from other languages is to note that Kotlin is always "pass by value"; in other words, when you call a function, the function argument always gets a new copy of the value. The confusion can come because the value you're copying into the new parameter can be an (immutable) reference to some (mutable) object on the heap. But mutating that object does not do anything to the variables and parameters that contain references to it, and if you change one of the variables you're just pointing it at a new object, not changing the original object.
Concisely put: it's pass-by-value, but the value is a reference.
v
That's his point @Sam. He said, "as it is pass-by-value anyway, why am I not allowed to re-assign the parameter". πŸ™‚
s
Interesting question, and I think Java actually allows that, so I guess Kotlin made an explicit choice not to
v
Yes, and as I said, I guess because it is bad practice even in Java where it is allowed and was often a source of bugs and misunderstandings. And there is virtually no cases where you would win anything over just declaring an additional local variable.
πŸ‘ 1
s
Sounds like I was actually the one getting confused then πŸ˜„ you basically had it all covered
πŸ‘Œ 1
t
ok, I cannot assign a different value, but I can modify the value. Which is effectively the same thing.
I think the point is this assumption, to me this is like saying that I can enter my home by opening the door or by smashing it, I achieve the same result, at least for an external observer (I am now inside), but I would hardly call it "the same thing"
g
k
In Kotlin, as well as Java, immutability is a property of the class. It's not something that you can declare at the point of instantiation; it's something you build into the design of the class.
g
Yes I understand.
This is a proposal for usage site immutability.
h
Would your proposal mean that for each class the compiler needs to know what subset of its interface is mutating? For properties the split seems obvious: setters are mutating, getters are not. But actually getters could have mutating side effects [1]. Aside from properties, how are you going to determine whether you're allowed to call some method on the passed object? If you know the implementation, I suppose you might be able to check if it mutates, but there are plenty of cases where you don't know what implementation is called [2], and hence I suppose the compiler will have to assume it could be a mutating implementation and not allow calling it. [1]
Copy code
class A {
    private var _foo = 0
    val foo: Int get() = _foo++
}

fun bar(immutable a: A) {
    a.foo // error?
}
[2]
Copy code
interface I {
    val x: Int
    fun foo()
}

class A: I {
    override var x = 0
        private set
    override fun foo() {}
}

class B: I {
    override var x = 0
        private set
    override fun foo() { x++ }
}

fun bar(immutable i: I) {
    i.foo() // error?
}
g
@Huib Donkers classify each method of the type, whether it's mutating or not. If there are implementations of the interface that are mutating, consider the interface mutating.
basically, yes, what you said.
k
classify each method of the type, whether it's mutating or not
That's basically how C++ does it with its
const
and
mutable
keywords. In C++ this works well, but I don't think Kotlin has the same ideology.
l
You don't need mutable parameters, because you can always shadow the argument. That makes the typical use of modified arguments unnecessary:
Copy code
fun foo(arg: String? = null) {
  val arg = arg ?: "some other value"
  // ... use arg here without worrying about using the original value
}