Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala - method call syntax

Tags:

methods

scala

I am a beginning practitioner in Scala and I saw a few different syntax for calling a method. Some are nice, as ignoring parenthesis for a parameterless method, or ignoring the dot as in

1 to 10

but some really puzzle me. for instance:

breakable { ... }

this is simply a method call right? Can I also do that for more than one parameter or a parameter which is not a parameterless function?

Thanks

like image 666
Bober02 Avatar asked Aug 10 '12 09:08

Bober02


2 Answers

There are two standard ways of calling methods:

obj.method(params)   // dot notation
obj method (params)  // operator notation

The above can be modified in the following ways:

  1. If params is a single parameter, you can replace () with {}.
  2. If params is a single parameter and you are using operator notation, you can drop the parenthesis.
  3. If method doesn't take parameters, you can drop (params) (that is, drop the empty ()).
  4. If method ends with :, then it actually binds to the right in operator notation. That is, (params) method_: obj is equivalent to obj.method_:(params).
  5. Either way, spaces are optional as long as identifiers can be told apart. So one can add spaces to the dot notation, like obj . method ( params ) or write .method(params) on the next line -- as often happens with call chaining --, as well as remove spaces from the operator notation, as in a+b.

There's also some stuff with tuple inference, but I try to avoid it, so I'm not sure of the exact rules.

None of these will explain the example you are confused about, however. Before I explain it, however, I'd like to show some syntactic sugars that can also be used to call methods:

obj(params) // equivalent to obj.apply(params)
obj.x = y   // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y  // equivalent to obj.update(x, y)
obj op= y   // equivalent to obj = obj op y, if op is symbolic
~obj        // equivalent to obj.unary_~; also for !, + and -, but no other symbol

Ok, now to the example you gave. One can import members of stable values. Java can do it for static methods with its static import, but Scala has a more general mechanism: importing from packages, objects or common instances is no different: it brings both type members and value members. Methods fall in the latter category.

So, imagine you have val a = 2, and you do import a._. That will bring into scope all of Int methods, so you can call them directly. You can't do +(2), because that would be interpreted as a call to unary_+, but you could call *(4), for example:

scala> val a = 2
a: Int = 2

scala> import a._
import a._

scala> *(4)
res16: Int = 8

Now, here's the rule. You can call

method(params)

If:

  1. method was imported into scope.
  2. You keep the parenthesis (even if there's only one parameter)

Note that there's a precedence issue as well. If you write obj method(params), Scala will presume method belongs to obj, even if it was imported into scope.

like image 152
Daniel C. Sobral Avatar answered Oct 19 '22 05:10

Daniel C. Sobral


If we desugar this we will have:

breakable({ ... }) 

this matches signature

breakable: (op: ⇒ Unit): Unit 

and uses so named call-by-name arguments (you may think of this as pass a block of code as argument)

More over scala allows you to write this:

scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit

scala> foo { println(1) } { println(2) }
1
2

Above is the example of curried function

like image 39
om-nom-nom Avatar answered Oct 19 '22 04:10

om-nom-nom