是否可以在Scala中执行此操作(不改变类的内部状态)?

Ala*_*ano 0 functional-programming scala

比方说,有一个叫做的课RemoteIdGetter.它从服务器返回一个密钥.但是它只向服务器发出请求,如果密钥不够"新鲜",意味着它最后一次被请求,则大于或等于5分钟(300秒).否则,它返回密钥的本地"缓存"值.

我需要在没有( var)改变内部状态 RemoteIdGetter或使用纯函数方法的情况下做到这一点.

它可能看起来像这样:

class RemoteIdGetter {
  def key = {
    if (!needToAskServer) // return the local "cached" value of the key
    else makeRequest

  }

  def makeRequest = // make a request to a remote server to get the key
  def time = // current date-time
  def lastUpdatedTime = // the last date-time a key has been updated 
                        // (requested from the server)
  def needToAskServer = time - lastUpdatedTime >= 300
}
Run Code Online (Sandbox Code Playgroud)

我想知道,这可能吗?我为什么需要它?我只是好奇,如果可能的话.

sen*_*nia 6

每次用相同的参数调用它时,纯函数应该返回相同的结果,所以如果你想在没有可变状态的情况下执行此操作,那么RemoteIdGetter每次获得这样的键时都必须生成新的:

case class RemoteIdGetter(cachedKey: Option[KeyType] = None, lastUpdatedTime: Option[DateTime] = None) {
  def getKey(time: DateTime) = {
    val (key, t) = (for {
      k <- cachedKey
      lt <- lastUpdatedTime
      if (time - lt < cachePeriod)
    } yield k -> lt).getOrElse(makeRequest -> time)
    key -> RemoteIdGetter(Some(key), Some(t))
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

val (key, newGetted) = oldGetter.getKey(currentDateTime)
Run Code Online (Sandbox Code Playgroud)

您必须RemoteIdGetter每次都使用最新生成的.

或者你可以隐藏可变状态.例如,您可以使用actor:

import akka.actor.ActorDSL._
val a = actor(new Act {
  become {
    case GetKey => replyAndBecome(sender)
  }

  def replyAndBecome(sender: ActorRef): {
    val key = makeRequest
    sender ! key
    become getState(key, time)
  }

  def getState(key: KeyType, lastUpdatedTime: DateTime): Receive = {
    case GetKey =>
      if (time - lastUpdatedTime < cachePeriod)
        sender ! key
      else 
        replyAndBecome(sender)
  }
})
Run Code Online (Sandbox Code Playgroud)

没有可见的可变状态(如var,或可变集合),但有一个隐藏的可变状态 - 演员行为.