Home > OS >  How to pass a variable from main function to another function and modify it? (Kotlin)
How to pass a variable from main function to another function and modify it? (Kotlin)

Time:02-18

I am aware that an argument passed to a function will be seen as "val", even if the variable was initialized as "var". But this has been a problem for me. In this example code below, I want to modify the value of variable "num" by using the function "changeNum". But of course, Kotlin won't allow me to modify it. How do I get around this? How can I use the function "changeNum" to modify the variable "num"?

fun main() {
    var num: Int = 5
    changeNum(num)
}

fun changeNum(num: Int){
    num  = 2
    print(num)
}

CodePudding user response:

Kotlin is pass-by-value, so you can't do that directly with primitive types like Int.

The usual approach is to just return a new value instead of modifying what you receive as argument (a functional approach). It makes it clearer from the calling code's perspective:

fun main() {
    var num: Int = 5
    num = changeNum(num)
}

fun changeNum(num: Int): Int {
    val newValue = num   2
    print(newValue)
    return newValue
}

If you really want to mutate the variable instead of returning a new value, here are 2 approaches I'm thinking of to do this:

  1. put all the code operating on this value into a class, and make the local variable a property of that class (this is the OO approach)
  2. put this primitive variable into a class, and pass an instance of that class

Option 1 would look like this:

class SomeClass(var num: Int) {

    fun changeNum() {
        num  = 2
        print(num)
    }
}

fun main() {
    val container = SomeClass(5)
    container.changeNum()
}

Option 2 would look like this:

class SomeMutableContainer(var num: Int)

fun main() {
    val container = SomeMutableContainer(5)
    changeNum(container)
}

fun changeNum(container: SomeMutableContainer) {
    container.num  = 2
    print(container.num)
}

CodePudding user response:

It's possible to do this in Kotlin with a property

import kotlin.reflect.KMutableProperty0

var num = 1

fun main() {
    println(num)
    changeNum(::num)
    println(num)
}

fun changeNum(numProperty: KMutableProperty0<Int>) {
    numProperty.set(12345)
}

>> 1
>> 12345

A KMutableProperty0 represents a basic var, so you can pass in a property reference using the ::num syntax (same as how you'd pass a function reference). That way, instead of passing the current value, you're providing the function with a reference to the property itself, and then you can call set on it.

But the question is, do you really want to do this? Or are you overcomplicating something that should be done in a more simple way, or a more readable one? You can't actually do this with a variable, like you're trying to do inside fun main(), only properties on an object (top-level vars, basically) - but even if you could, why wouldn't you just do this instead?

fun main() {
    var num: Int = 5
    ...
    num = changeNum(num) // this would need renaming but y'know
}

it's still a one-line call, your changeNum function can still have side effects, do validation etc, it just returns the result instead of setting it as a side effect. This is a lot easier to follow, especially when it's the usual way of setting a value on a thing.


If you really want to use references, but making them top-level in your class is messy, then maybe consider creating a state object instead:

import kotlin.reflect.KMutableProperty0

data class AllThemNums(var num1 :Int = 1, var num2: Int = 9999)

fun main() {
    val nums = AllThemNums(num1 = 5)
    changeNum(nums::num1)
    println(nums)
}

fun changeNum(numProperty: KMutableProperty0<Int>) {
    numProperty.set(numProperty.get()   2)
}


>> AllThemNums(num1=7, num2=9999)

you could even put the changeNum function inside the data class!

  • Related