[英]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)
這清楚地標記了test
, step
和初始值,就像命令式版本一樣。 我不確定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.