簡體   English   中英

慣用法Scala解決命令式代碼

[英]Idiomatic Scala solution to imperative code

在'慣用'Scala中表達此功能有哪些想法。 或者更確切地說,有沒有辦法在不犧牲可讀性的情況下刪除本地變量?

def solve(threshold: Int)(f: Int => Int): Int = {
  var sum = 0
  var curr = 0
  while(sum < threshold) {
   sum += f(curr)
   curr += 1
  }
  curr
}

我唯一想到的就是這個,但在我看來它更長,更不易讀。

def solve2(threshold: Int)(f: Int => Int): Int = {
  val resultIterator = Iterator.iterate (0, 0) { case (curr, sum) =>
    (curr + 1, sum + f(curr))
  }
  (resultIterator find (_._2 >= threshold)).get._1
}
def solve(threshold: Int)(f: Int => Int): Int = {
  Iterator.from(0).map(f).scanLeft(0)(_ + _).indexWhere(threshold <=)
}

在我看來,循環版本更清晰。

最直接的方法是將while循環轉換為嵌套的尾遞歸函數。

def solve(threshold: Int)(f: Int => Int): Int = {
    def solveLoop(sum: Int, curr: Int): Int = if (sum < threshold) {
        solveLoop(sum + f(curr), curr + 1)
    } else {
        curr
    }
    solveLoop(0,0)
}

這是循環的標准“功能”方式。

你可以

def solve(threshold: Int, i: Int = 0)(f: Int => Int) = {
  if (threshold <= 0) i else solve(threshold - f(i), i+1)(f)
}

但我不確定這實際上是否更清楚。 請注意,它實際上比while循環的緊湊版本更多的字符:

def solve(threshold: Int)(f: Int => Int) = {
  var s,i = 0; while (s < threshold) { s += f(i); i += 1 }; i
}

具有可變變量的循環並不總是壞的,“慣用的”或不是。 只需保持函數中安全包含的可變狀態,所有其他人看到的是一個無狀態函數來調用。

順便提一下,盡管sum是一個明智的變量名,但curr值得懷疑。 i怎么了? 它被廣泛用作索引變量,無論如何,變量都是一個令人討厭的東西; 關鍵是你采取一些東西,每次增加它,無論它是什么,然后返回它。 正是這種邏輯流,而不是名稱,告訴你(和其他人)它是什么。

以下是我在Haskell中的表現:

solve threshold f = snd $ until test step (0, 0)
  where test (sum, i) = sum >= threshold
        step (sum, i) = (sum + f i, succ i)

這清楚地標記了teststep和初始值,就像命令式版本一樣。 我不確定scala是否until libs某處,但是定義它是微不足道的:

def until[A](test: A => Boolean)(f: A => A)(v: A): A = {
  if (test(v)) {
    v
  } else {
    until(test)(f)(f(v))
  }
}

def solve(threshold: Int)(f: Int => Int): Int = {
  def test = (sum: Int, i: Int) => sum >= threshold
  def step = (sum: Int, i: Int) => (sum + f(i), i + 1)
  until(test.tupled)(step.tupled)((0, 0))._2
}

我總是想知道人們何時談論'慣用'scala。 因為在我看來,每個人都有自己對慣用語的看法。 如果您正在尋找功能性解決方案,我建議您先看看“迭代器模式的本質”。 實際上scala中有一個非常好的博客文章關於這個檢查: http//etorreborre.blogspot.com/2011/06/essence-of-iterator-pattern.html

暫無
暫無

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

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