Использование кортежей в 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