What is the rule for parenthesis in Scala method invocation?

Scala

Scala Problem Overview


Isn't toList a method that converts something into a List?

If yes so why can't I use parenthesis with it? I must be missing something more fundamental here.

Here is the example:

val l = Array(1,2,3).toList // works fine

val l = Array(1,2,3).toList() // gives the error below

> Not enough arguments for method apply: (n: Int)Int in trait > LinearSeqOptimized. Unspecified value parameter n.

Scala Solutions


Solution 1 - Scala

If a method is defined as

def toList = { /* something */ }

then it must be called as

object.toList

with no extra parentheses. We say that this method has zero parameter lists.

We could also define a parameter list but put nothing in it:

def toList() = { /* something */ }

Now, we could call either of

object.toList()
object.toList

since Scala allows the shortcut of omitting parentheses on method calls.

As far as the JVM is concerned, there is no difference between the first definition ("zero parameter lists") and the second ("one empty parameter list"). But Scala maintains a distinction. Whether this is a good idea or not is debatable, but the motivation might be clearer when you realize that we can also

def toList()() = { /* something */ }

which is known as two empty parameter lists, and then call any of

object.toList()()
object.toList()
object.toList

and now, if we were to convert this into a function, we would type it as

() => () => T   /* T is the return value of the something */

while the second definition would be

() => T

which is clearly different conceptually, even if practically you use it the same way (put in nothing and sooner or later get out a T).

Anyway, toList doesn't need any parameters, and the Scala standard is to leave off the parens unless the method changes the object itself (rather than just returning something), so it's def toList without any parens afterwards. And thus you can only call it as object.toList.

Solution 2 - Scala

Your second line is actually interpreted as

val l = Array(1,2,3).toList.apply()

since foo(x) is "magic" syntax for foo.apply(x).

That's why the complier complains about "not enough arguments", as the apply method on lists takes one argument.

Thus you can write e.g.:

scala> val i = Array(1, 2, 3).toList(1)
i: Int = 2

Solution 3 - Scala

Let me answer from Scala coding style perspective.

Scala style guide says...

Omit empty parenthesis, only be used when the method in question has no side-effects (purely-functional). In other words, it would be acceptable to omit parentheses when calling queue.size, but not when calling println().

Religiously observing this convention will dramatically improve code readability and will make it much easier to understand at a glance the most basic operation of any given method. Resist the urge to omit parentheses simply to save two characters!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTraderJoeChicagoView Question on Stackoverflow
Solution 1 - ScalaRex KerrView Answer on Stackoverflow
Solution 2 - ScalaKnut Arne VedaaView Answer on Stackoverflow
Solution 3 - ScalaVishal JohnView Answer on Stackoverflow