2014-01-16 2 views
5

у меня есть:Scala - Match Кортеж Вариантов

val foo = Some(List(1, 2, 3)) -> Some("y") 

Я хотел бы, чтобы бросить спичку его:

foo match { 
    case (Some(x), Some(y)) => println(x + " " + y) 
    case _ => println("error") 

Это прекрасно работает Some(List(1, 2, 3) -> Some("score")), но не для Some(List(1, 2, 3) -> None, None -> Some("y") или None -> None с:

error: constructor cannot be instantiated to expected type; 
    found : Some[A] 
    required: None.type 
error: not found: value ... 

Почему это так?

Конечно, я мог бы использовать getOrElse(), но это не выглядит так элегантно.

Thx много, Карстен

Update:

foo match { 
case (x: Some[List[Int]], y: Some[Int]) => println(x.get) 
case _ => println("error") 
} 

завершается, а также с:

error: pattern type is incompatible with expected type; 
found : Some[Int] 
required: None.type 

Я думаю, что case _ позаботится об этом.

ответ

6

Это компилятор говорит вам что-то. Если у вас есть выражение, как

val foo = Some(List(1, 2, 3)) -> None 

Он будет иметь тип (Некоторый [Список [Int]], None.type), которые вы можете легко увидеть, от ввода в выражении в консоли лестницы

scala> val foo = Some(List(1, 2, 3)) -> None 
foo: (Some[List[Int]], None.type) = (Some(List(1, 2, 3)),None) 

Знаете ли вы, во время компиляции, что второй элемент кортежа может быть только когда-либо None, совпадение с Some может никогда не получиться. Отсюда сообщение об ошибке.

Если вы дадите foo менее ограничительный тип, он будет работать.

val foo : (Option[List[Int]], Option[String]) = Some(List(1, 2, 3) -> None 

Обратите внимание, что это точно так, как должно быть. Согласование чего-то, что никогда не может произойти, почти наверняка является ошибкой. Вы должны повысить до любого, чтобы избежать ошибки времени компиляции (но тогда вы получите ошибку времени выполнения.

+0

Хм, это имеет смысл. Однако можно определить foo._1 и foo._2. Это то, что я хочу Знаю. – Karsten

+0

Хорошо, теперь я понимаю. Я думал, что foo будет иметь тип (Option [List [Int]], Option [Any]). – Karsten

+0

Вы могли бы так поступить. Но разработчики языка scala решили дать Some и None свой собственный тип, так что такие вещи можно найти во время компиляции. Обычно это не проблема в реальном коде, потому что вы должны определить foo для самого общего типа, который вы хотите обработать, например (Option [List [Int [ ]], Option [String]). –

2

В коде ниже, Scala получите ошибку компиляции на foo match но компилируется и корректно работает с foo2/foo3:

val foo = None -> None 
val foo2: (Option[Any], Option[Any]) = None -> None 
val foo3: (Option[Any], Option[Any]) = foo 

foo match { 
    case (Some(x), Some(y)) => println(x + " " + y) 
    case _ => println("error") 
} 
Смежные вопросы