# Functions: Multiple Input Parameter Groups

Note: The following text is an abridged version of the lesson in my book, Learn Functional Programming The Fast Way!

Functions can have multiple input parameter groups, like this:

``def sum(a: Int)(b: Int): Int = a + b``

That function can be called like this:

``val x = sum(1)(2)``

Compare that to a “normal” function, which looks like this:

``def sum(a: Int, b: Int): Int = a + b``

At first I couldn’t understand why this was an important feature in Scala, but the reality is that it’s very important. When combined with Call By-Name parameters (CBNs), it’s one of the features that lets us write our own control structures, and create our own Domain-Specific Languages (DSLs).

To understand this, we need to look at CBNs.

## Call by-name parameters in Scala

Most input parameters are “Call By-Value” (CBV) parameters, meaning that when a variable has a value --- such as `x` having the value `42` --- when that variable is passed into a function, the function receives its value, `42`.

Conversely, “by-name” parameters are quite different than by-value parameters. Rob Norris makes the observation that you can think about the two types of parameters like this:

• A by-value parameter is like receiving a `val` field; its body is evaluated once, right before the parameter is bound to the function.
• A by-name parameter is like receiving a `def` method; its body is evaluated later, whenever it’s used inside the function.

## Example 1: Defining Call By-Name parameters in functions

``````def exec(blockOfCode: => Unit): Unit =
blockOfCode``````

In this example, `blockOfCode` is a CBN parameter. Notice that the difference between a “normal” CBV input parameter and a CBN parameter is the use of the `=>` transformation symbol in the parameter’s definition:

``````def f(param: Int) ...      // CBV parameter

def f(param: => Int) ...   // CBN parameter
--``````

Because `=>` always means transform in Scala, you get the idea that `param` is something that is transformed into an `Int` in this example.

Now, going back to `exec`:

``````def exec(blockOfCode: => Unit): Unit =
blockOfCode``````

You can read this input parameter as, “`blockOfCode` is some piece of code that returns `Unit` when it runs.” Or you can say, “`blockOfCode` is transformed into the `Unit` type after it runs.” Either of those statements is accurate.

This means that you can pass `exec` any code block that has the `Unit` return type, including a one-line block of code:

``````exec(println(1))
----------``````

or a multiline block of code enclosed in curly braces:

``````exec {
val i = 42
println(s"Secret of the universe = \$i")
}``````

Because `println` has the `Unit` return type, both of those work.

## Example 2: Executing Call By-Name parameters in your function

Another great feature of CBN parameters is that you can use them anywhere inside your function. You can even call them multiple times inside your function, if your algorithm calls for that.

To demonstrate the anywhere aspect, here’s another example, where I call `codeBlock` in the second line of the function. Also notice that I define `codeBlock` to yield an `Int` instead of `Unit`:

``````def exec(codeBlock: => Int): Unit =
val result = codeBlock
println(s"ran the code, result = \$result")``````

The REPL shows how `exec` works with a little block of code like `2 + 2`:

``````scala> exec(2 + 2)
ran the code, result = 4``````

Because `exec` takes any block of code that yields an `Int`, you can also pass functions into it, like these:

``````def sum(a: Int, b: Int) = a + b
exec(sum(2, 3))

def multiply(a: Int, b: Int) = a * b
exec(multiply(2, 3))``````

That last example looks like this in the REPL:

``````scala> exec(multiply(2, 3))
ran the code, result = 6``````

## Example 3: CBNs and multiple parameter groups

Before we get into the next example, a piece of knowledge you need to know is that Scala functions can be defined to have multiple input parameter groups. One of the simplest possible examples looks like this:

``def sum(a: Int)(b: Int): Int = a + b``

When a function is defined with two parameter groups like that, you just pass your parameters into it in two separate sets of parentheses when you call it:

``````scala> sum(1)(1)
val res0: Int = 2``````

This feature enables us to do some cool things, such as to write our own control structures and domain-specific languages (DSLs), especially when combined with CBNs.

To demonstrate this, imagine that you want to create your own control structure named `doubleIf` that can be used like this:

``````doubleIf(age > 18)(numAccidents == 0) {
println("Discount!")   // some block of code here
}``````

As shown, you pass it two test conditions in the first two parameter groups:

``````doubleIf(age > 18)(numAccidents == 0) ...
--------  -----------------``````

and if both of those are `true`, `doubleIf` executes your block of code, which is between the curly braces, as the third parameter group.

If `doubleIf` sounds difficult to write — fear not! — it’s relatively simple, as these things go. I just mentioned that `doubleIf` is a function that has three parameter groups, so you can start sketching it like this:

``def doubleIf()()()``

The first two parameter groups are test conditions, which means that they are both code blocks — CBN parameters — that yield a `Boolean` value:

``def doubleIf(test1: => Boolean)(test2: => Boolean)(???)``

Then the third parameter group is the block of code the caller wants to run if the two test conditions are `true`. In my case I’ll require that this returns `Unit`, to keep things simple:

``def doubleIf(test1: => Boolean)(test2: => Boolean)(codeBlock: => Unit)``

And finally, the body of the function says, “If both test conditions are `true`, run the block of code”:

``````// test1 and test2 are shortened to t1 and t2 to fit the book’s page width
def doubleIf(t1: => Boolean)(t2: => Boolean)(codeBlock: => Unit): Unit =
if t1 && t2 then codeBlock``````

Now if you put this following code in the REPL, you’ll see that the `"Discount!"` text is printed:

``````val age = 20
val numAccidents = 0

doubleIf(age > 18)(numAccidents == 0) {
println("Discount!")
}``````

But if both of those conditions are not `true`, you’ll see that `"Discount!"` is not printed.

As I hope this example shows, CBNs combined with multiple parameter groups give you the power to create your own control structures, and eventually your own DSLs.

## Note: Better names for by-name parameters?

According to Wikipedia, these terms date back to a language named ALGOL 60 (yes, the year 1960). I don’t mean any disrespect to that language, but for me, the term “by-name” isn’t very helpful (though I’m sure it had a solid meaning back then).

These days I find that the following terms are more accurate and meaningful:

• Evaluate on access
• Evaluate on use
• Evaluate when accessed
• Evaluate when referenced

With any of those phrases you can replace “Evaluate” with words like “Execute” or “Run,” if you prefer.

## Key points

As a quick recap, these are some key points about CBNs:

• You define them with the `=>` symbol
• You must specify their return type
• They’re not executed until you call them in your function
• They can be called anywhere in your function
• They can be multiple times in your function
• Combined with multiple parameter groups, they let us write our own control structures and DSLs