2016-09-21 80 views
1

在斯卡拉如何将fold作为for-comprehension实现?我看到唯一的方法是使用一些递归调用?这是一个失败的尝试,不知道如何做到这一点?什么是执行foldfor-comprehension实现折叠与理解

val nums = List(1,2,3)       
    nums.fold(0)(_+_)        
    def recFold(acc: Int = 0): Int = { 
    (for { 
     a <- nums 
     b = recFold(a + acc) 
    } yield b).head 
    }            
    recFold(0) //Stack overflow 
+0

我对scala没有太丰富的经验,但我没有看到从你的递归调用返回的基本情况? –

+0

使用'头部'是不安全的 – cchantep

回答

2

如果你真的想使用for,你不需要递归,但你需要一个可变变量:

val nums = List(1,2,3) 

def recFold(zero: Int)(op: (Int, Int) => Int): Int = { 
    var result: Int = zero 
    for { a <- nums } result = op(result, a) 
    result 
} 

recFold(0)(_ + _) // 6 

这是非常相似,如何foldLeftTraversableOnce实际执行:

def foldLeft[B](z: B)(op: (B, A) => B): B = { 
    var result = z 
    this foreach (x => result = op(result, x)) 
    result 
} 
0

折可以实现从右到左或从左到右两种方式的最佳途径。无需使用for加递归。递归就够了。

def foldRight[A, B](as: List[A], z: B)(f: (A, B) => B): B = { 
    as match { 
     case Nil => z 
     case x :: xs => f(x, foldRight(xs, z)(f)) 
    } 
    } 

    @annotation.tailrec 
    def foldLeft[A, B](as: List[A], z: B)(f: (A, B) => B): B = { 
    as match { 
     case Nil => z 
     case x :: xs => foldLeft(xs, f(x, z))(f) 
    } 
    } 
+0

我只是有兴趣,如果有一些超级聪明的方式来使用一个似乎总是似乎在FP ... – user3139545