2013-05-04 116 views
7

为什么不可能链接模式匹配结构?例如,下面是合法的,如果无厘头,模式匹配“返回”值

val a = ADT(5) 

val b = a match { 
    case ADT(a) if a > 4 => ADT(a * 3) 
    case ADT(a) => ADT(a + 1) 
} 
b match { 
    case ADT(a) if a > 13 => doSomething(a) 
    case _ => {} 
} 

但下面的不是:

a match { 
    case ADT(a) if a > 4 => ADT(a * 3) 
    case ADT(a) => ADT(a + 1) 
} match { 
    case ADT(a) if a > 13 => doSomething(a) 
    case _ => {} 
} 

我怀疑这是因为我不应该摆在首位那样做,但原则我不明白为什么它不合法。

+4

'(匹配{..})匹配{..}'会工作。 – user2246674 2013-05-04 04:55:50

回答

5

是的,它应该工作,因为(几乎)在Scala中的所有内容都是表达式,并且每个表达式都可以用作模式匹配。

在这种情况下,模式匹配是一个表达式,所以它可以被另一个“链接”模式匹配使用。但编译器不喜欢它。

给编译器括号中的小提示可以帮助:

case class ADT(value: Int) 

val a = ADT(5) 

(a match { 
    case ADT(a) if a > 4 => ADT(a * 3) 
    case ADT(a) => ADT(a + 1) 
}) match { 
    case ADT(a) if a > 13 => println(a) 
    case _ => {} 
} 
+0

我偶然发现了圆括号的解决方法,但我不明白为什么它在这里是必要的,但没有必要用'val a = if(false)6 else if(true)if(true)5 else 3 else 2' – 2013-05-04 05:11:22

+0

@CarlSummers编译器只能推断这么多。这只是操作的顺序。如有疑问(您或编译器)明确。 (我实际上对Scala很陌生,但这是我喜欢的东西之一。) – hangtwenty 2013-08-13 12:11:44

3

你的直觉是正确的;这不是废话—通常你能够链接中缀运营商在这种方式,没有括号(如其他用户已建议)。实际上,match曾经作为—的方法实现,并且作为中缀运算符(默认情况下为左关联)—工作,因此您的备用语法可以工作。但是,在Scala 2.5中,match被作为一种特殊的语言结构而不是一种方法。不幸的是,我不知道为什么这样做,但这是原因:match而不是一个中缀操作符,尽管看起来如此。