2010-01-08 63 views
6

我不明白为什么下面的情况不匹配。 Null应该是Any的一个实例,但它不匹配。有人可以解释发生了什么吗?匹配元组为null

val x = (2, null) 
x match { 
    case (i:Int, v:Any) => println("got tuple %s: %s".format(i, v)) 
    case _ => println("catch all") 
} 

prints catch all 

谢谢。

回答

9

这与指定完全相同。

Type patterns consist of types, type variables, and wildcards. 
A type pattern T is of one of the following forms: 

* A reference to a class C, p.C, or T#C. 
This type pattern matches any non-null instance of the given class. 

有趣的是,如此多的相关性归因于null是Any的成员。它是每种类型的成员,但AnyVal和Nothing。

+0

我认为这个选择的动机是它匹配JVM上“instanceof”字节码的行为。 – 2010-01-08 17:09:47

+0

那,并让null通过将完全吸吮。你必须有一个淫秽的零容忍去寻找动机! – extempore 2010-01-08 23:11:13

+0

“Obscene null tolerance”或者没有,有一种说法是,类型模式“x:T”的最自然和直接的含义是匹配类型T的任何成员。例如,它可以避免像“val x:Any = null“ - 很好,但是”val(x:Any,y:Any)=(null,null)“ - MatchError。这“完全吸引”了。 我并不是说Scala做出了错误的选择,也没有说它是特别重要的,因为惯用的Scala避免使用null。 – 2010-01-09 09:08:08

1

我只是猜测在这里,因为我不是Scala专家,但根据的任何类在斯卡拉我认为,因为null不是一个对象,它不是来自任何和作为这与列出的第一种情况不符。

添加下面的代码示例。它在运行时打印“别的东西”。

val x = (2, null) 
x match { 
    case (i:Int, v:Any) => println("got tuple %s: %s".format(i, v)) 
    case (i:Int, null) => println("something else %s".format(i)) 
    case _ => println("catch all") 
} 

进一步的研究之后,好像空应与任何意义匹配documentation说,它扩展AnyRef延伸的任何。

编辑:像其他人一样说。第一个案件的目的不符合null。它在文档中指定。

+0

'null'是'Null'类的单例实例。 – 2010-01-08 01:46:26

+0

这很有道理。 null的文档(http://www.scala-lang.org/docu/files/api/scala/Null.html)表示它扩展了扩展Any的AnyRef,所以它看起来应该匹配大小写(i:Int,五:任何)。 – 2010-01-08 01:50:14

3

即按规定(Scala的参考2.7,8.2节)是:

的引用对类C,P.C,或T#℃。 此类型模式匹配给定类的任何非空实例。 请注意,该类的前缀(如果给出 )与确定类实例的 相关。对于 实例,模式p.C仅匹配 类别C的实例,这些类别是使用路径p创建的 作为前缀。

6

您是否尝试过v占位什么

val x = (2, null) 
x match { 
    case (i:Int, v) => println("got tuple %s: %s".format(i, v)) 
    case _ => println("catch all") 
}