Skip to content

Allow marking functions as "input mutating"? #28

@yairm210

Description

@yairm210

Some functions change state - but only state that is passed to them as input

Example:

    fun addHelloWorld(list:MutableList<String>){
        list.add("Hello")
        list.add("World")
    }
    

    fun a(): MutableList<String> {
        val myList = mutableListOf<String>()
        addHelloWorld(myList)
        return myList
    }

A is obviously pure, even though it calls a function that changes state, because the change does not read or write any other external state, and the value passed in is local state - inaccessible from elsewhere.

This is important for performance reasons - the "readonly" version of the above is:

    fun getHelloWorld(): MutableList<String> {
        val list = mutableListOf<String>()
        list.add("Hello")
        list.add("World")
        return list
    }
    
    @Pure
    fun a(): MutableList<String> {
        val myList = mutableListOf<String>()
        myList.addAll(getHelloWorld())
        return myList
    }

where you pay allocation overhead for creating and destructing the extra list.

A third alternative that works, is passing in a lambda to do this for us:

    @Pure
    fun addHelloWorld(@Pure add: (String) -> Unit){
        add("Hello")
        add("World")
    }
    
    @Pure
    fun a(): MutableList<String> {
        val myList = mutableListOf<String>()
        addHelloWorld{myList.add(it)}
        return myList
    }

Why does this work?

  • The lambda is checked for purity in a() - acceptable, since a is allowed to mutate myList
  • When passing a @pure lambda, since the containing function is @pure the lambda is prechecked
  • Within addHelloWorld it's a function invoke

But this is a very different way of working, and our purpose is to not have to force users to change their code in order to get good validation results!

Problems:

  • Can't have just one marking - pure input mutators and readonly input mutators are different
    • an additional annotation, like @Pure @MutatesInput, kind of takes the meaning away from Pure
    • two annotations - @MutatesInputReadonly and @MutatesInputPure - feels bad
  • Need to ensure that values passed are mutatable by the passing function

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions