【问题标题】:scala functional way to store statescala存储状态的功能方式
【发布时间】:2018-04-10 17:07:40
【问题描述】:

我想使用函数的方式在 scala 中存储一个状态 (key -> value)。大概是以前在奥德斯基的课上学过的,但是记不住了。

这是我的非功能性方法;

import org.scalatest.{FunSuite, Matchers}

trait EventHandler

class StatefulNonFn {

  type EventName = String

  private var state = Map.empty[EventName, EventHandler]

  def update(name: String): EventHandler = {
    state.get(name).fold {
      val handler = new EventHandler {}
      state += name -> handler
      handler
    }(eh => eh)
  }

}

class NonFunctionalStateSpec extends FunSuite with Matchers {

  test("stateful") {
    val stateResult = new StatefulNonFn().update("MusicAdded")
    stateResult.isInstanceOf[EventHandler] shouldBe true
  }

}

我所做的一个尝试是使状态成为“EventName 和 previousState 的函数”,这是有道理的,但现在我不知道如何存储所有这些状态?

我的第一个电话会很好,因为在那种情况下状态是空的。

import org.scalatest.{FunSuite, Matchers}

trait EventHandler

class Stateful {

  type EventName = String

  private val stateFn = new ((String, Map[EventName, EventHandler]) => Map[EventName, EventHandler]) {
    override def apply(name: String, prevState: Map[EventName, EventHandler]): Map[EventName, EventHandler] = {
      val handler = new EventHandler {}
      prevState + (name -> handler)
    }
  }

  def initState = Map.empty[EventName, EventHandler]

  def update(name: String, prevState: Map[EventName, EventHandler]) = stateFn(name, prevState)
}

class FunctionalStateSpec extends FunSuite with Matchers {

  test("stateful") {
    val stateHelper = new Stateful()
    val stateResult = stateHelper.update("MusicAdded", stateHelper.initState)

    stateResult.keys.size shouldBe 1

    val stateResult1 = stateHelper.update("MusicDeleted", stateResult)
    stateResult1.keys.size shouldBe 2

    //what i obviously want is something like this without me wanting to store the previousStates

    //stateHelper.update("MusicAdded1")
    //stateHelper.update("MusicAdded2")

  }

}

我不确定,也许某些东西最终必须是可变的。在上述情况下如何存储以前的状态?没有客户在每次通话中提供它。因为可以从 5 个不同的客户端更新状态,而无需知道之前的状态。

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    事实证明,如果你想做一些有用的程序,你需要突变和状态。你需要做 IO,比如保存到数据库中(每次这样做可能会返回一些不同的 ID),或者获取一个随机数,或者当前时间戳,或者打印到控制台等。

    如果你在做函数式编程,那么做的不是纯粹的、确定性的、全面的东西。这是关于隔离副作用(如突变和状态)。

    因此,像 Haskell 这样的严格纯语言通过返回动作(或计划,或动作描述......)而不是执行它们来做到这一点。运行时执行这些操作,因此您有两件事:

    1. 你的清纯性感节目

    2. 运行时,负责做脏事。

    然而 Scala 不只是希望您返回操作以便运行时执行它们……您需要自己做。

    话虽如此,如果您不想去黑暗的地方,您的解决方案是完全可以的。否则,我建议您阅读 this,John Degoes 的一篇文章,它基本上解释了如何做您想做的事情(同时定义什么是 freemonad)。

    【讨论】:

      猜你喜欢
      • 2011-03-22
      • 1970-01-01
      • 2019-04-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 2016-10-12
      • 2018-12-31
      相关资源
      最近更新 更多