在Kotlin的静态函数中是否有一种方法可以在多次调用中重用变量?

huangapple go评论63阅读模式
英文:

Is there a way to reuse variables in Kotlin in static functions in multiple calls?

问题

我刚刚发现在Kotlin中函数参数是不可变的。我本来期望能够使用可变参数,但在官方文档中没有提到这一点。个人认为在Kotlin中应该有一种方法可以在多个静态函数之间重用单个变量。对于不可变参数,如何实现这一点呢?我尝试不返回被使用的值,只返回数组,重用像索引或在不同函数中使用的相同变量,而不需要访问其他函数的数据。就像在其他语言中,可以传递一个数据,但可能不会在其他函数中读取它,但支持在静态函数的范围内写入一个数据并使用它。

我尝试了Kotlin Playground,我期望有一个可变参数的选项,但没有找到。我尝试了数组和列表,并发现在Kotlin Playground中,成员可能会被设置,但原始数组或列表不能被修改。我的问题是这是否会编译通过。如果可以的话,我可以将所有变量都绑定到数组或列表中,然后随意设置它们。无论如何,问题是:在Kotlin中,如何实现一组静态函数重用像可变变量(var)一样的变量或多个变量?这是出于效率考虑,更多的变量意味着更多的垃圾回收,程序运行速度变慢,我更喜欢一个更快的程序。

英文:

I just found that function params are not mutable in Kotlin. I was expecting mutability with no mention of this in official documentation I found. Personally I think there should be some way to reuse a single variable across multiple static functions in Kotlin. How can this be with immutable params? I am trying for not returning values used, just arrays, reuse values like index of it or same variable used in different functions not needing access to data from other functions. Like in other languages a data thing can be passed around and used but maybe not read in other functions, but it supports writing a thing and using it within scope of a static function.

I have tried Kotlin playground, I expected a var param thing, none present. I tried arrays and lists and found in Kotlin playground, members may be set but not origin array or list. My question is whether this would compile or not. With that I could rig all variables to be in arrays or lists and set as I please. Anyway, question is: how can a set of static functions in Kotlin reuse a variable or variables like var in multiple calls? This is for efficiency sake, more variables, more garbage collection, slower programs, and I would prefer a faster program.

答案1

得分: 1

Kotlin不支持通过引用传递函数参数。参数总是被复制。这也不受Kotlin的主要目标平台支持:Java和JavaScript。

如果您真的想要这样做,可以创建一个简单的包装器并将其传递:

fun test(value: Wrapper<String>) {
    value.value = "foo"
}

data class Wrapper<T>(var value: T)

然而,这并不是真正的“Kotlin方式”。在Kotlin或Java等语言中,我们通常假设函数/方法接收参数并返回新值。我们可以修改传递的对象,如果函数的名称清楚地提到了这一点,这并不被认为是一种不良做法。但是通过参数返回结果或替换调用者的变量更典型于像C这样的语言,而不是Kotlin/Java。我相信Kotlin/Native对指针有一些支持,所以在那里可能是可能的。

英文:

Kotlin doesn't support passing function arguments by a reference. Arguments are always copied. It is not supported by the main target platforms of Kotlin as well: Java and JavaScript.

If you really want to do this, you can create a simple wrapper and pass it around:

fun test(value: Wrapper&lt;String&gt;) {
	value.value = &quot;foo&quot;
}

data class Wrapper&lt;T&gt;(var value: T)

However, this is not really a "Kotlin way". In languages like Kotlin or Java we assume functions/methods receive arguments and they return new values. We can modify passed objects and if the name of the function clearly mentions this, this is not considered a bad practice. But returning results through arguments or replacing variables of the caller, is more typical to languages like C, than Kotlin/Java. I believe Kotlin/Native has some support for pointers, so it could be possible there.

答案2

得分: -2

根据我理解,任何具有属性的对象都可以重复使用该属性,包括数组、列表和IntArray。然而,在Kotlin中,这不是首选方法,正如Louis Wasserman所说,这可能会对性能产生负面影响。

我理解的首选方法是创建一个带有伴生对象的类,在伴生对象中定义一个变量(var)和一个使用该变量的函数。如果需要静态函数和变量,可以使用 @JvmStatic 注解标记所有应该是静态的部分。我知道在Java中,第一个和第二个等效,第一个较慢,第二个较快。

第二种方法的唯一问题是每个变量只能同时执行一个函数调用。解决此问题的方法之一是为每个函数使用不同的变量。我发现数组和列表会根据函数调用而变化,并在函数调用之外保持变化,不管是 val 还是 var。

fun test(x: DoubleArray): DoubleArray {
    x[0] += 2.0
    return x
    //至少在JVM上可以工作
}

fun main() {
    val ar: DoubleArray = DoubleArray(2)
    println(test(ar)[0])
    println(ar[0])
    //两者在JVM上都打印出2.0
    println(ar[1])
}
class Test private constructor() {
    companion object {
        var variable: Double = 0.0
        fun test() {
            Test.variable = 2.0
        }
    }
}

第一个示例演示了如何允许使用数组或列表的部分。第二个示例演示了如何使用静态变量。我测试了这两种方法,并且它们在我可以在Kotlin Playground上使用的所有平台上都有效。

要重复使用变量,可以使用静态列表或者可能是数组,并传递一个用于使用静态变量的索引,以允许静态变量的异步操作。由于某些变量可能首先被更低索引使用,可能需要一个自由变量。根据我的经验,在Java中,函数速度排名如下:常规非静态函数较慢,静态函数会更改其参数居中,仅更改静态变量的静态函数最快。出于简单性考虑,你可以尝试使用居中的方法,但出于速度考虑,最好使用静态列表和变量的票务系统,就像这样:

class XE private constructor() {
    companion object {
        @JvmStatic
        var ints: IntArray = IntArray(1)
        @JvmStatic
        var freeInts: BooleanArray = BooleanArray(1) { true }
        @JvmStatic
        fun test(ticket: Int = 0) {
            XE.freeInts[ticket] = false
            XE.ints[ticket] = 2
            //使用 ints[ticket]
            XE.freeInts[ticket] = true
        }

        @JvmStatic
        fun getTicket(free: BooleanArray): Int {
            var index = 0
            while (!free[index] && index != free.size) {
                index += 1
            }
            return index
        }
    }
}

对于这个示例,应该有一个获取第一个可用票务的函数。我知道这段代码可以编译,我在Kotlin Playground上测试过,尽管排除了JS IR和Wasm之外的所有其他平台,但目前所有其他平台(JVM、JS、Canvas)都经过了测试。

英文:

From what I understand, any object with a property can have that property reused including like Array and List and IntArray. This is not a preferred way in Kotlin though and as Louis Wasserman said it may be a negative impact to performance.

As I understand it, a preferred way would be to have a class with a companion object and inside that companion object have a var thing and a function that uses that var thing. If I like want static functions and variables, use @JvmStatic to annotate all that should be static. I know that in Java equivalents first and second work, first is slower, second is faster.

Only problem with second is that only one function call may be done at once per variable. One fix for this could be use different variables per each function. I found that arrays and lists change based on function calls and stay changed outside of function calls, val or not.

fun test(x:DoubleArray):DoubleArray {
    x[0]+=2.0;
    return x;
    //Works here at least on JVM
}

fun main() {
     ar:DoubleArray=DoubleArray(2);
    println(test(ar)[0]);
    println(ar[0]);
    //Both print 2.0 on JVM
    println(ar[1]);
}
class Test private constructor(){
    companion object {
        var variable:Double = 0.0;
        fun test() {
            Test.variable=2.0;
        }
    }
}

That first one is how using an array or list part would be allowed. Second is how to do a static variable usage. I tested and both work on all platforms I could use on Kotlin Playground.

For reusing variables, using a static list or maybe an array and passing an index of static variables to use would allow async for static variables. As some may be lower index done first, a which is a free variable may be needed. In my experience, in Java function speed ranks in following order: regular not static slower, static that changes its parameters middle, static functions that only change static variables fastest. I may try middle for simplicity sake but for fastness sake, use a static list and variable ticket system. Like this:

class XE private constructor() {
    companion object {
        @JvmStatic
        var ints:IntArray=IntArray(1);
        @JvmStatic
        var freeInts:BooleanArray=BooleanArray(1){true};
        @JvmStatic
        fun test(Int ticket=0) {
            XE.freeInts[ticket]=false;
            XE.ints[ticket]=2;
            //Use ints[ticket]
            XE.freeInts[ticket]=true;
        }
        @JvmStatic
        fun getTicket(free:BooleanArray):Int{
            Int index = 0;
            while (!free[index]&amp;&amp;index!=free.size) {
                index+=1;
            }
            return index;
        }
    }
}

For this, a get first ticket available should be. I know this compiles, I tried on Kotlin Playground, all platforms I could. Like my tests in Kotlin Playground exclude JS IR and Wasm but all other platforms currently (JVM, JS, Canvas) were tested in.

huangapple
  • 本文由 发表于 2023年7月5日 00:01:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76614308.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定