2017-10-12 10 views
0

スカラー尾の再帰に関する質問があります。私はリストを取り、偶数の新しいリストを作成する単純なテール再帰コードを書いた。しかし、スカラーが要素をリストに追加できないため、リストは降順でソートされます。以下は、私は次の質問Scalaでのテール再帰

  1. どのように私は、このメソッド内でリストを逆に文を追加することができますを持っているコード

    def listCreator(lists: List[Int]): List[Int] = { 
        @tailrec 
        def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = { 
         lists match { 
          case Nil => accum 
          case x :: Nil if (isEven (x) == true) => x :: accum 
          case x :: Nil if (isEven (x) == false) => accum 
          case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum) 
          case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum) 
         } 
        } 
        evenListCreator(lists, List()) 
    } 
    

    はありますか?

  2. この行evenListCreator(lists, List())は、メソッド呼び出しの直後にあり、末尾再帰には必須ですか?

+0

'Vector'は不変であるが、合理的、効率的なアペンドを持って、あなたの代わりに' List' –

答えて

2

戻す前に元に戻すことができます。

scala> def listCreator(lists: List[Int]): List[Int] = { 
    |  @tailrec 
    |  def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = { 
    |   lists match { 
    |    case Nil => accum 
    |    case x :: Nil if (isEven (x) == true) => x :: accum 
    |    case x :: Nil if (isEven (x) == false) => accum 
    |    case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum) 
    |    case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum) 
    |   } 
    |  } 
    |  evenListCreator(lists, List.empty[Int]).reverse 
    | } 
listCreator: (lists: List[Int])List[Int] 

scala> listCreator((1 to 10).toList) 
res2: List[Int] = List(2, 4, 6, 8, 10) 

scala> 

あなたはすぐにメソッドの呼び出しを追跡する必要はありませんが、あなたは二つの引数を送信する必要もありません場合は、1つのリストがあり、第二は空のリストです。だから私たちは整数のリストだけを使用しているので、空のリストを送るように気にする必要はありません。

、あなたが直接、またそれを行うことができます

scala> val list = (1 to 10).toList 
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> list.map(_ * 2) 
res8: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) 

scala> 
2
  1. evenListCreator(lists, List()).reverseまたはevenListCreator(lists.reverse, List())が、あなたの場合には最初の形式は、最も可能性の高いevenListCreator
  2. に呼び出した後に短くなります逆にリストとして優れています
  3. この行:evenListCreator(lists, List())はメソッド呼び出しに従わず、メソッド呼び出しです。それがなければ、あなたのテール再帰関数(def evenListCreator)だけを定義し、それを呼び出さずに戻るので何も起こりません。

他のいくつかの注意事項

あなたはあまりにも多くの停止条件を持っている、これで十分です:

@tailrec 
def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = { 
    lists match { 
    case Nil => accum 
    case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum) 
    case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum) 
    } 
} 

コード私はこれが優れていると思いますが、あまりにも冗長です:

@tailrec 
def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = { 
    lists match { 
    case Nil => accum 
    case x :: tail if isEven (x) => evenListCreator(tail, x :: accum) 
    case x :: tail if !isEven (x) => evenListCreator(tail, accum) 
    } 
} 

あなたはそのように再帰関数を呼び出すこともできます:

evenListCreator(lists, Nil) 
2

Q1。 @Mahesh Chand Kandpalが指摘したように、返される前にListを取り消すことができます。または、プリペンド( "cons")メソッドの代わりにaccum :+ xというメソッドを追加してリストを構築することもできます。x :: accum

しかし、Listの場合、consメソッドはappendメソッドより効率的です。したがって、通常、ビルドアンドリバースする方が効率的です。

Q2。いいえ。テールの再帰は、呼び出しが返ってから待機する他の操作がないことを意味します。つまり、return callMyself()はテールコールですが、return callMyself() + 1ではありません。

P.S.私は本当に...

def listCreator(ints: List[Int]): List[Int] = ints.filter(i => (i&1) < 1) 
+0

母のそれを使用するかもしれませんが、私はどこかに開始しなければならなかった、これが唯一の学習運動です知っているが、:)ご協力いただきありがとうございます – Srinivas

関連する問題