2012-03-31 73 views
1

我正在尝试查找行集合中最长行的长度。reduceLeft为什么会抱怨类型不匹配?

val lines = Source.fromFile(args(0)).getLines() //a collection of strings 
    val longestLine = lines.reduceLeft((a,b) => 
     if(a.length > b.length) a.length else b.length) 

但是,这将导致以下错误:

/home/jesvin/dev/scala/readfile.scala:11: error: type mismatch; 
found : Int 
required: String 
     if(a.length > b.length) a.length else b.length) 
           ^
/home/jesvin/dev/scala/readfile.scala:11: error: type mismatch; 
found : Int 
required: String 
     if(a.length > b.length) a.length else b.length) 
              ^
two errors found 

我试图在某些地区仍有明确的返回语句和类型转换,但没有奏效。

我使用reduceLeft错误吗?

回答

10

Am I using reduceLeft wrong?

是的,你想有一个fold的行为不是reduce和。 A reduce产生与集合的类型参数相同的类型 - 它可以产生另一种类型的fold

scala> Seq("a","b","cd").reduceLeft(_+_) 
res24: String = abcd 

在此,SEQ的类型参数是字符串 - 因此reduceLeft还产生一个字符串。

scala> Seq("a","b","cd").foldLeft(0)(_+_.length) 
res25: Int = 4 

相反foldLeft可以产生另一种类型的 - 在这个例子中一个Int。

在你的例子中seq.max是你想要的。试着自己实现它,然后当你看到源代码来验证你的实现是否正确。

提示:一个reduce是实现这样的一个fold

def reduce(f: (A, A) => A) = 
    tail.fold(head)(f) 

这就是为什么reduce抛出时,它被称为一个空的集合的异常的原因。

2

是的,你是。 reduceLeft必须返回一个与集合中的类型兼容的类型的对象 - 在本例中为String。看到Programming in Scala恰好为你的问题 - 直到相同的变量名称。

你想:

val longestLine 
    = lines.reduceLeft((a,b) => if(a.length > b.length) a else b).length 

当然,这只能如果集合非空。出于这个原因,以及其他人,foldLeft通常更可取,如@Antoras所示。

+0

我在第三章的末尾写了这个程序,却没有看原版,找到了我的学习空白。原来,在这种情况下,我对减少和折叠操作不够了解。 – aitchnyu 2012-03-31 18:15:16

相关问题