【问题标题】:Scala: having issue with a forward reference + looping counterScala:前向引用+循环计数器有问题
【发布时间】:2014-02-21 17:46:46
【问题描述】:

我正在使用 Akka 调度程序来错开列表中消息的发送,该列表是通过读取文件的行而构建的。这是一些代码:

 def startClock {
          val filename = "conf/my_file.json"
          val lines = scala.io.Source.fromFile(filename).getLines.toList
          var linePtr = 0

          if(linePtr == lines.length) { 
            clock.cancel()
          }
          else {
            Logger.info(s"num: $linePtr")
            default ! Message(lines(linePtr))
            linePtr = linePtr + 1
          }
        }

lazy val clock: Cancellable = Akka.system.scheduler.schedule(Duration.Zero, Duration.create(5000, TimeUnit.MILLISECONDS))(startClock)
val x = clock

现在为了解决前向引用编译器错误,如下所示:play.PlayExceptions$CompilationException: Compilation error[forward reference extends over definition of value clock]

我必须将时钟设置为lazy,然后在下一行引用它以触发startClock,它可以很好地完成这部分。我在这里遇到的问题是,linePtr 始终是0。它永远不会增加,但else {} 块中的代码被确认总是命中。我基本上在这里只有无限递归,而且我对 Scala 不够熟悉,无法确定我在这里做错了什么。我也尝试在startClock 之前定义val clock,但是在反向场景中我也有一个前向引用。这里似乎是鸡和蛋的问题。

【问题讨论】:

  • 我可以看到的一个问题是linePtr 被定义为startClock 函数的本地。每次调度程序调用startClock 时,它总是将linePtr 设置为0,这就是它总是命中你的else 语句的原因。如果您想正确递增,那么您可能应该在startClock 函数之外定义filenamelineslinePtr。这将是混乱的代码,因为它非常“副作用”,但对于您想要做的事情来说,这将是朝着正确方向迈出的一步。

标签: scala playframework akka


【解决方案1】:

也许课程不是关于变量捕获的工作原理,而是关于使用 API。由于getLines 为您提供了一个迭代器,因此只需使用它进行迭代。推测:

val lines = Source.fromFile(f).getLines
val clock = scheduler schedule send
def send  = if (lines.hasNext) d ! Message(lines.next) else clock.cancel()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多