2011-07-18 19 views
6

seni bu yüzden bu nasıl çalıştığını merak etmeye başladıEşleştirme

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

gibi bir şekilde listelerinde eşleme yapabilirsiniz biliyoruz. Eğer doğru anlamak, :: sadece bir operatör olduğunu, yani ne nasıl yapıldığını işlevsellik bu tür oluşturmak için bir yol varsa

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

gibi bir şey yapmama engel içelim; değilse, neden?

+0

Neden y-2'yi kullanmıyorsunuz (ne zaman y = 4)? –

+0

Bu daha çok bir meraktır, bu yüzden özel bir örneğim yok, ama bunun daha karmaşık sınıflar için güzel olduğunu hayal ettim. – Dylan

cevap

8

Desen uygun girdi alır ve bir unapply fonksiyonu ile parçalanır. Yani sizin durumunuzda, unapply(4), toplamı 4 olan iki sayıyı döndürmek zorunda kalacaktı. Ancak, 4'e kadar çok sayıda çift var, bu yüzden işlev ne yapacağını bilemez. 2 nasılsa unapply işlevine erişilebilir olması için

İhtiyacın olduğunu.

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

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

(Kompaktlık için val Sum(2)(y) = 5 gibi bir şey yapabilmek için iyi olurdu, ama Scala parametreli presi izin vermez; here bkz.)

: 2 saklayan özel bir durum sınıf bunun için çalışacak

[DÜZENLEME: Bu biraz saçma, ama aslında çok aşağıdakileri yapabilirsiniz:

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

]

DÜZENLEME: head::tail'un çalışmasının sebebi, kafanın bir listenin kuyruğundan ayrılmasının bir yolunun olması. Eğer bir numara kırmak nasıl istediğini önceden belirlenmiş bir fikir olsaydı + kullanabilirsiniz: yaklaşık ::+ karşı doğal özel bir şey yok

.

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

ve gibi kullanın::

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

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

EDIT: Örneğin, eğer o zaman böyle bir şey yapabileceğini, "ikiye bölünmüş" demek + istedi Nihayet, this zaman açıklar desen eşleştirme, A op B, sözdizimi güzel görünmesini sağlayan op(A,B) ile aynı anlama gelir. case head :: tail ile Eşleşen

+0

Düzenlemenin benim için bazı şeyleri temizlediğini düşünüyorum, bu gece bu konseptle daha sonra etrafıma oyuncak koymak zorunda kalacağım – Dylan

+0

@Dylan: Düzyazıyı yeniden yazdım bu yüzden umarım daha az kafa karıştırıcı olur. API bağlantısı için – dhg

4

gerçek eşleştirme yapmadan önce op(p1, p2) için tercüme şeklinde p1 op p2 bir infix işlemi modelini kullanır.

o eşleştirme yapacağını bir

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

nesne eklemek kolaydır iken

, sadece başına bir sonuç temin edebilir: Aşağıdaki

+ sorun olduğu (:: için API bakınız) değer. Örneğin.

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

Şimdi bu işleri: Ayrıca

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

bu

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

Ama bu olmaz ve bunu değiştiremezsiniz:

:: için
4 match { case x + 2 => x } // does not match 

Sorun değil, olsa da, çünkü her zaman head nedir ve listenin tail nedir tanımlanır.

+0

+1 olduğunu farketmedim. Yani bundan aldığım şeyden, bir Liste [_] aslında bir alt sınıf ve dolayısıyla bir vaka sınıfıdır ve bu yüzden bu şekilde eşleştirebilirsiniz? Yani eğer "merhaba" maçı {case head :: tail // h + ello ... 'gibi bir eşleşme sunmak isteseydim, o zaman bir String'den kendi özel vaka sınıfım için örtülü bir dönüşüm yapmam gerekirdi? – Dylan

1

Scala'da iki adet :: s var (okunan "eksiler" var). Biri, List s operatöründe, diğeri ise baş ve kuyruk ile karakterize boş olmayan bir listeyi temsil eden bir sınıftır. Dolayısıyla, head :: tail, operatörle ilgisi olmayan bir yapıcı modelidir.