2

整数のリストの要素間の距離のリストを返す次の関数があります。

def dists(l: List[Int]) = {
  //@annotation.tailrec
  def recurse(from: Int, rest: List[Int]): List[Int] = rest match {
    case Nil => Nil
    case to :: tail => to - from :: recurse(to, tail)
  }

  l match {
    case first :: second :: _ => recurse(first, l.tail)
    case _ => Nil
  }
}

への呼び出しが末尾の位置にあるように見えますが、注釈::を使用できません。@tailrecrecurse

@tailrec連結を行うための互換性のある方法はありますか?

アキュムレータを使用できますが、入力または出力を反転する必要がありますよね?

編集:再帰的アプローチに特に興味があります。recurse私の具体的な使用例は、1 回の呼び出しで結果リストに複数の項目を追加できるという点で、もう少し複雑です。

=> item1 :: item2:: recurse(...)

距離関数は、問題を示すための単なる例です。

4

4 に答える 4

1

遅れて申し訳ありませんが、Haskell と ML に存在する標準パターンは scala でも機能します。これはcmbaxterの回答とかなり似ていますが、参考のために追加すると思いました.Scalaを始めたとき、このようなものが大いに役立ちました.

リストを再帰するときは、常にアキュムレータ パターンを使用します。また、タプル形式ではなく、ここで関数を定義するカリー形式を使用しました。

また、あなたのコードに関連して、すべてのパターンマッチステートメントを外部valを持つのではなく、再帰関数自体の中に入れます。

  def build (l1: List[Int]) (acc: List[Int]): List[Int] =
l1 match {
    case Nil => acc
    case h::t => build (t) (acc.::(h))
    case _ => acc
}                                                 //> build: (l1: List[Int])(acc: List[Int])List[Int]    
  val list1 = List(0, 1, 2)                       //> list1  : List[Int] = List(0, 1, 2)
  val list2 = List(3, 4, 5, 6)                    //> list2  : List[Int] = List(3, 4, 5, 6)
  val b = build(list1)(list2)                   //> b  : List[Int] = List(6, 5, 4, 3, 0, 1, 2)
于 2013-07-29T14:47:23.773 に答える