Scala can have an arbitrary number of parameter blocks, not just one. So:
def f(i: Int) = i + 2
def g(i: Int)(j: Int) = i + j
def h(i: Int)(j: Int)(b: Boolean) = if (b) i + j else i * j
all works. Parameter blocks are a way to organize parameters and signal to the compiler how to handle the translation from a method (which def
s are) into a function (which is a method that you can pass as an argument).
Now, if you have empty parameter blocks you can just omit them for brevity:
def a()()() = println("Hi") // Do nothing!
a()()() // Full call
a() // Drop some
a // Drop all of them
All of the calls to a
do the same thing. But you can't add more empty parameter blocks than belong--those are interpreted as calls to whatever is returned by the method.
a()()()() // No go, calls `()` on `Unit` which doesn't exist
So this covers cases 1 and 3 of yours.
Now, you can also have a method return a function. A function maps arguments (just one block!) to an output, but unlike methods, you can pass it around. (Scala is good at automatically wrapping methods into functions when such is needed.)
So
def b = () => println("Hi")
says that each time you call b
, you should create a function that takes no parameters and returns whatever println("Hi")
returns. In fact, it returns Unit
, i.e. no return value--it actually is a value, but it's always the same entity: ()
. This avoids having to have special cases for procedures/methods returning void
and methods with a return value; everything has a return value (at least conceptually). Anyway, if you have one:
val c = b
then you can call it:
c() // Will print "Hi"
or you can just create and call all in one go
b() // The `b` part creates the function, `()` calls it.
A tour through e.g. Programming in Scala will cover all the basics you'll need in this regard. (I liked having a paper copy, even if one does have to pay for it.)