Синтаксис Function.tupled и заполнителя

Я видел это использование примера Function.tupled в другом ответе: Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length).

Оно работает:

scala> Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
<console>:5: warning: method tupled in object Function is deprecated: 
Use `f.tuple` instead
       Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
                                                ^
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

Кажется, я могу обойтись без синтаксиса заполнителя.

scala> Map(1 -> "one", 2 -> "two") map (x => x._1 -> x._2.length)
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

Прямое использование синтаксиса заполнителя не работает:

scala> Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length)
<console>:5: error: wrong number of parameters; expected = 1
       Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length)

Как работает Function.tuple? Кажется, в Function.tupled(_ -> _.length) много чего происходит. Кроме того, как бы я использовал его, чтобы не получать предупреждение об устаревании?


person huynhjl    schedule 01.03.2010    source источник
comment
@huynhjl Устаревание Function.tupled является результатом понимания того, что функция должна знать, как кортежировать себя без посторонней помощи. Однако это действительно не очень хорошо работает с выводом типов. Я очень надеюсь, что они не удалят Function.tupled, не сделав механизм вывода типов достаточно умным, чтобы обойти эту проблему.   -  person Daniel C. Sobral    schedule 01.03.2010


Ответы (1)


ОБНОВЛЕНИЕ Устаревание было удалено сегодня в ответ на к этой проблеме.


Обработка функции — это просто адаптация FunctionN[A1, A2, ..., AN, R] к Function1[(A1, A2, ..., AN), R]

Function.tuple устарел в пользу FunctionN#tupled. Следствием этого (возможно, непреднамеренным) является то, что средство вывода типов не может вывести типы параметров в:

scala> Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled                 
<console>:5: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$minus$greater(x$2.length))
       Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled
                                        ^
<console>:5: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$minus$greater(x$2.length))
       Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled

Любой из них будет работать:

scala> Map(1 -> "one", 2 -> "two") map { case (a, b)  => a -> b.length }
res8: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

scala> Map(1 -> "one", 2 -> "two") map ((_: Int) -> (_: String).length).tupled           
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

scala> Map(1 -> "one", 2 -> "two") map ((p: (Int, String))  => p._1 -> p._2.length)
res12: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

Я предлагаю вам прочитать ответы на этот недавний вопрос, чтобы получить более глубокое представление о «_» в литералах функций и о том, как работает вывод типов:

Что в Scala в чем разница между использованием `_` и использованием именованного идентификатора?

ОБНОВЛЕНИЕ

В ответ на комментарий, это так.

scala> val f = (x:Int, y:String) => x + ": " + y
f: (Int, String) => java.lang.String = <function2>

scala> f.tupled
res0: ((Int, String)) => java.lang.String = <function1>

scala> Map(1 -> "1") map f.tupled
res1: scala.collection.immutable.Iterable[java.lang.String] = List(1: 1)

Для этого требуется Scala 2.8. Обратите внимание, что Map#map может привести к другой карте, если возвращаемый тип функции — Tuple2, в противном случае — список, как указано выше.

person retronym    schedule 01.03.2010
comment
Спасибо за ответ. Что меня смущает, так это то, что это не работает: val f = (x:Int, y:String) => x + ": " + y; f.tupled. Разве это не должно возвращать версию f, которая работает с кортежем (Int, String)? - person huynhjl; 01.03.2010
comment
хорошо, я вижу, это многое объясняет. Я повторно протестировал версию 2.8.0.Beta1, и она работает, как и ожидалось. Раньше я пробовал с 2.8.0.Beta1-RC5, которая была у меня на пути. Мне нужно избавиться от RC5... - person huynhjl; 01.03.2010