2

I have a string array:

val str:Array[String] = Array("aa","bb")
scala> str.foreach(println) // works
aa
bb
scala> str.foreach(println()) // println() also returns a Unit, doesn't it?
                          ^
error: type mismatch;
found   : Unit
required: String => ?

Why does str.foreach(println) work with no problem, but str.foreach(println()) doesn't?
Isn't println equivalent to println() which returns a Unit value?

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
Julia Chang
  • 181
  • 1
  • 8
  • 6
    `foreach` expects a **function** from **String** to **Unit**. - `println` is a **method** with many overloaded versions. - **Scala** has something called _eta-expansion_ which allows to implicitly convert a **method** to a **function** when one is expected. Thus `foreach(println)` is equivalent to `foreach(s => println(s))`, which compiles. On the other hand `foreach(println())` is just an empty print, which has type **Unit** which is not what `foreach` expects, thus it does not compiles. – Luis Miguel Mejía Suárez Oct 03 '19 at 02:41
  • @LuisMiguelMejíaSuárez That is, foreach(s => println(s)) is equivalent to foreach(println(_)) which is equivalent to foreach(println) due to eta-expansion, correct? The println argument in foreach is actually println(_) that has an argument, howerver println() has no argument even both of them return a Unit value. Thanks. – Julia Chang Oct 03 '19 at 06:45

2 Answers2

7

println is a method (convertible to a function) that takes input (String in this case) and produces a result (Unit) and a side-effect (printing to StdOut).

println() is the invocation of a method that takes no input, produces a result (Unit), and a side-effect (\n to StdOut).

They aren't the same.

The 2nd one won't work in a foreach() because foreach() feeds elements (strings in this case) to its argument and println() won't take the input that foreach() is feeding it.

This will work str.foreach(_ => println()) because the underscore-arrow (_ =>) says: "Ignore the input. Just throw it away and invoke what follows."

jwvh
  • 50,871
  • 7
  • 38
  • 64
1

The reason is you are missing the underscore. Try this

str.foreach(println(_))
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
yafiet andebrhan
  • 161
  • 1
  • 3
  • 11