2014-10-21 4 views
3

Я начинаю изучать Scala, и я не совсем понимаю некоторые способы сопоставления шаблонов. Может ли кто-нибудь объяснить мне, почему первый случай работает, но второй случай не работает?Scala pattern-matching confusion

def getFirstElement(list: List[Int]) : Int = list match { 
    case h::tail => h 
    case _ => -1 
} 

Scala> getFirstElement(List(1,2,3,4)) 
res: Int = 1 

Scala> 1 :: List(1,2) 
res: List[Int] = List(1, 1, 2) 
def getSumofFirstTwoElement(list: List[Int]): Int = list match { 
    case List(a: Int, b: Int)++tail => a + b 
    case _ => -1 
} 

<console>:11: error: not found: value ++ 

Scala> List(1,2) ++ List(3,4,5) 
res: List[Int] = List(1, 2, 3, 4, 5) 

ответ

6

Причина заключается в том, что нет unapply метод на объект типа ++. Причина, по которой :: работает потому, что за кулисами она действительно:

final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] { 
    override def tail : List[B] = tl 
    override def isEmpty: Boolean = false 
} 

Source

Это приводит к тому, как по шаблону реализован в Scala. Он использует extractors (или here), которые являются в основном объектами, которые содержат метод unapply, который предоставляется по умолчанию классами case.

+2

Также следует отметить, что это работает как hd :: tl, потому что оно заканчивается символом a:, что означает, что он может быть использован в этом правильном ассоциативном способе. Я начал придумывать способ заставить ваш ++ работать, но он просто не был бы симпатичен –

1

++ представляет собой метод на объект списка. Я думаю, что вы хотите:

def getSumofFirstTwoElement(list: List[Int]): Int = list match { 
    case a::b::tail => a + b 
    case _ => -1 
} 
+0

Это работает. Я понимаю ++ метод - это метод на объекте списка. Почему я не могу использовать это в шаблоне case-case? Благодарю. – Pierrew

+0

Как описал Джастин, его из-за неприменимости превращает объект в его компоненты. –

1

В случае, если два, ++ не используется для несанкционированного доступа. Вы хотите, чтобы экстрактор :: разложил список.

Хорошее объяснение here.

scala> def getSumofFirstTwoElement(list: List[Int]): Int = list match { 
    |  case a::b::t => a + b 
    |  case _ => -1 
    | } 
getSumofFirstTwoElement: (list: List[Int])Int 


scala> getSumofFirstTwoElement(List(1,2,3,4)) 
res0: Int = 3