2012-03-31 63 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

相關問題