這裏有一個可能性:
import scala.annotation.tailrec
def sequence[A](a: List[Option[A]]): Option[List[A]] = {
@tailrec
def seq(remaining: List[Option[A]], result: Option[List[A]]): Option[List[A]] = {
if (remaining.isEmpty) {
result
} else {
(remaining.head, result) match {
case (Some(item), Some(list)) => seq(remaining.tail, Some(item :: list))
case _ => None
}
}
}
seq(a, Some(Nil))
}
,因爲它擊中了第一None
元素,它會很快停止評估名單。並且應該返回與實現相同的結果。但是,注意這個實現對於空輸入列表將返回Some(Nil)非常重要。
的實施可以縮短一點,這取決於你對錶現和其他可讀性標準的偏好:
def sequence[A](a: List[Option[A]]): Option[List[A]] = {
@tailrec
def seq(remaining: List[Option[A]], result: Option[List[A]]): Option[List[A]] = {
(remaining, result) match {
case (Nil, _) => result
case (Some(item) :: tail, Some(list)) => seq(tail, Some(item :: list))
case _ => None
}
}
seq(a, Some(Nil))
}
結果將Some
單子或None
。如果您想保留列表順序,你將不得不
- 取代
seq(a, Some(Nil))
與seq(a, Some(Nil)).map(_.reverse)
- 或
list :+ item
更換item :: list
。
雖然,list :+ item
不追加項目的List
的最佳方式。如果您想保留訂單並使用'@tailrec'方法,我建議您使用Vector
作爲結果類型,而不是List
。
您對結果缺少'.map(_。reverse)'。你也可以將兩個'None'匹配情況合併爲_ _> None,並將它們放在'Some'情況之後。 – Arjan
編輯我的答案與關於列表順序的評論。然而,如果我申請你的第二個建議,我不得不放棄'@ tailrec',would'nt I. –
不,要成爲尾部遞歸,recusrive調用不必在最新的匹配語句中,只是該特定情況下的最後一項陳述。 – Arjan