If your 'let' doesn't propagate so that immutable collections are used, it's not very valuable. Just like 'final' in Java doesn't prevent anyone from mutating your ArrayList. Using 'val' instead of something more suggestive like final/const/'not mut' seems a lot nicer to me. (Edit: and indeed Kotlin having "mutableListOf" and "listOf" separation is a good step in readability. The val/var before either of those is less important.)
val/var/const/whatever only describe the reference, not the value. It doesn't really make sense for that annotation to, say, swivel a collection between ImmutableList and MutableList.
Now, you might be right that it's confusing, this difference between reference mutability and value mutability. I see beginners struggle with it in Javascript's new let vs const all the time.
2. Java does a lot with the keyword 'final'. I guess here you're talking about the concurrency behaviors of it? Does it bother you that you can remove 'final' via reflection?
3. It's still useful (e.g. not needing to use yoda-style ifs in languages where you can assign inside an if expression Just In Case you forget an =), but not very. That's my whole point.
1. the issue is one of visibility; e.g. you can initiate and pass / share String objects safely between threads without synchronization or worries because underlying String there's a final char[] backing it.
What `final` guarantees is that the variable will be initialized and visible (along with all its referenced objects) before the class constructor is finished. Without this guarantee you'd need `volatile` semantics or locks, which are more problematic.
2. yes, I'm talking about multi-threading; if the user removes "final" via reflection, or modifies final references via reflection, then it gets what he's asking for; but no, it does not bother me because I never do that and I stay away from libraries using reflection anyway.
I thought that's how the majority of languages worked. It just means the variable cannot be changed to reference a different value. It does not make the value immutable.
It really depends on the language. 'const' in C works differently from 'const' in other languages (even C++, which has some great 'const' use cases that make guarantees about whether values will change, not just about the symbol binding), they both work differently than 'final'. Similar confusions with 'static'. If all you want to say is "cannot reassign this symbol", then 'val' is great and sidesteps this whole history of readability and meaning confusion.
In Rust, it does (in general) make the value immutable. Most mutations of values in Rust are done through mutably borrowing the value, which you can't do when the value is defined with `let` rather than `let mut`, the exceptions being things like `Mutex`, which gives you a value that can be mutably borrowed when you acquire the lock.