TupleからList ( そして productIterator がIterator[Any]型を返すことへのちょっとした不満 )

前に、ListからTupleに変換するメソッド作りましたが、それの逆の話。
まずそもそも、Tupleには、productIteratorというメソッドがあり*1、それを呼んだあとにtoListすればListになります。
REPLの出力そのまま貼りつけ↓

scala> ("scala","clojure","java")
res0: (java.lang.String, java.lang.String, java.lang.String) = (scala,clojure,java)

scala> res0.productIterator.toList
res1: List[Any] = List(scala, clojure, java)

しかし、productIteratorが返すのは、Iterator[Any]型です。
それをtoListしても、もちろん、List[Any]型にしかなりません。

しかし、上記の例だと、
List[Any]型ではなく、List[String]型で返すことってできないの?
という疑問がわいたので、そういものを返す関数作ってみました(・∀・)

implicit def tuple2List[A<:X,B<:X,C<:X,X]( t: Tuple3[A,B,C]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3)
}

使い方の例↓(REPLの出力そのまま貼りつけ。コメントだけ後から追加)

scala> ("scala","clojure","java")
res2: (java.lang.String, java.lang.String, java.lang.String) = (scala,clojure,java)

scala> res2 tupleToList
res3: List[java.lang.String] = List(scala, clojure, java) //ちゃんとStringのListになる

scala> (BigInt(3) , new java.lang.Long(9) ,new java.lang.Float(3.2) )
res4: (scala.math.BigInt, java.lang.Long, java.lang.Float) = (3,9,3.2)

scala> res4 tupleToList
res5: List[java.lang.Number] = List(3, 9, 3.2) //BigInt、java.lang.Long、java.lang.Floatの共通の親である、java.lang.NumberのListになる

で、これっておそらく、可変長型引数*2とかないと、DRYに関数定義するの無理なので、scalaソースコードを吐く、scalaのコード書いた(`・ω・´) *3
メタプロメタプロ(゚∀゚)/

object generateTuple2List {

  val typeNames = 'A' to 'V' map{ _. toString }
  
  def main(args: Array[String]): Unit = {
    1 to 22 map{ generateFunc } foreach println
  }
  
  def generateFunc(n:Int):String = {
    
    val tName = typeNames take(n)
    
    "implicit def tuple2List[" +
    tName.mkString("<:X,") +
    "<:X,X]( t: Tuple" + n +
    tName.mkString("[" , "," , "]" ) +
    ") = new {\n" + 
    "  def tupleToList:List[X] = List[X](t._" +
    (1 to n).mkString(",t._") + ")\n" +
    "}\n"
    
  }

}

これ↑を実行して生成した、ソースコードがこれ↓

implicit def tuple2List[A<:X,X]( t: Tuple1[A]) = new {
  def tupleToList:List[X] = List[X](t._1)
}

implicit def tuple2List[A<:X,B<:X,X]( t: Tuple2[A,B]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2)
}

implicit def tuple2List[A<:X,B<:X,C<:X,X]( t: Tuple3[A,B,C]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,X]( t: Tuple4[A,B,C,D]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,X]( t: Tuple5[A,B,C,D,E]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,X]( t: Tuple6[A,B,C,D,E,F]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,X]( t: Tuple7[A,B,C,D,E,F,G]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,X]( t: Tuple8[A,B,C,D,E,F,G,H]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,X]( t: Tuple9[A,B,C,D,E,F,G,H,I]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,X]( t: Tuple10[A,B,C,D,E,F,G,H,I,J]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,X]( t: Tuple11[A,B,C,D,E,F,G,H,I,J,K]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,X]( t: Tuple12[A,B,C,D,E,F,G,H,I,J,K,L]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,X]( t: Tuple13[A,B,C,D,E,F,G,H,I,J,K,L,M]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,X]( t: Tuple14[A,B,C,D,E,F,G,H,I,J,K,L,M,N]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,X]( t: Tuple15[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,X]( t: Tuple16[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,X]( t: Tuple17[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,R<:X,X]( t: Tuple18[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17,t._18)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,R<:X,S<:X,X]( t: Tuple19[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17,t._18,t._19)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,R<:X,S<:X,T<:X,X]( t: Tuple20[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17,t._18,t._19,t._20)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,R<:X,S<:X,T<:X,U<:X,X]( t: Tuple21[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17,t._18,t._19,t._20,t._21)
}

implicit def tuple2List[A<:X,B<:X,C<:X,D<:X,E<:X,F<:X,G<:X,H<:X,I<:X,J<:X,K<:X,L<:X,M<:X,N<:X,O<:X,P<:X,Q<:X,R<:X,S<:X,T<:X,U<:X,V<:X,X]( t: Tuple22[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V]) = new {
  def tupleToList:List[X] = List[X](t._1,t._2,t._3,t._4,t._5,t._6,t._7,t._8,t._9,t._10,t._11,t._12,t._13,t._14,t._15,t._16,t._17,t._18,t._19,t._20,t._21,t._22)
}

まぁ実用性があるのかどうかっていわれると微妙ですが(´・ω・`)
そもそも自分自身は、TupleからListに変換したいって思ったことがほぼないですし。
あまりにも、そういう事がしたいと思うことが多い場合、scalaにおける、TupleとListの使い分けができてないんじゃないかと思います。*4
しかし、他の言語では、ある程度相互運用性があるのか、詳しく知りません*5が、scalaやってる人で、そういう、List と Tupleの相互変換したい的な話はちらほら聞きますね。

*1:case classの場合だけど、使い方一緒なので、このへんの解説参照。Tupleやcase classの共通の親のProductで定義されてる

*2:可変長引数ではなく、可変長引数

*3:多分何らかしらの方法で、scalaのライブラリのFunction、Product、Tupleなどの1から22までほとんどにたようなコードになってるものは、こういうコード生成してるんじゃないかと思う。こういうのが、 @cpp_akira さんが批判してたやつ → scala勉強会第9回資料の18枚目参照。自分も不満だけど、もう今さら、こういう場合に現れるDRYに書けないscalaの性質ってどうしようもない気がする(´・ω・`)

*4:あくまでも今までの自分のscalaの経験上の感覚なので、これに対する反論歓迎

*5: pythonとかそうなの?