2017-06-13 89 views
0

我有以下遞歸方法:爲什麼我無法將Nil附加到列表中?

def myMethod(foo: List[FooBar], acc: List[MyClass]): List[MyClass] { 

    // ... some code ... 

    myMethod(foo.tail, acc :+ getMyObject(foo.head).getOrElse(Nil)) 

} 

getMyObject任選返回MyClass實例的方法。不幸的是,我不能編譯這一點,因爲我得到這個錯誤:

[error] found : List[Product with Serializable] 
[error] required: List[MyClass] 

該編譯錯誤表明我不能追加Nil到列表acc,所以我必須使用下面的代碼:

def myMethod(foo: List[FooBar], acc: List[MyClass]): List[MyClass] { 

    // ... some code ... 
    val bar = getMyObject(foo.head) 
    myMethod(foo.tail, if (bar.isDefined) acc :+ bar.get else acc) 

} 

但是,我更喜歡第一種方法,因爲它更簡潔。爲什麼我不能將Nil添加到列表中?

回答

3

:+需要一個n -elemnt列表和元素x並返回n+1 - 元素列表,其中最後一個元素x。這意味着兩件事情:

  • 沒有爭議,您可以使用作爲:+右操作數來獲得相同大小的列表
  • :+需要正確的操作是列表中的元素類型。

所以你可以做acc :+ Nil只有acc是列表的列表,即使如此,你想要什麼,因爲它會把一個額外的空列表到你的列表中,而不是保持不變的名單也不會做。


解決您的問題,最簡潔的方式是acC++ bar。這使用連接而不是追加和工作,因爲選項被看作0或1個元素的集合。因此acC++ barbar的零個或一個元素附加到acc的零個或一個元素。注:您通常應該使用模式匹配或更高階的函數來操作列表,而不是headtail

0

您使用了錯誤的操作,使用++而不是

myMethod(foo.tail, acC++ getMyObject(foo.head).map(List(_)).getOrElse(Nil)) 

myMethod(foo.tail, getMyObject(foo.head).map(acc :+ _).getOrElse(acc)) 
+0

'getMyObject'返回一個'Option [MyClass]' - 所以這不會編譯 –

+0

你是對的,編輯過 – Mikel

1

的問題是追加操作:+採用非列表值,並將其添加到列表。問題是Nil和Myclass是不同的類型,所以結果列表採用滿足MyClass和Nil的最具體類型。他們是完全無關的類型,所以你最終得到Product with Serializable作爲常見的超級類型。

要將一個元素或任何內容附加到列表中,請首先將該元素包裝到列表中。然後連接你的單例列表或零與舊列表。

myMethod(foo.tail, acC++ getMyObject(foo.head).map(x => List(x)).getOrElse(Nil)) 
相關問題