сопоставить кортеж с нулем

Я не понимаю, почему следующий случай не подходит. Null должен быть экземпляром Any, но не соответствует. Может кто-нибудь объяснить, что происходит?

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

Спасибо.


person agilefall    schedule 08.01.2010    source источник


Ответы (4)


Это точно так, как указано.

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.

Интересно, что так много значимости приписывается нулевому членству в Any. Это член всех типов, кроме AnyVal и Nothing.

person psp    schedule 08.01.2010
comment
Я предполагаю, что мотивация для этого выбора заключается в том, что он соответствует поведению байт-кода instanceof на JVM. - person Matt R; 08.01.2010
comment
Это, а также пропуск null - полный отстой. У вас должна быть непристойная нулевая толерантность, чтобы искать мотивацию! - person psp; 09.01.2010
comment
Неприличная пустая толерантность или нет, но есть аргумент, что наиболее естественным и понятным значением для шаблона типа x: T является соответствие любому члену типа T. Например, это позволило бы избежать таких нарушений, как val x: Any = null - отлично, но val (x: Any, y: Any) = (null, null) - MatchError. Это тоже полный отстой. Я не говорю, что Scala сделал неправильный выбор, и не говорю, что это особенно важно, учитывая, что идиоматический Scala избегает использования null. - person Matt R; 09.01.2010
comment
Это плохой пример, поскольку эта проблема не имеет ничего общего с null. val (x: Int, y: Long) = (5, 5) также не выполняется с ошибкой соответствия. В любом случае, если вы используете null таким образом, что это возникает, я предполагаю, что вы делаете это неправильно. - person psp; 09.01.2010
comment
Боюсь, я не слежу за тобой. Я предполагаю, что ваш пример не работает, потому что второй 5 тип, выведенный как Int, поэтому он не проходит проверку типа во время выполнения, но это, похоже, не применимо к моему примеру. - person Matt R; 11.01.2010

Вы пробовали использовать заполнитель v для чего-нибудь?

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

Это как указано (Scala Reference 2.7, раздел 8.2):

Ссылка на класс C, p.C или T # C. Этот образец типа соответствует любому ненулевому экземпляру данного класса. Обратите внимание, что префикс класса, если он указан, имеет значение для определения экземпляров класса. Например, шаблон p.C соответствует только экземплярам классов C, которые были созданы с путем p в качестве префикса.

person Daniel C. Sobral    schedule 08.01.2010

Я просто предполагаю, поскольку я не эксперт по scala, но согласно документация для класса Any в scala Я думаю, что, поскольку null не является объектом, он не является производным от Any и поэтому не соответствует первому из перечисленных случаев.

Добавление примера кода ниже. При запуске выводит "что-то еще".

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")  
}  

После дополнительных исследований кажется, что значение null должно соответствовать какому-либо значению в документации говорит, что он расширяет AnyRef, который расширяет Any.

РЕДАКТИРОВАТЬ: Как все сказали. Первый случай не соответствует нулю намеренно. Это указано в документации.

person Brian Hasden    schedule 08.01.2010
comment
null - это одноэлементный экземпляр класса Null. - person Daniel C. Sobral; 08.01.2010
comment
В этом есть смысл. Документация для null (scala-lang.org/docu/files /api/scala/Null.html) говорит, что он расширяет AnyRef, который расширяет Any, поэтому кажется, что он должен соответствовать case (i: Int, v: Any). - person Brian Hasden; 08.01.2010