Почему предоставление частичной функции для броска карты во время выполнения, а не дает ошибку компиляции? - PullRequest
3 голосов
/ 19 июня 2019

Извиняюсь, если это очевидно, но я новичок в scala и получаю два неожиданных поведения со следующим кодом:

Seq(1, "a", 2, "b") map { 
    case i: Int => i+1
}

1) Я бы ожидал получить коллекцию, в которой строки не изменяются и числа увеличиваются на 1, но вместо этого я получаю ошибку.

2) Я считаю, что синтаксис case i: Int => i + 1 представляет собой частичную функцию, которая определена для Ints. Но, похоже, что map принимает полную функцию, так почему же она компилируется? Разве не было бы лучше, чтобы компилятор помог мне? Всегда лучше перемещать исключения времени выполнения для компиляции исключений времени.

Ответы [ 2 ]

6 голосов
/ 19 июня 2019

map() не принимает частичную функцию в качестве переданного параметра, но collect() делает.

Seq(1, "a", 2, "b") collect {
  case i: Int => i+1
}
//res0: Seq[Int] = List(2, 3)

Обратите внимание, что ввод, который не определен для частичной функции, не передается, а простоотброшен.То, что вы не хотите, чтобы ушел, нуждается в обработчике, даже если это просто обработчик case _ => по умолчанию.

Seq(1, "a", 2, "b", 'z') collect {
  case i: Int    => i+1        //increment ints
  case c: Char   => c.toUpper  //capitalize chars
  case s: String => s          //strings pass through
}
//res0: Seq[Any] = List(2, a, 3, b, Z)

Когда вы передаете частичную функцию в map(), компилятор не жалуется, потому что trait PartialFunction[-A, +B] extends (A) => B,Другими словами, частичная функция является типом функции.

Стоит также отметить, что при работе с частичными функциями ...

ответственность вызывающего абонента за вызов isDefinedAt перед вызовом apply ...

Таким образом, мы можем заключить, что collect() делает это, а map() нет.

3 голосов
/ 19 июня 2019

Попробуйте

Seq(1, "a", 2, "b") map {
  case i: Int => i + 1
  case any => any
}

, который выводит

res0: Seq[Any] = List(2, a, 3, b)

Причина, по которой Seq(1, "a", 2, "b") map { case i: Int => i + 1 } компилируется, состоит в том, что тип Seq(1, "a", 2, "b") равен Seq[Any].С другой стороны, следующее

Seq("a", "b").map { case i: Int => i + 1 }

дает ошибку компилятора

scrutinee is incompatible with pattern type;
[error]  found   : Int
[error]  required: String
[error]   Seq("a", "b").map { case i: Int => i + 1 }

, поскольку Seq("a", "b") имеет тип Seq[String], а { case i: Int => i + 1 } имеет тип PartialFunction[Int, Int].

...