Использование кортежей в map, flatmap,... частичных функциях

Если я сделаю:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { t => t._1 + t._2 }

Все нормально.

Если я сделаю:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { case (b, n) => b + n }

Это тоже нормально.

Но если я сделаю:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { (b, n) => b + n }

Она не будет работать.
Почему я должен использовать ключевое слово case для использования именованных кортежей?

3 ответа

Решение

Сообщение об ошибке с 2.11 является более объяснительным:

scala> l map { (b, n) => b + n }
<console>:9: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
      Consider a pattern matching anonymous function, `{ case (b, n) =>  ... }`
              l map { (b, n) => b + n }
                       ^
<console>:9: error: missing parameter type
              l map { (b, n) => b + n }
                          ^

За подачу заявки вы получаете "автоматическую запись":

scala> def f(p: (Int, Int)) = p._1 + p._2
f: (p: (Int, Int))Int

scala> f(1,2)
res0: Int = 3

где вы поставили два аргумента вместо одного.

Но вы не получите авто-развязку.

Люди всегда хотели, чтобы это работало именно так.

Эту ситуацию можно понять с помощью types внутренней функции.

Во-первых, синтаксис типа функции параметра для map Функция заключается в следующем.

Tuple2[Int,Int] => B //Function1[Tuple2[Int, Int], B]

Первый параметр функции расширяется до этого.

(t:(Int,Int)) => t._1 + t._2 // type : Tuple2[Int,Int] => Int

Хорошо. Тогда вторая функция.

(t:(Int, Int)) => t match {
  case (a:Int, b:Int) => a + b
}

Это тоже нормально. В случае неудачи,

(a:Int, b:Int) => a + b 

Давайте проверим типы функции

(Int, Int) => Int // Function2[Int, Int, Int]

Так что тип функции параметра неправильный.

В качестве решения вы можете преобразовать несколько функций арности в режим кортежа и обратно с помощью вспомогательных функций в объекте Function. Вы можете сделать следующее.

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map(Function.tupled((b, n) => b + n ))

Пожалуйста, обратитесь к API функции для получения дополнительной информации.

Тип аргумента функции, передаваемой функции карты, примененной к последовательности, определяется типом элементов в последовательности. Особенно,

сценарий 1: l map { t => t._1 + t._2 } такой же как l map { t: ((String, String)): (String) => t._1 + t._2 } но короче, что возможно из-за вывода типа. Компилятор Scala автоматически определяет тип аргумента (String, String) => String

Сценарий 2: вы также можете написать в более длинной форме

l map { t => t match {
    case(b, n) => b + n
  }
}

Сценарий 3: функция неверного типа передается на карту, которая похожа на

def f1 (a: String, b: String) = a + b

def f2 (t: (String, String)) = t match { case (a, b) => a + b }

l map f1 // won't work

l map f2
Другие вопросы по тегам