2013-03-29 2 views
9

サイズを指定することなく部分的にtupleと一致する方法はありますか? 、これはコンパイルされませんスカラーで不明なサイズのタプルに一致する

v match { 
    case ("Dr", : _*) => "What's up, Doc?" 
    case ("Mr", name, :_*) => s"Welcome, Mr. ${name}" 
    case _ => "Have we met?" 
} 

:_*は、通常、パラメータの不確定な数を意味するが、私はタプル

val v = ("Dr", "John","H", "Watson") 

を持っている場合たとえば、私のような何かを行うことができるようにしたいのですがこの場合明らかに使用することはできません。考え方は、2より大きいタプルに対してこのマッチャーを使用できるようにすることです。 でそれを行うことができるかどうかを知りたい場合は、まずvListに変換することができます。

EDIT:私は、ウェブ上で発見ほとんどの情報は、バックのScala 2.8にまでさかのぼりれ、this discussionあるので、私は「いいえ、することはできません」と答えてつもりです。

+0

私が知る限り、サイズの異なるタプルは異なるタイプなので、方法はありません。しかし、それはマクロで行うことができます - 目的は、すべての可能なサイズに一致するコードを生成することです。あるいは、示唆したように、暗黙の変換を 'Seq [Any]'に定義してください。これはあまりにも汚い解決策であり、あなた自身に尋ねる方がいいでしょう。タプルはあなたの問題に使う正しいタイプですか?多分彼らはそうではないでしょう。 –

+1

@SargeBorschしかし、それらすべてがProductを拡張します;-) –

+0

@ om-nom-nomはい、それは本当ですが、あなたがProduct型を持っているなら、その要素の型を知らないので、データへの型付きのないアクセスを失います –

答えて

11

タプルは、異種タイプの構造です。あなたができるので、そのように、彼らは、productIterator形質を実装します。

v.productIterator.toList match { 
    case "Dr" :: _ => "What's up, Doc?" 
    case "Mr" :: name :: _ => s"Welcome, Mr. ${name}" 
    case _ => "Have we met?" 
} 

をしかし、あなたはすぐにSeq[String]をしたいようなあなたの例では、実際に見えます。タプルを使用する理由はありますか?

+1

質問に記載されているとおり、私はそれが可能かどうかを知りたいだけですが、タプルを使用する特別な理由はありません。 D – Chirlo

+1

短い答えは "いいえ"なので、異なるアリティのタプルは、Iterator [Any]を提供する以外は何も共有しません。 –

10

これはHListsにタプルからshapelessの変換を使用して行うことができ、

scala> import shapeless._ 
import shapeless._ 

scala> import Tuples._ 
import Tuples._ 

scala> val v = ("Dr", "John","H", "Watson") 
v: (String, String, String, String) = (Dr,John,H,Watson) 

scala> v.hlisted match { 
    | case "Dr" :: _ => "What's up Doc?" 
    | case "Mr" :: name :: _ => s"Welcome, Mr. ${name}" 
    | case _ => "Have we met?" 
    | } 
res0: String = What's up Doc? 

それは、上記の例では見えないですが、可能な完全な静的型情報がでバインドされた名前のために維持されることに注意してくださいケースの句は、例えば、

scala> (23, "foo", true).hlisted match { 
    | case i :: s :: b :: HNil => if(b) i+s.length else 0 
    | case _ => -1 
    | } 
res1: Int = 26 
-1

はこれを試してみてください:

case tuple:Product => { 
    tuple.productIterator.toList match { 
     case (head::rest) => ... 

    } 
} 
関連する問題