2011-07-18 5 views
6

私はあなたが私はこれがどのように機能するか疑問に思い始めたマッチングは

val list = List(1,2,3) 
list match { 
    case head::tail => head 
    case _ => //whatever 
} 

のような方法で、リスト上のマッチングを行うことができることを知っています。私が正しく理解していれば、::はそう何がこの種の機能を作成する方法があれば、それはどのように行われている

4 match { 
    case x + 2 => x //I would expect x=2 here 
} 

のようなものをやってから私を停止することだ、ちょうどオペレータです。そうでない場合は、なぜですか?

+0

「y-2」(y = 4の場合)を使用しないのはなぜですか? –

+0

これはもっと好奇心が強いので、具体的な例はありませんが、これはもっと複雑なクラスにはいいと思いました。 – Dylan

答えて

8

パターンマッチングは入力を受け取り、unapply関数で分解します。したがって、あなたの場合、unapply(4)は、合計4の2つの数値を返さなければなりません。しかし、4に合計するペアがたくさんあるので、関数は何をすべきか分からないでしょう。

2は何とかunapply機能にアクセスできる必要があります。 2を保存する特殊なケースクラスは、このために働くだろう:

case class Sum(addto: Int) { 
    def unapply(i: Int) = Some(i - addto) 
} 

val Sum2 = Sum(2) 
val Sum2(x) = 5 // x = 3 

を(コンパクトのためval Sum(2)(y) = 5ような何かを行うことができるようにいいだろうが、Scalaはパラメータ化された抽出を許可していません。hereを参照してください。)

[EDIT:これは少し愚かですが、実際にはあまりにも次の操作を行うことができます:

val `2 +` = Sum(2) 
val `2 +`(y) = 5 // y = 3 

]

編集:理由は、head::tailの作品は、リストの末尾から頭を分割する正確に1つの方法があるということです。

+::について本質的に特別なものは何もありません:あなたはそれが数を破るたかったかの所定の考えを持っていた場合は、+を使用することができます。たとえば、あなたは、あなたが何かを行うことができ、「半分に分割」を意味する+を望んだ場合:

object + { 
    def unapply(i: Int) = Some(i-i/2, i/2) 
} 

をし、それが好きで使用します。

scala> val a + b = 4 
a: Int = 2 
b: Int = 2 

scala> val c + d = 5 
c: Int = 3 
d: Int = 2 

はEDIT:最後に、thisは、その説明パターンマッチングA op Bは、op(A,B)と同じことを意味し、構文が見栄えが良くなります。 case head :: tailとマッチング

+0

あなたの編集は私のために物事をクリアすると思う、私は今晩遅くこのコンセプトで周りにおもちゃを持っていなければならないだろう – Dylan

+0

@Dylan:私は散文を書き直したので、うまくいけば分かりにくいだろう。 – dhg

4

は、実際のマッチングを行う前にop(p1, p2)に翻訳さ形p1 op p2中置動作パターンを使用します。

を(::ためAPIを参照してください)+の問題点は次のとおりです。

それがマッチングを行うだろう

object + { 
    def unapply(value: Int): Option[(Int, Int)] = // ... 
} 

オブジェクトを追加するのは簡単ですが、あなただけごとに1つの結果を供給することができます値。例えば。

object + { 
    def unapply(value: Int): Option[(Int, Int)] = value match { 
    case 0 => Some(0, 0) 
    case 4 => Some(3, 1) 
    case _ => None 
} 

今、この作品:

0 match { case x + 0 => x } // returns 0 

もこの

4 match { case x + 1 => x } // returns 3 

しかし、これは、あなたがそれを変更することはできませんではないでしょう。

4 match { case x + 2 => x } // does not match 

んが、問題を::ため、しかし、それはheadは常に定義され、リストはtailとなります。

+0

+1 APIリンク - 私はそれを認識しませんでした。だから、私が集めたことから、リスト[_]は実際には::のサブクラスなので、ケースクラスなので、そういうものにマッチできるのですか?だから、もし私が '' hello "match {case head :: tail // h + ello ...'のようなマッチングをしたいのであれば、Stringから自分の特殊なcaseクラスへの暗黙の変換を行う必要がありますか? – Dylan

1

Scalaには::(「cons」と発音)が2つあります。 1つはListの演算子であり、もう1つはクラスであり、頭と尾を特徴とする空でないリストを表します。したがってhead :: tailはコンストラクタパターンです。このパターンは演算子とは関係ありません。