Kotlinlang: val as optional declaration

on the matter of locally scoped function declarations which are extremely constrained in terms of modifiers, limited almost exclusively to

val foo:Any=thing()

the language could be made ever so slightly more compact, readable and sensible by making the ‘val’ function-scoped declaration tokens an optional suggestion to hint that what we want is to declare

foo=thing()

or

(foo1,foo2)=thing()

I find no reason to believe that in the scope of a function this would impose any backwards compatibility challenges or significantly challenge the implementation of the language AST’s for interactive editing.

1 Like

Removing val or var removes the ability to just Ctrl+F (or grep) and search “val name”. Also, it makes this not context free anymore. Lastly, it clashes with normal assignments (and notably shadowing), means you cannot discern if it’s an assignment or a declaration, because you need to search up if it was declared before.

3 Likes

I’m in agreement here, those mentioned usecases could be spared by the option of not eliding val.
I don’t find those editor habits to be compelling language requirements however. in pure functions one might very rarely see val declared and in fact not appreciate the weight added by the keyword on succinct expressions. when porting java, and cranking out gui code the features you cite would benefit maintainers greatly and in fact, still be the option.

So the proposal is to allow dropping val in local functions for gains in clarity and readability?

I dislike this idea. I’m frustrated by how Python allows you to disguise declarations and assignments. It makes the code harder to read and opens up new kinds of bugs in Kotlin.

It makes the code harder to read since declaring a variable and assigning a variable look the same. When you see foo = thing(), is that the first time it’s been used and the code is declaring a new val? Am I assigning a var? And what is foo when I read that, val or var?

I guess I must pay the cost of searching through the rest of the code to see if there’s another declaration of foo… Oh no, now I have to search in a higher scope. I must now check my class, my supers, my static imports, and extension functions.

It’s also more bug-prone. What happens when I’m writing a local function and write foo = thing() to declare a new variable foo. Sure it works now, but what happens when I import another package that includes an extension function? What happens when another coder adds a foo member? I guess I won’t have to deal with this variable shadows one from a larger scope warnings anymore since the bug was created without warning.

I can’t think of a good argument for conflating declarations and assignments besides saving three keystrokes. Maybe there are passable arguments that I’m unaware of, but “clarity” and “readability” definitely aren’t them.

3 Likes

I double everything what @arocnies said. Also:

class Receiver {
    var receivedBytes: Int = 0

    fun receive() {
        ...
        recievedBytes = 10
    }
}

Kotlin tries to be a concise, but still rather an explicit language. It intentionally avoided language constructs which would make the code shorter, but at the same time it would make it more ambiguous.

2 Likes

Note that in many typed languages (including Java), local declarations tend to be much more verbose. With its short keywords and type inference, Kotlin has already made declarations as easy and concise as possible — only three fixed letters and a space! It could hardly be any shorter!

As mentioned above, allowing that to be omitted would remove protection against many types of error; it would not apply equally to both mutable and immutable values; and it would make code harder to read. (“Is this updating the value of an existing variable, or creating a new one?”) IIRC, Kotlin’s designers have been explicit that they value readability and safety over strict conciseness, where they don’t coincide.

For me, the saving of only three letters wouldn’t come anywhere near to justifying those losses.

2 Likes

i think we are discussing a matter of shadowing, a warning, and an illegal re-assignment error condition which would be come a warning.

that’s a good point, and a good catch, but i stand on pure functional programming gaining a benefit anyway, that the optional val/var carries with it provenance of declaration, and for f’s sake make shadowing a lot less legal anyways by that same provenance.