运维开发网

scala – 从可变算法中发现功能算法

运维开发网 https://www.qedev.com 2020-07-12 20:55 出处:网络 作者:运维开发网整理
这不一定是 Scala问题,它是一个设计问题,与避免可变状态,功能思维和那种排序有关.碰巧我正在使用Scala. 鉴于这一系列要求: >输入来自1到10之间的基本无限的随机数流 >最终输出为SUCCEED或FAIL >在任何特定时间都可以有多个对象“收听”流,并且他们可以在不同的时间开始收听,因此他们可能对“第一”数字有不同的概念;因此,流的监听器需要与流本身分离. 伪代码: if (first
这不一定是 Scala问题,它是一个设计问题,与避免可变状态,功能思维和那种排序有关.碰巧我正在使用Scala.

鉴于这一系列要求:

>输入来自1到10之间的基本无限的随机数流

>最终输出为SUCCEED或FAIL

>在任何特定时间都可以有多个对象“收听”流,并且他们可以在不同的时间开始收听,因此他们可能对“第一”数字有不同的概念;因此,流的监听器需要与流本身分离.

伪代码:

if (first number == 1) SUCCEED
else if (first number >= 9) FAIL
else {
  first = first number
  rest  = rest of stream
  for each (n in rest) {
    if (n == 1) FAIL
    else if (n == first) SUCCEED
    else continue
  }
}

这是一个可能的可变实现:

sealed trait Result
case object Fail extends Result
case object Succeed extends Result
case object NoResult extends Result

class StreamListener {
  private var target: Option[Int] = None

  def evaluate(n: Int): Result = target match {
    case None =>
      if (n == 1) Succeed
      else if (n >= 9) Fail
      else {
        target = Some(n)
        NoResult
      }

    case Some(t) =>
      if (n == t) Succeed
      else if (n == 1) Fail
      else NoResult
  }
}

这会起作用,但闻起来对我来说. StreamListener.evaluate不是引用透明的.并且使用NoResult令牌感觉不对.它虽然清晰易用/代码,但确实具有优势.除此之外,还有一个功能性解决方案吗?

我想出了其他两个可能的选择:

>评估返回一个(可能是新的)StreamListener,但这意味着我必须使Result成为StreamListener的子类型,感觉不对.

>让评估将Stream [Int]作为参数,让StreamListener负责消耗尽可能多的Stream,以确定失败或成功.我在这种方法中看到的问题是,注册侦听器的类应该在生成每个数字后查询每个侦听器,并在失败或成功时立即采取适当的操作.通过这种方法,我不知道如何发生这种情况,因为每个监听器都强制评估Stream,直到完成评估.这里没有单一数字生成的概念.

有没有标准的Scala / FP成语我在这里俯瞰?

考虑到您的第一个可能的选项,我不确定为什么您将Result作为StreamListener的子类型,而不是只使用与StreamListeners相关的Result的特定子类型.

sealed trait Result
sealed trait FinalizedResult extends Result

trait StreamListener {
  def evaluate(n: Int): Result
}

case object Uninitialized extends Result with StreamListener {
  def evaluate(n: Int): Result = {
    n match {
      case i if (n == 1) => Succeed
      case i if (n >= 9) => Fail
      case _ => Initialized(n)
    }
  }
}

case class Initialized(target: Int) extends Result with StreamListener {
  def evaluate(n: Int): Result = {
    n match {
      case i if (n == target) => Succeed
      case i if (n == 1) => Fail
      case _ => this
    }
  } 
}

case object Succeed extends FinalizedResult
case object Fail extends FinalizedResult

但是,你是不是只是将可变性改为调用代码来跟踪对Results / StreamListeners的引用?

0

精彩评论

暂无评论...
验证码 换一张
取 消