简体   繁体   English

Scala 替代无限循环

[英]Scala alternative to an infinite loop

Is there any more functional alternative in Scala for an infinite loop?在 Scala 中是否有更多功能替代品用于无限循环?

while(true) {
  if (condition) {
    // Do something
  } else {
    Thread.sleep(interval);
  }
}

You can do it recursively你可以递归地做

@tailrec
def loop(): Nothing = {
 if (condition) {
  // Do something
  } else {
  Thread.sleep(interval);
  }
  loop()
 }

One thing that you can do is using higher-order functions like Stream.continually and pair it up with a for comprehension:您可以做的一件事是使用像Stream.continually这样的高阶函数,并将其与 a 配对以for理解:

import scala.util.Random
import scala.collection.immutable.Stream.continually

def rollTheDice: Int = Random.nextInt(6) + 1

for (n <- continually(rollTheDice)) {
  println(s"the dice rolled $n")
}

This example itself is not purely functional due to the non-referentially transparent nextInt method, but it's a possible construct that may help you think about function composition rather then using side effects.由于非引用透明的nextInt方法,此示例本身并不是纯函数式的,但它是一种可能的构造,可以帮助您考虑函数组合而不是使用副作用。

EDIT (2020-12-24)编辑 (2020-12-24)

As correctly point out in a recent comment, "[a]s of 2.13, Stream is deprecated. But the same method does exist in LazyList(import scala.collection.immutable.LazyList.continually)".正如在最近的评论中正确指出的那样,“[a] s of 2.13,Stream 已弃用。但 LazyList(import scala.collection.immutable.LazyList.continually) 中确实存在相同的方法”。

The following will work from 2.13 onward:从 2.13 开始,以下内容将起作用:

import scala.util.Random
import scala.collection.immutable.LazyList.continually

def rollTheDice: Int = Random.nextInt(6) + 1

for (n <- continually(rollTheDice)) {
  println(s"the dice rolled $n")
}

You can see it in action and play around with it here on Scastie .您可以在 Scastie 上看到它的实际运行情况并进行操作

I guess infinite tail recursion:我猜无限尾递归:

  @tailrec
  def loop(): Nothing = {
     if (condition) {
       // Do something
     } else {
       Thread.sleep(interval);
     }
     loop()
  }

Just to add to Stefano's great answer, in case someone is looking to a use-case like mine:只是为了补充 Stefano 的好答案,以防有人正在寻找像我这样的用例:

I was working on tasks from Kafka Streams course and needed to create an infinite stream of mock events to Kafka with some fields being completely random(amounts), but others rotated within a specific list(names).我正在处理 Kafka Streams 课程中的任务,需要为 Kafka 创建无限的模拟事件流,其中一些字段是完全随机的(数量),但其他字段在特定列表(名称)中轮换。

The same approach with continually can be used passing a method(via ETA expansion) to it and traversing the bounded variable afterwards:可以使用与continually相同的方法将方法(通过 ETA 扩展)传递给它,然后遍历有界变量:

  for {record <- continually(newRandomTransaction _)
       name <- List("John", "Stephane", "Alice")} {
    producer.send(record(name))
  }

where the signature of newRandomTransaction is as follows:其中newRandomTransaction的签名如下:

  def newRandomTransaction(name: String): ProducerRecord[String, String] = {
   ...
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM