【问题标题】:Scala: separate states of count variable inside returned methodScala:返回方法中计数变量的单独状态
【发布时间】:2017-07-08 11:01:33
【问题描述】:

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

该方法应该是一个无状态函数,这样当使用整数 n 调用它时,它会返回一个有状态函数。这个有状态的函数在第一次被调用时应该返回 n,然后是 n + 1,然后是 n + 2,等等。

计数器必须是独立的,这样运行 counter(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 提供它们自己单独的计数变量,以便它们“不会干扰彼此的状态”。

我在正确的轨道上吗?任何指导将不胜感激。

【问题讨论】:

    标签: scala closures constants


    【解决方案1】:

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

    def counter : Int => () => Int = {
       // Complete definition below.
       var count = 0
    
       n: Int => () => {
           var returnVal = n + count
           count = count + 1
           returnVal
       }
    }
    

    因为valcount 变量只定义一次,这发生在你定义 counter 方法时,所以以后所有的闭包都会共享这个变量;使用def 方法,每次调用 counter(n) 时都会重新定义 count 变量。


    如果在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>
    

    【讨论】:

    • 谢谢,这更有意义。不幸的是,我必须按照作业指南保留 val 关键字。
    【解决方案2】:

    首先,查看the difference between def and val。它的 TL;DR 是 val 只会评估一次,所以如果你在到达你想要返回的函数之前在 counter 中定义它,你就不能真正依赖一个计数持有变量。

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

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

    【讨论】:

    • 这并不重要,但我会将returnVal 设为val
    • 好电话@Jasper-M。
    猜你喜欢
    • 2018-11-17
    • 2011-01-19
    • 2015-09-09
    • 2018-08-16
    • 2016-04-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2020-03-02
    相关资源
    最近更新 更多