To me, 'var' and 'val' look (optically) almost the same. Theay are both 3 chars wide and start with 'va'.
I can image that occasionally they can be confused.
What about 'final' or 'const'?
Of course, there reasons to have it that way - it's fast to type, but 5 chars instead of 3 will do as well.
And, 'val' doesn't sound as opposite of 'var': var stands for 'variable', so something that can not be changed.. is not value but is a 'constant'.
'val' could also imply that something is passed by value..
+0
(I was fine with "val" as it resembles Scala and I like similarities in languages and the IDE could color "val"/"var" differently but "const" isn't bad either.)
I think 'val' and 'var' are fine. I never had a problem with them in Scala. But if there really has to be a change I agree that 'var' should change to something like 'mutable'. It should be easier to create final variables than mutable ones.
In relation to the other thread I posted about var's being SharedObject, I'd rather see var get changed to something like 'mutable', or maybe even 'let x = ...' over changing the val but either way would be acceptable.
However, if we’re looking at changing val/var semantics, has anyone thought about lexically scoped val’s? Something maybe like:
let (x = 5, name = “Mark”) {
doSomethingWith(x, “$name was here}”)
}
here, the immutable vars are bound to the context of the closure, this style of construct could also work well for ARM blocks, at the end of the closure call .close() on any let’d variables.
let (reader = BufferedReader(FileReader(File(“foo.txt”)))) {
// something with reader
} // reader.close() happens here?
What sort of problems do you encounter with it? Or was it more a "it didn't feel right"? I could see you one might end up a lot of nested code quite easily, but that might just serve to yell "refactor" to you :)
First of all, it's hard to make general enough: simple 'let' is good, but what about 'if' and 'custom control structures' like forEach or 'try with resources' that you proposed?
Also, having two disconnected ways of defining an immutable variable ('val' and 'let') feels wrong.
My bad - I should have made it clear that I assumed "changing val" implied deprecating/removing val in favour of let.
One generic way I was thinking it could be implemented, from a very naive perspective is that:
let (x = 5, name = “Mark”) {
///
}
under the covers generates the equivalent of something like:
class $1(val x: Int, val name: String) : Closure {
fun run() {
// this has access to immutable, class local vals x and name
}
}
$1(5, “Mark”).run()
I’ve not looked at how the closures are actualy generated so not sure off hand if this is anything like whats really done currently. Altho, given this isn’t really a closure to pass around, it could just generate a method:
No, const does not describe the current semantics: this value is read-only for you, i.e. it is not a variable for you.
There is a subset of cases where val is effectively a constant value, so a new keyword or const may be useful for that subset. But using another keyword must not affect source or binary compatibility when switching from val to the other keyword, or vice versa.
Based on what you’ve just stated, the semantics of “val” (i.e. a location in memory that is not mutable) exactly parallels the notion of a “const”. Can you describe any situation where this is not the case?
As far as the ABI is concerned, swapping out this keyword does not affect the size or location of the stored value in memory relative to it’s original location in legacy code.
On a separate note, I just realised this discussion is 7 years old… Lol! Thanks a lot Google Search!
I emphasized the important part in my previous post: for you. The value is not mutable for the client seeing val. Depending on how the val is implemented, it is possible that the value can be changed by someone else.
In this example foo is read-only for main, but it can definitely change (note: this can be written down in a better way, but I split the var and val for clarity):
class C {
private var fooImpl = 0
val foo: Int
get() = fooImpl
fun inc() {
fooImpl++
}
}
fun main(args: Array<String>) {
C().run {
println(foo)
inc()
println(foo)
}
}
Output:
0
1
This is simply how Kotlin works. I am not attached to how this works, but a lot of existing code relies on these semantics so changing the semantics is not an option.
If there really is a need to communicate to a client that a value will never change, then a new construct (keyword, etc.) needs to be added.
I still believe const is a valid construct in this scenario. This property does declare a backing store and therefore it’s essentially a function that returns a immutable value for both the developer and the end user.
Even if the code was changed to add a custom setter to this property, I’m not sure Kotlin would allow it as it would break the notion of ‘val’. Which consequentially is also the notion of ‘const’.
I think one of the real problem with using ‘const’ is that Kotlin already defines the keyword as a modifier that can be combined in conjunction with ‘val’ to declare compile time constants. However that might simply be an artifact of a deduction not currently being made by the current iteration of the Kotlin compiler. Most compilers (take gcc compilers supporting C++1x) will try to inline any variable declarations that would otherwise be immutable during the variable’s lifetime.
You are correct that an immutable value is returned. But this is because all functions in Kotlin return simple values (primitives or references to objects), and simple values always have copy semantics. I am assuming that the semantics are the same on all platforms here.
I now understand what you want, you would like const to work sort of like it does on C++. Am I correct that you want to prevent clients that receive a const reference from calling functions that are not const on that reference? I think this can easily be solved using an additional interface. See the collection interfaces for examples.