Это из-за того, что мы не можем выполнить <
(меньше чем) операцию с типом AnyVal
.
scala> val donut = Tuple2("Donut", 2.5)
donut: (String, Double) = (Donut,2.5)
scala> val plain = Tuple2("Plain", 1)
plain: (String, Int) = (Plain,1)
Как вы можете видеть выше. Когда вы определяете Tuple2("Donut", 2.5)
, 2.5
выводится на Double
, а в Tuple2("Plain", 1)
, 1
выводится как Int
, поскольку вы не указали тип явно.
Теперь, когда вы создаете список этих кортежей, из-за типа списка вывода тип будет (String, AnyVal)
.
scala> val tuples = List(donut, plain)
tuples: List[(String, AnyVal)] = List((Donut,2.5), (Plain,1))
Теперь, когда вы выполняете case x if x._2 < 2
, вы фактически сравниваете тип AnyVal
с числом, т.е. 2
, что невозможно, поскольку компилятор считает, что x._2
- это AnyVal
(не число) и не будет компиляции. Поэтому вы получаете исключение во время компиляции.
<console>:22: error: value < is not a member of AnyVal
case x if (x._2 < 2) => "price under 2"
Во втором случае, т. Е. Когда вы определили кортеж как Tuple2("Plain", 1.0)
, его тип номера также выводится как Double
.
scala> val donut = Tuple2("Donut", 2.5)
donut: (String, Double) = (Donut,2.5)
scala> val plain = Tuple2("Plain", 1.0)
plain: (String, Double) = (Plain,1.0)
И, когда вы создаете список кортежей, так как оба имеют одинаковый тип, т.е. (String, Double)
, список будет иметь тип List[(String, Double)]
.
scala> val tuples = List(donut, plain)
tuples: List[(String, Double)] = List((Donut,2.5), (Plain,1.0))
И x._2 < 2
будут компилироваться правильно, так как вы вызываете <
в двойном (число).