簡體   English   中英

將命令性功能轉變為更具功能性

[英]Transform imperative function to be more functional

我在這里找到這個人:

      var time = createdAt
      var coolDown = duration
      while (time <= timestamp) {
        if (time <= timestamp && timestamp <= time + timeLimit.getOrElse(0L)) {
          return None
        } else {
          time = time + timeLimit.getOrElse(0L) + coolDown
          coolDown = 2 * coolDown
        }
      }
      Some("Error")

並希望將其重構為比命令式功能更強大的功能,但是我在函數式編程方面還很陌生,我想知道您實現該功能的方法。 我用單元測試進行了介紹,並打算創建一個數學函數或具有一個遞歸函數。 有沒有逐步進行的方法? 從頭開始? 您將如何解決?

該函數應返回以下內容:

-N-|-C-|-N-|--C(2x)--|-N-|----C(4x)----|-N-|--------C(8x)---------|-N-|...

它返回Error的時間呈指數增長。 假設coolDowntimeLimit是第一天返回None的第二天,第二天Error ,第三天None ,然后兩天Error ,依此類推...

是的,在@Carcigenicate發表評論后,這很容易。 我已經開始逐步進行重寫,並且方向一致。 結果:

def evaluateCooldown(time: Long, coolDown: Long): Option[String] = {
  if (time <= timestamp) {
    if (timestamp <= time + timeLimit.getOrElse(0L)) {
      None
    } else {
      evaluateCooldown(time + timeLimit.getOrElse(0L) + coolDown, 2 * coolDown)
    }
  } else {
    Some("Error")
  }
}
evaluateCooldown(unlockedAt, cdc.duration)

自然,有很多方法可以做到這一點。 這是使用惰性ADT的一種...

我們定義val ts = timestamp.getOrElse(0L)

def slen(n: Int) = math.pow(2, n - 1) * countDown + timeLimit
val prev = Stream.iterate(1)(slen).scan(0)(_ + _).takeWhile(_ < ts).last

查找時間戳之前的最后一個N | C部分的列表長度,然后

if (prev + timeLimit > ts) None else Some("Error")

另一種優化方法

我們可以用

用累積和替換scan

def clen(n: Int) = (math.pow(2, n) - 1) * countDown + n * timeLimit
val nextn = Stream.from(1).find(clen(_) > ts)

在時間戳之后找到第一部分的索引,然后

if (len(nextn - 1) + timeLimit > ts) None else Some("Error")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM