Why is this β€œcase" necessary?

object Test1 { def main(args: Array[String]) { val list = List("a", "b") list map { x β‡’ println(x) } list map { case x β‡’ println(x) } val list2 = List(("aa", "11")) list2 map { case (key, value) β‡’ println("key: "+key+", value: "+value) } } } 

Pay attention to the last line, why you need to use the case keyword, but list map { x β‡’ println(x) } can delete it?

+4
source share
5 answers
 { case (key, value) => f } 

- this is not the same as

 { (key, value) => f } 

The first is a pattern match, which splits Tuple2 into its components, assigning their values ​​to key and value . In this case, only one parameter is skipped (tuple). { x => println(x) } works because x assigned a tuple and println prints it.

The second function, which takes two parameters and does not create a pattern match. Since map requires a function that takes one parameter, the second case is incompatible with map .

+9
source

You cannot break a tuple in a functional literal. That's why you have to use a case to match them. Another way: bind your function with two arguments to match:

 import Function.tupled list2 map tupled { (key, value) => println("key: "+key+", value: "+value) } 
+14
source

list2 has elements of type Tuple2[Int, Int] , so the signature of the function you must pass to the map (in this case ... foreach is a more natural choice when you return nothing), Tuple2[Int, Int] => Unit . That is, this requires one argument of type Tuple2[Int, Int] .

Since Tuple2 supports unapply , you can use pattern matching to break this tuple inside your function, as you did:

 { case (key, value) β‡’ println("key: "+key+", value: "+value) } 

The signature of this function is still Tuple2[Int, Int] => Unit

It is identical and probably compiled with the same bytecodes as:

 { x: Tuple2[Int, Int] => println("key: "+x._1+", value: "+x._2) } 

This is one of many examples where Scala combines orthogonal concepts in a very pleasant way.

+4
source

list2 map { x => println(x) } works without problems for me. If you want to match the pattern (dividing the argument into its parts according to its structure), you always need a case . Alternatively you can write:

 list2 map { x => println("key: "+x._1+", value: "+x._2) } 

BTW, map should be used to convert the list to another. If you just want to see all the items in a list, use foreach or for understanding.

+3
source

I am still studying Scala, but I believe that what happens is that you define a partial function that takes one argument. When calling methods such as List.map or List.foreach, which require only one argument, you can omit the underscore or the name val.

An example of the oval name val in closure:

 val v = List("HEY!", "BYE!") v.foreach { Console.println } // Pass partial function, automatically 

This is the same as:

 val v = List("HEY!", "BYE!") v.foreach { Console.println _ } // Pass partial function, explicitly 

Using anonymous val:

 val v = List("HEY!", "BYE!") v.foreach { Console.println(_) } // Refer to anonymous param, explicitly 

Or using the name val:

 val v = List("HEY!", "BYE!") v.foreach { x => Console.println(x) } // Refer to val, explicitly 

Your closure uses a partial function (case statement) that takes an anonymous variable and immediately turns it into a tuple associated with two separate variables.

I guess I went up one of the fragments above. When I get to my work computer, I will check in the REPL.

Also, look at the Currying function in Scala for more information.

+1
source

Source: https://habr.com/ru/post/1341132/


All Articles