Merging val & var

Currently the writer must decide whether to use val or var within its code and then IDE warns them if val may be used instead of var or if var needs to be used instead of val.

I think we could merge val and var into single var and let this IDE feature be shifted towards compiler so compiler decides whether val or var is necessary. Is there any specific reason why not?

  1. This would prevent accidental leaving var where val could be used.
  2. Generally less need to think about the language and the writer might focus more on the code.
  3. Less comments on merge requests.
  4. Avoiding things like (note, this is example, I know it can be written more nicely and functionally):
    fun appendInfo(string: String) {
        var string = string // this can be avoided
        for (val info : infoList) {
           string += info
        }
        return string
    }

The difference between var and val is in my opinion not one to primarily make things easier for the compiler, but for the programmer themselves - defining and knowing if a variable is mutable or not is a nice tool to have, and one that can prevent bugs by itself.

Your shown example seems not based upon val/var, but upon the immutability of function parameters - which is a different topic that also has been addressed a couple times.

2 Likes

Remember: val only indicates that the value is read-only for you. It may still be mutable (i.e. the value may change between reads). But in many cases vals are also immutable (e.g. a parameter).

val exists to enforce immutability. Only developer intent can make immutability choice crystal clear (well, not quite because it locks only reference, but that’s a first step).

Example: merging val and var would make impossible to know if a data class is immutable or not :

data class PersonView(val name : String, val surname : String)
val myView = pairView("Duck", "Donald")
// Compiler error : cannot reaffect immutable reference. Without val keyword, there's no way to guess it
myView.name = "Duck" 

If you need more information about why it needs to be explicit, I think you can check another language design choice : Rust. Their Ownership/Borrowing system needs developer to unambiguously specify if a the reference is mutable or not, to know which borrowing (reference sharing) strategy is allowed.

Also, I agree with @dfriehs, it’s a quick and comfortable way to know if a reference in code will be reaffected or not (that’s really important for debugging I think).

1 Like

Please, stop saying that. It confuses a lot of other developers. In the examples you give, the vals happen to be immutable, but it is not an inherent feature of val.

val means: You can read it, but you cannot change it. Somebody else might be able to change its value though, so do not assume that the value will always be the same.

I can understand the confusion about vals sometimes being mutable and sometimes being immutable, but we should accurately describe things to help everybody understand how Kotlin works, and what it does and does not provide for you.

1 Like

Well, is val really immutable in Kotlin/Native backend?
With threading policy “Frozen or ThreadLocal”.

You’re right, that’s confusing.
But, IMHO, what is confusing is not the term. All terms like constant, read-only and immutable needs to be contextualized : what is not changeable ? The reference to the object or its structure (i.e: the values it holds) ?

“You can read it, but cannot change it”. Sorry, but the same mistake exists here. You cannot change the reference defined by the val, but if the object defines writable properties, you can change things into it. So, is the “read-only” term really clearer ?

What needs to be made clearer is not the term, it’s what it reports to. That’s the effort that needs to be done : be aware what we’re talking about. val and var configure the object reference, and only that. And so forth, val enforces reference immutability, and only that.

I agree that the mutability of referenced objects also needs to be communicated. Unfortunately (and understandably: different semantics are possible, satisfying different developers and having a different impact on the implementation effort) Kotlin does not have a way to do that.

In specific contexts. For example: local variables, properties of classes (which do not have overrides for the getter), etc.

You can never assume that a val reference property of a type is immutable. You may not be able to change it, but it could change. In principle you need to retrieve it every time you want to use it, unless it is documented that it is guaranteed to always be the same.

Neither the compiler nor the JVM really needs this information. The existence of the val keyword for locals is there purely to improve code quality. It stops you from modifying values without intending to.

In general you should prefer val over var. The editor will warn you if you use var without needing to

This is a feature where you want the language to help you keep your code correct. Kotlin is quite opinionated in that.

The reason why parameters should be immutable is because making them immutable reduces the difference between value and reference semantics. In particular it is common for people to assume that they can change the original by changing the parameter. If you give good names you will find that the names of the strings (parameter, variable) are going to be different anyway (something like, baseString and appendedInfoResult)

1 Like