Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between .map (...) and .map {...} in scala

Tags:

scala

I'm new in scala. Is there any the differences between the high order function follow brace or parentheses block?

For example:

  • List(1, 2, 3).map(i=> i + 1)

  • List(1, 2, 3).map {i => i + 1}

Both of them get same result: List(2, 3, 4)

But for this example List(1, 2).map { println("Hi"); _ + 1 } The result is below and why 'Hi' just print once?

Hi
List[Int] = List(2, 3)
like image 878
Little Roys Avatar asked Aug 23 '17 00:08

Little Roys


People also ask

What is map () method in Scala?

One such widely used method offered by Scala is map (). map () is a higher order function. Every collection object has the map () method. map () takes some function as a parameter. map () applies the function to every element of the source collection. map () returns a new collection of the same type as the source collection.

What is the difference between map () and map ()?

Important points about map () method: 1 map () is a higher order function. 2 Every collection object has the map () method. 3 map () takes some function as a parameter. 4 map () applies the function to every element of the source collection. 5 map () returns a new collection of the same type as the source collection.

What is the difference between flatMap() and map() transformation in Scala?

The returned DataFrame can have the same count or more elements than the current DataFrame. This is one of the major differences between flatMap () and map (), where map () transformation always returns the same number of elements as in input. flatMap [ U]( f : scala. Function1 [ T, scala.

How to iterate through keys and values of a map in Scala?

You can iterate through the keys and values of a Map using “foreach” loop. Here, we used method foreach associated with iterator to walk through the keys. Following is the example program. Save the above program in Demo.scala. The following commands are used to compile and execute this program.


2 Answers

A block in Scala is just an expression. Like parentheses, they are useful for grouping code together. Unlike parentheses, blocks don't contain just one expression, but can contain 1 or more expressions. The value of a block is the value of the last expression in it.

{ println("Hi"); _ + 1 } is equivalent to { println("Hi"); (i: Int) => i + 1 }. This is a block that prints out "Hi", and it's value is a function that adds one. The string is printed before execution exits the block, and the function that it produces doesn't know anything about the println.

Here are some examples of these rules:

list.map(i => i + 1)
//      ^----------^
//    function literal passed as argument

list.map(_ + 1)
//       ^---^
// Underscore shorthand for above

list.map({ i => i + 1 })
// Identical to above.
// The block only contains one expression, so it has the value of that expression
// Otherwise stated: { expr } === expr

list.map({ println("Hi"); _ + 1 })
//         ^-----2-----^  ^-3-^
//       ^------------1---------^
// 1: The argument to map is the value of this block
// 2: The first statement of the block prints something. This is only executed once,
//   because it's not the *block* being passed as argument, it's its value.
// 3: Function literal in underscore notation. This is the value of the block
//   and this is what map sees.
// Order of operations (approx. bytecode):
// load list onto stack
// load string "Hi" onto stack
// call println and pop string off stack
// create function (i => i + 1) on top of stack
// invoke map with argument (i => i + 1), popping list and function off stack

list.map { println("Hi"); _ + 1 }
// Identical to above, but Scala lets you omit the () because you are using {}

list.map({ i => println("Hi"); i + 1 })
// Function literals grow as big as they can be.
// The block contains only one expression, which is (i => println("Hi"); i + 1)
// This function prints "Hi" and then returns i + 1
// This call to map will print "Hi" for every element

list.map { i => println("Hi"); i + 1 }
// Identical to above, but Scala lets you omit the () because you are using {}

Additionally, there are by-name parameters to deal with. By-name parameters are declared like so:

def func(a: => String) // Not () => String, it's => String

When you have by-name parameter, then

func { println("x"); _ + 1 }

actually passes the whole block as argument. The block still evaluates to i => i + 1, but func is in control of when that evaluation happens. Specifically, the code of the block is turned into a Function0 and passed into func, which can call it as many times as it likes, with side effects. This can be used to great effect, essentially allowing normal functions to act like custom control flow operators:

@tailrec def repeat(i: Int)(op: => Any): Unit
= if(i == 0) ()
  else {
    require(i >= 0, s"negative repeat amount: $i")
    op // Evaluate op
    repeat(i - 1)(op) // Won't evaluate op; will let sub-call deal with it
  }

repeat(5) { println("Hi"); println("Bye") }
// Hi
// Bye
// Hi
// Bye
// Hi
// Bye
// Hi
// Bye
// Hi
// Bye

Note how the parentheses are omitted around the block, which really makes this seem like the ability to define a control flow operator.

like image 154
HTNW Avatar answered Oct 19 '22 04:10

HTNW


In general, you would use parentheses for enclosing simple function parameters:

l.map( x => x * 2 )

and curly braces for enclosing more complex code block or partial functions including case pattern matching:

l.map{ x =>
  val y = x * 2
  y
}

l.map{
  case x if x%2 == 0 => x * 2
  case _ => 0
}

As to the reason why Hi is only printed once, List(1, 2).map{ println("Hi"); _ + 1 } is no different from List(1, 2).map{ println("Hi"); x => x + 1 }. To include println in the map iteration:

List(1, 2).map{ x => println("Hi"); x + 1 }
// Hi
// Hi
// res1: List[Int] = List(2, 3)
like image 37
Leo C Avatar answered Oct 19 '22 03:10

Leo C