1

I'm taking my first steps in scala, and here is an "hello world"-like code :

package test
object Main {
def main(args: Array[String]): Unit = {
        println("Blabla something : " + 3)
        println("Blabla something : " , 3)
    }
}

Here is the output I get :

Blabla something : 3
(Blabla something : ,3)

Why are there parentheses printed in the second line, along with the "," ? I was expecting the same output as in the first line.

Note : I tried searching for scala println parentheses and such, but all I get is posts on how to remove the parentheses from the code, not from the output.

nha
  • 17,623
  • 13
  • 87
  • 133
  • 2
    Similar to [this question](http://stackoverflow.com/questions/5997553/why-and-how-is-scala-treating-a-tuple-specially-when-calling-a-one-arg-function). What happens here is "auto-tupling" (see @LimbSoup's answer) – 0__ Jun 22 '14 at 22:16
  • @0__ I was indeed suspecting some feature of scala playing it's part here, but I had no idea which one. I'll dig into that thanks. – nha Jun 22 '14 at 23:38

3 Answers3

6

To see this in action you could do something like this in the REPL:

scala> import scala.reflect.runtime.universe.TypeTag
scala> def printz[T](x: T)(implicit tT: TypeTag[T]) = { val v = x; println(s"$v : $tT")}

scala> printz("Blabla something : " , 3)
(Blabla something : ,3) : TypeTag[(String, Int)]

TypeTag[(String, Int)] hints at the tuple (String, Int).

  • +1 That seems cool, would you (briefly) explain what happens in your `printz` function ? – nha Jun 22 '14 at 23:34
  • 1
    TypeTags are a way of reifying types at runtime ([TypeTags and Manifests](http://bit.ly/1pBwiOX)) and captured as an implicit `tT`. So `printz` is like `println` except it also prints the typetag of some type `T` (type of value `x` that is passed to the method) along with the value `x`. In general one should not use reflection. But here it is a great way to find what's going on under the hood as `println` takes `Any`. (I'd argue that the behaviour shown is actually a mistake and should have been flagged but can't be because any value works for println.) Does that help? – user3765699 Jun 23 '14 at 00:40
2

The comma has a special meaning. The compiler is interpreting the arguments of println("Blabla something : " , 3) as a Tuple, because of the comma. In particular, one with type (String, Int).

Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
1

When you call

println("Blabla something : " , 3)

the following happens:

  1. println only expects one argument. Also, in Scala functions with one argument can be called without parentheses. That means that println interpretes everything after it as one parameter and adds parentheses around it, and your command is getting translated as:

    println(("Blabla something : " , 3))

  2. When the argument given to println is not a String, it is converted to a String by calling its toString method, which exists for every object (in one or another form). For a Tuple (which is the argument given to println in this example) the default toString method just prints the tuple as a pair of values, surrounded with quotes, which is exactly what you see.

Ashalynd
  • 12,363
  • 2
  • 34
  • 37
  • Functions may never be called without parentheses, and the only time methods can be called without parentheses is with infix notation, which isn't what is happening here. `println "x"` is a syntax error, though `Console println "x"` works. That said, this is otherwise a correct description of what happens. – wingedsubmariner Jun 22 '14 at 23:01
  • @wingedsubmariner I'm not sure I get it. Are you saying that the parentheses are added for the tuple and not the function ? (Wouldn't that be weird ?) – nha Jun 22 '14 at 23:40
  • 2
    @nha Scala doesn't interpret `println(a, b)` as passing the tuple `(a, b)` to `println`, it sees it as an attempt to pass two parameters to `println`, discovers that `println` doesn't take two parameters but will accept a tuple (the type of its parameter is `Any` which is a supertype of all the tuple types) and so wraps the parameters into a tuple, making `println((a, b))`. See [this answer](http://stackoverflow.com/a/5998559/1224627). – wingedsubmariner Jun 23 '14 at 00:16
  • @wingedsubmariner OK I get it now. I didn't realise that println took only one parameter. Thanks for the clarification. – nha Jun 23 '14 at 07:35