...

/

Method Invocation

Method Invocation

In this lesson, we will go over the method invocation techniques used in Scala.

Generally speaking, method invocation in Scala follows Java conventions. In other words, there should not be a space between the invocation target and the dot (.), nor a space between the dot and the method name, nor should there be any space between the method name and the argument-delimiters (parentheses). Each argument should be separated by a single space following the comma (,):

Press + to interact
foo(42, bar)
target.foo(42, bar)
target.foo()

As of version 2.8, Scala now has support for named parameters. Named parameters in a method invocation should be treated as regular parameters (spaced accordingly following the comma) with a space on either side of the equals sign.

Press + to interact
foo(x = 6, y = 7)

While this style does create visual ambiguity with named parameters and variable assignment, the alternative (no spacing around the equals sign) results in code which can be very difficult to read, particularly for non-trivial expressions for the actuals.

Arity-0

Scala allows the omission of parentheses on methods of arity-0 (no arguments):

Press + to interact
reply()
// is the same as
reply

However, this syntax should 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(). This convention mirrors the method declaration convention given above.

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!

Postfix Notation

Scala allows methods that take no arguments to be invoked using postfix notation

Press + to interact
// recommended
names.toList
// discourage
names toList

This style is unsafe, and should not be used. Since semicolons are optional, the compiler will attempt to treat it as an infix method if it can, potentially taking a term from the next line.

Press + to interact
names toList
val answer = 42 // will not compile!

This may result in unexpected compile errors at best and happily compiled faulty code at worst. Although the syntax is used by some DSLs, it should be considered deprecated and avoided.

Since Scala 2.10, using postfix operator notation will result in a compiler warning.

Arity-1(Infix Notation)

Scala has a special punctuation-free syntax for invoking methods of arity-1 (one argument). This should generally be avoided, but with the following exceptions for operators and higher-order functions. In these cases, it should only be used for purely-functional methods (methods with no side-effects).

Press + to interact
// recommended
names.mkString(",")
// also sometimes seen; controversial
names mkString ","
// wrong - has side-effects
javaList add item

Symbolic Methods/Operators

Symbolic methods (operators) should always be invoked using infix notation with spaces separating the target, the operator, and the parameter.

Press + to interact
// WRONG!
"daniel"+" "+"spiewak"
a+b
a.+(b)
Press + to interact
// right!
"daniel" + " " + "spiewak"
a + b

For the most part, this idiom follows Java and Haskell syntactic conventions. A gray area is short, operator-like methods like max, especially if commutative.

Press + to interact
// fairly common
a max b

Symbolic methods which take more than one parameter (they do exist!) may still be invoked using infix notation, delimited by spaces.

Press + to interact
foo ** (bar, baz)

Such methods are fairly rare, however, and should normally be avoided during API design. For example, the use of the /: and :\ methods should be avoided in preference to their better-known names, foldLeft and foldRight.

Higher-Order Functions

As noted, methods which take functions as parameters (such as map or foreach) should be invoked using infix notation. It is also possible to invoke such methods in the following way:

Press + to interact
// WRONG!
names.map { _.toUpperCase }

This style is not the accepted standard! The reason to avoid this style is for situations where more than one invocation must be chained together:

Press + to interact
// WRONG!
names.map { _.toUpperCase }.filter { _.length > 5 }
Press + to interact
// RIGHT!
names map { _.toUpperCase } filter { _.length > 5 }

Both of these work, but the former can easily lead to confusion. The sub-expression { _.toUpperCase }.filter when taken in isolation looks like we are invoking the filter method on a function value. However, we are actually invoking filter on the result of the map method, which takes the function value as a parameter.