Scala:返回方法中count变量的单独状态

Scala:返回方法中count变量的单独状态,scala,closures,constants,Scala,Closures,Constants,Scala新手试图实现一个名为“counter”的方法,其方法签名如下 该方法应该是一个无状态函数,因此当使用整数n调用它时,它将返回一个有状态函数。这个有状态函数在第一次调用时应该返回n,然后是n+1,然后是n+2,以此类推 计数器必须是独立的,以便运行计数器(1)两次可以产生两个互不干扰状态的函数 以下是我目前的情况: val counter : Int => () => Int = { // Complete definition below. var count

Scala新手试图实现一个名为“counter”的方法,其方法签名如下

该方法应该是一个无状态函数,因此当使用整数n调用它时,它将返回一个有状态函数。这个有状态函数在第一次调用时应该返回n,然后是n+1,然后是n+2,以此类推

计数器必须是独立的,以便运行计数器(1)两次可以产生两个互不干扰状态的函数

以下是我目前的情况:

val counter : Int => () => Int = {
   // Complete definition below.
   var count = 0

   n: Int => () => {
       var returnVal = n + count
       count = count + 1
       returnVal
   }
}
如何调用计数器的示例:

  assert ({ 
     val k1 : () => Int = counter (1)
     val k2 : () => Int = counter (2)
     val r1 : Int = k1 ()
     val r2 : Int = k1 ()
     val r3 : Int = k2 ()
     val r4 : Int = k2 ()
     val r5 : Int = k2 ()
     val r6 : Int = k1 ()
     (r1, r2, r3, r4, r5, r6)
  } === (1, 2, 2, 3, 4, 3)
  )
运行断言时,计数器的实现返回(1、2、4、5、6、6)

我相信这是由于k1和k2都指向同一个计数变量。但是,我不知道如何按照要求提供k1和k2各自独立的计数变量,以便它们“不会干扰彼此的状态”


我走对了吗?非常感谢您的指导。

您需要将定义的计数器方法的关键字从
val
更改为
def

def counter : Int => () => Int = {
   // Complete definition below.
   var count = 0

   n: Int => () => {
       var returnVal = n + count
       count = count + 1
       returnVal
   }
}
因为使用
val
,count变量只定义一次,这在定义counter方法时发生,因此稍后所有闭包都将共享此变量;使用
def
方法,每次调用计数器(n)时都会重新定义计数变量


如果在
var count=0
行之后添加println,则更容易看到这一点:

scala> val counter : Int => () => Int = {
          // Complete definition below.
          var count = 0
          println(count)

          n: Int => () => {
              var returnVal = n + count
              count = count + 1
              returnVal
          }
       }

0                                           // 0 is printed here
counter: Int => (() => Int) = <function1>

scala> val k1 = counter(1)                  // nothing prints here
k1: () => Int = <function0>

scala> val k2 = counter(2)                  // nothing prints here
k2: () => Int = <function0>
scala>val计数器:Int=>()=>Int={
//完整的定义如下。
变量计数=0
println(计数)
n:Int=>()=>{
var returnVal=n+count
计数=计数+1
返回值
}
}
0//0在此处打印
计数器:Int=>(()=>Int)=
scala>val k1=计数器(1)//此处不打印任何内容
k1:()=>Int=
scala>val k2=计数器(2)//此处不打印任何内容
k2:()=>Int=

您需要将定义的计数器方法的关键字从
val
更改为
def

def counter : Int => () => Int = {
   // Complete definition below.
   var count = 0

   n: Int => () => {
       var returnVal = n + count
       count = count + 1
       returnVal
   }
}
因为使用
val
,count变量只定义一次,这在定义counter方法时发生,因此稍后所有闭包都将共享此变量;使用
def
方法,每次调用计数器(n)时都会重新定义计数变量


如果在
var count=0
行之后添加println,则更容易看到这一点:

scala> val counter : Int => () => Int = {
          // Complete definition below.
          var count = 0
          println(count)

          n: Int => () => {
              var returnVal = n + count
              count = count + 1
              returnVal
          }
       }

0                                           // 0 is printed here
counter: Int => (() => Int) = <function1>

scala> val k1 = counter(1)                  // nothing prints here
k1: () => Int = <function0>

scala> val k2 = counter(2)                  // nothing prints here
k2: () => Int = <function0>
scala>val计数器:Int=>()=>Int={
//完整的定义如下。
变量计数=0
println(计数)
n:Int=>()=>{
var returnVal=n+count
计数=计数+1
返回值
}
}
0//0在此处打印
计数器:Int=>(()=>Int)=
scala>val k1=计数器(1)//此处不打印任何内容
k1:()=>Int=
scala>val k2=计数器(2)//此处不打印任何内容
k2:()=>Int=
首先,退房。TL;最重要的是,
val
只计算一次,因此,如果在到达要返回的函数之前在
计数器中定义计数保持变量,则不能真正依赖该变量

为了更清楚,我添加了括号以使模式匹配更加明显,并将该行分开,因为我们需要捕获传递到
计数器
的参数,并将其存储在我们返回的匿名函数的闭包中

val counter : Int => () => Int = {
  (n: Int) => {
    var count = n

    () => {
      val returnVal = count
      count = count + 1
      returnVal
    }
  }
}
首先,退房。TL;最重要的是,
val
只计算一次,因此,如果在到达要返回的函数之前在
计数器中定义计数保持变量,则不能真正依赖该变量

为了更清楚,我添加了括号以使模式匹配更加明显,并将该行分开,因为我们需要捕获传递到
计数器
的参数,并将其存储在我们返回的匿名函数的闭包中

val counter : Int => () => Int = {
  (n: Int) => {
    var count = n

    () => {
      val returnVal = count
      count = count + 1
      returnVal
    }
  }
}

谢谢,这更有意义。不幸的是,我必须按照作业指导原则保留val关键字。谢谢,这更有意义。不幸的是,我必须按照作业指导原则保留val关键字。这并不重要,但我会打
returnVal
a
val
。打个好电话@Jasper-M。这并不重要,但我会打个
returnVal
a
val
。打个好电话@Jasper-M。