Suggestion: Static local variables

C has static local variables, e.g.:

int count() { 
    static int count = 0; 
    count++; 
    return count; 
} 

This feature leads to much more concise code, the equivalent in kotlin would be:

var count = 0
fun count(): Int {
    count++;
    return count;
}

In kotlin, this unecessarily polutes the classes namespace, leads to problems with variable name clashing, and can give the impression that the variable is applicable to the whole class, when in fact it is only applicable to the function.

Static local variables would easily allow definitions of variables that are only applicable to a certain function, but still need to preserve their state between multiple invocations.

The compilation for this would be easy, for JVM just create a private field at class level perhaps prepended with the function name.

Drawbacks:
It may be confusing for people transitioning from java to understand that the variable keeps its value between invocations.

3 Likes

You can easily simulate that with an object:

object Counter {
  private var counter = 0
  fun count(): Int = counter++
}

I don’t think adding a feature for this to be much worthwhile.

4 Likes

Source compatible:

object count {
    private var count = 0;
    operator fun invoke() = ++count
}
6 Likes

I personally find this to be far less concise. It breaks the rules of where field-declarations can be made and the current-way of doing it is far cleaner in my opinion.

1 Like

Kotlin tries to discourage people from writing non-pure top-level functions, functions that depend on some mutable state. Kotlin has classes and objects to encapsulate mutable state and to work with it. C-style programming with mutable global state is still supported in Kotiln for a variety of reasons (you are allowed to write a top-level var, which is essentially static). However, it is non-goal for Kotlin to make this C-style programming easier. The ability to declare static variables inside functions is missing in Kotlin by design, not by omission.

11 Likes
fun count() = Count()
private object Count {
    private var count = 0
    operator fun invoke() = ++count
}

This would be better as you’re then not breaking any Kotlin naming conventions.

I haven’t had the need for such a feature but don’t you think giving me the option would be good? Should we not let the programmer decide how he’ll use the language instead of vice versa?

Static locals is a really bad idea.

6 Likes

JetPack Compose basically has static locals with some weird workaround, look at the following code:

@Composable
@Preview
fun app() {
    val basicallyStaticLocal = remember { mutableStateOf(true) }
    MaterialTheme {
        // UI code here
    }
}
fun main() = application { Window(onCloseRequest = ::exitApplication, title = "Example") { app() } }

So if JetBrain’s modern UI framework has a need for it, why not support it normally so it doesn’t have to be done weirdly like it is in Jetpack Compose? I just don’t get why the same company that’s limiting that functionality is also using it in something new and modern if it’s a really bad idea like as you claim it is.

2 Likes

In my case, static locals would be quite nice for immutable objects, such as Pairs, Regexes and Lists. Thus, I could encapsulate them in a method where they are used without repeated allocation of new ones.

2 Likes

+1
I created a similar thread few months ago : Auto extract final objects from code

A language should always provide a way to make optimized code at least as easily as badly optimized code.

1 Like

@sylvainspinelli your use case is a little bit different.

You need reusing the same value all the time, like a constant, but with a non constant expression. Theoretically the compiler could execute the code at compile time, if this is possible (no external references).

Instead the “counter” example needs a one time initialization and changes the value later.
If it’s not static, the value will start at the same initial value on each invocation.

Also, in your other thread it’s not discussed, why extracting all the resuse expressions can be a bad thing.

The main problem from my POV is not so much the work to move the wannabe-constants to some other file (e.g. we have a Constants.kt for that), but it breaks encapsulation.

From my POV you should be able to encapsulate constructs, that are only used inside a function (or even inside a block). It’s another kind of scoped variables. This makes completely clear to the reader, that he does not need to look if there is another usage of that thing, because it’s clearly not visible outside of the scope.

Another consequence is, that I can use the same name for the same thing in each function.
It just doesn’t make sense to have patternXYZ, patternABC, etc. if it’s always the same thing and the context makes the difference.
Something like this:

fun f1() {
  static val thing = initThing1()
  thing = doAction1With(thing)
}

fun f2() {
  static val thing = initThing2()
  thing = doAction2With(thing)
}

fun main() {
  f1()
  f1()
  f2()
  f2()
}