Suspend variables (suspend val, suspend var)

I was thinking about submitting a KEEP for suspending variables and values and came here to give it a discussion.

What I’m suggesting is the ability to make a variable’s getter and setter suspending, thus making the variable itself suspending.
For example,

    suspend var kotlinVersion:Int
    get() { // a suspending get
       return api.getKotlinVersion()
    }
    set(value) { // a suspending set
        api.setKotlinVersion(value)
    }
    
    suspend fun addToKotlinVersion(){
        kotlinVersion = kotlinVersion + 1 // will get the kotlin version from API, increase it by one and then        submit it again to the API.
    }

Any call to this variable needs to be handled in a suspending function.
One of the usages for these types in my mind is variable delegates:

    suspend var kotlinVersion:Int by KotlinVersionHandler() // SuspendingReadWriteProperty of Int

The Kotlin generated code for these variables contains suspending functions, just like regular suspending functions.
Abstract variables with suspend modifier can exist in interfaces and abstract classes. The implementation classes need to define them as override suspend var ....

Notes:

  • The cannot be added as constructor values and can only exist in the body of classes, especially for data classes, since functions like equals cannot be suspending.
  • Type of these fields needs discussion, since in the above example, type of the kotlinVersion is not really an Int (it is really and Int in a suspending environment). This gets more tricky with Java interoperability.
  • The suspending part can be specific to the getter or setter part, for example, suspend var kotlinVersion:Int which has a suspend get() {} and a regular set function, but I think that would make things complicated.
2 Likes

@adibfara
Please consider coding conventions, suspending function is not properly “cheap to calculate”.

4 Likes

I asked for the same feature about a year ago: Suspend properties
It didn’t seem to get much attention and after a while I decided that I don’t really like the idea any more. As @fvasco pointed out, the coding conventions state that properties should be “cheap to calculate” and I would go even further and say, they should only contain trivial calculations.
Suspend does not really fit well with this idea of properties.

As far as I remember there have been suspending properties in a early version of coroutines. If I remember correctly, they removed it because they were not that well supported yet.

I guess that makes sense. Although in a way, delegated properties (or even properties with custom getter and setters) can be expensive to calculate. But I do get your point, since accepting suspending variablse would contradict the cheap rule, since they are not cheap by nature.
Everything aside, suspending delegated variables seem really cool, I’m not sure the cheap calculation should apply to them too, since they are lazy and that would indicate that they might not be so cheap.

I consider interesting the asynchronous delegates, something like: val result by deferred, this is really similar to the blocking version val result by future, so this considerations are debatable.

Synchronous and asynchronous worlds do not fit well together, blue and red functions are -after all- incompatible, you already mentioned data class.

Finally Kotlin’s coroutine library enriches suspending functions with coroutine scopes, this makes harder to implement a suspend lazy{ ... }, I already exposed some concerns in issue #1065.