前に、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の性質ってどうしようもない気がする(´・ω・`)