2013-07-01 3 views
0

Это кажется не логичным для меня:Карта переменную типа пара - невозможно

scala> val a = Map((1, "111"), (2, "222")) 
a: scala.collection.immutable.Map[Int,String] = Map(1 -> 111, 2 -> 222) 

scala> val b = a.map((key, value) => value) 
<console>:8: error: wrong number of parameters; expected = 1 
     val b = a.map((key, value) => value) 
           ^
scala> val c = a.map(x => x._2) 
c: scala.collection.immutable.Iterable[String] = List(111, 222) 

Я знаю, что я могу сказать val d = a.map({ case(key, value) => value })

Но почему нельзя сказать a.map((key, value) => value)? Существует только один аргумент типа Tuple2[Int, String] или Pair of Int, String. В чем разница между a.map((key, value) => value) и a.map(x => x._2)?

UPDATE:

val myTuple2 = (1, 2) - это одна переменная, правильно?

for ((k, v) <- a) yield v - (k, v) также является только одной переменной, правильно?

map((key, value) => value) - 2 переменных. странно.

Как я могу указать переменную типа Tuple2 (или любого другого типа) в map без использования case?

UPDATE2:

Что случилось с этим?

Map((1, "111"), (2, "222")).map(((x,y):Tuple2[Int, String]) => y) - неправильные

Map((1, "111"), (2, "222")).map(((x):Tuple2[Int, String]) => x._2) - OK

+1

Существует только одна переменная типа 'Tuple2 [Int, String]'. map имеет подпись 'def map [B] (f: (A) ⇒ B): Map [B]' - он принимает функцию, которая принимает ** одну ** переменную типа A и производит ** одну ** выходную переменную тип B (и 'x => x._2' является примером такой функции, тогда как' (ключ, значение) => значение' не является) –

+0

@ om-nom-nom, '(key, value)' - является одной переменной типа Tuple2. –

+0

, если это верно. «Список (1,2,3,4) .reduce ((x, y) => x + y)» невозможен –

ответ

6

Хорошо, вы все еще не убежден.В подобных случаях вполне разумно отбросить источник истины (ну, любопытный): Священная спецификация (aka, Scala Language Specification).

enter image description here

Таким образом, в анонимные параметры функции рассматриваются на индивидуальной основе, а не в целом кортеже группы (и это очень умный, в противном случае, как бы вы назвали анонимную функцию с 2, ... п параметры?).

В то же время

val x = (1, 2) 

является один элемент типа Tiple2 [Int, Int] (если вы заинтересованы вы можете найти соответствующий раздел спецификации, а).

for ((k, v) <- a) yield v 

В этом случае у вас есть одна переменная, распакована на две переменные. Он похож на

val x = (1, 2) // one variable -- tuple 
val (y,z) = x // two integer variables unpacked from one 

Некоторые называют эту уступке деструктурирующего и это частный случай сопоставления с образцом. И вы уже предоставили другой пример сопоставления с образцом в действии:

a.map({ case(key, value) => value }) 

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

+0

Итак, как указать переменную типа Tuple2 (или любого другого типа) на карте без использования случая? –

+0

@MariusKavansky в настоящее время нет другого напуганного способа (если бы я понял: вы хотите иметь 'for ((k, v) <- m), выдать v'-подобный синтаксис для .map без использования * case * и явного адреса). Я видел поток на ML, но он полна противоречий и угловых дел, поэтому я сомневаюсь, что вы могли бы сделать это в обозримом будущем. –

+0

@MariusKavansky Я не мог найти нить, о которой я говорил, но [есть друг друга] (https://groups.google.com/d/topic/scala-debate/pt9pqYS0S7g/discussion) –

2

Вы в основном задаете эти же вопросы:

Scala - can a lambda parameter match a tuple?

Вы уже перечислены большинство из них вариант, перечисленных здесь , включая принятый ответ на использование PartialFunction.

Однако, так как вы используете ваш лямбда в map функции, вы можете использовать for понимание вместо:

for ((k, v) <- a) yield v 

В качестве альтернативы, вы можете использовать метод Function2.tupled исправить тип вашей Lambda в:

scala> val a = Map((1, "111"), (2, "222")) 
a: scala.collection.immutable.Map[Int,String] = Map(1 -> 111, 2 -> 222) 
scala> a.map(((k:Int,v:String) => v).tupled) 
res1: scala.collection.immutable.Iterable[String] = List(111, 222) 

Чтобы ответить на ваш вопрос в вашей теме с ом-ном-ном выше, посмотрите на этот вывод:

scala> ((x:Int,y:String) => y).getClass.getSuperclass 
res0: Class[?0] forSome { type ?0 >: ?0; type ?0 <: (Int, String) => String } = class scala.runtime.AbstractFunction2 

Обратите внимание, что суперкласс анонимной функции (x:Int,y:String) => y является Function2[Int, String, String], не Function1[(Int, String), String].

+0

Это не то, о чем я прошу. –

+0

@MariusKavansky - На самом деле, это именно то, что вы просите - вы просто этого не осознаете! Вы должны слушать om-nom-nom. – DaoWen

+0

Посмотрите мое обновление. –

-2

Вы можете использовать поиск по шаблону (или частичную функцию, в данном случае, это то же самое), обратите внимание на угловые скобки:

val b = a.map{ case (key, value) => value } 
+1

Он уже перечислил этот вариант в своем вопросе. – DaoWen