index<--

Scala Functions

Idea of a function come from mathematics. It represents a formula that can be used to calculate output based on input. Most programming languages have functions. In Scala functions are expressions that can have parameters and can take arguments.

Function Concept

Anonymous Function

The most simple function is a linear function that takes one parameter and return its value back as it is. f(x) = x. If the function also has no name, this is the most simple function:

``````//syntax pattern
(x: Int) => x
``````

Hold on I can find one function that takes no parameters and return a constant. But of course this kind of function is not very useful is it? In next example there is an anonymous function that require no arguments and return 42 every time is called.

``````//constant function
() => 42
``````

Named Function

In Scalla we can assign a function to a handler (identifier). The handler will represent the function and can be called using arguments enclosed in paranthesis after the handler. The handler is just an identifier for a value that is initialized with an expression like this:

One Parameter

``````/* named function example */
val addOne = (x: Int) => x + 1
val y = addOne(1) // y == 2 (function is executed)

/* demonstrate how a function is a reference */
val func = addOne // create a second handler
val z = func(1)   // z == 2 (function is executed again)
``````

Multiple Parameters

A function can have several parameters that are separated by comma.

``````/* a function with 2 parameters */
val add = (x: Int, y: Int) => x + y
``````
Alert: You do not need to specify if the parameters are: "var" or "val" becouse in Scala, function parameters are immutable. That means implicit "val" parameters. If you ever try to mutate a parameter you will end-up with an error.

Default Values

A function can have parameters with default values that are also optional.

``````/* a function with 2 parameters */
val add = (x: Int, y: Int = 1) => x + y
``````

Scala Methods

Idea of a method come from OOP languages. It represents a sub-program or sub-routine that can be used to calculate output based on input just like functions. Scala is a hybrid language. It has both functions and methods. Methods always have names and are usually defined inside a class while functions can be anonymous and can be declared outside of any class.

Example 1:

In next example we define a simple method with two parameters. Observe we use keyword "def" that is also used in Python. This method will return an Integer result type, that is declared using ":" after parameter list.

``````//method with two parameters
def add(x: Int, y: Int): Int = x + y

``````

Example 2:

In next example we define a method that uses a block of code. Observe there is no "return" keyword used here. Scala has a "return" statement but is rarely used. The output of the method is equal to value of the last expression executed in the block.

``````//method with two parameters
def square(input: Double): String = {
val square = input * input
square.toString // this will generate the result
}
println(getSquareString(2.5)) // "6.25"
``````

Example 3:

In next example we define a method that uses two parameter lists. This I have never enchounter before in any other language. It is a feature that I have to investigate further.

``````//method with two parameter lists
def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
``````

Example 4:

In next example we define a method with no parameters. We don't use empty parameter list () at all. This is almost like a procedure that we know from other languages.

``````//method without parameters
def name: String = System.getProperty("user.name")
println("Hello, " + name + "!")
``````

Example 5:

A Scala method can have several results groupped in one as a tuple. You can unpack the results using also a tuple of identifiers. Each identifier capture one of the results, in corespondent order.

``````/* a methods with 2 results */
def mudiv(x: Int):(Int, Double) = { return (x * 2, x / 2.0) }

//unpack multiple results in two variables
val (m, d) = mudiv(3)

//check results
println(s"m=\$m d=\$d") //m=6 d=1.5
``````

Functional Programming

Functional programming (FP) is a style of programming that emphasizes writing applications using only pure functions and immutable values. This idea comes from algebra and mathematics. Functional programming is available in Scala but not exclusive. You can combine OOP and FP in your programs.

Features:

Let's review some of the key features of functional programming paradigm.

• Pure functions
• High order functions
• No null values

Pure functions

In functional programming there is this fundamental concept of Pure Function. That take one input as a parameter perform a computation and return a result. When input is the same, output is going to be the same for every call. To achieve this a function has restrictions:

• Pure function do not mutate any hidden state;
• Pure function do not have input/output parameters;
• It does not have any Input/Output operation with the external world;

Example:

In next example we define a method with that is in fact a pure function. Observe, methods can also be pure.

``````//demo for a pure method
def multiply(x: Int, y: Int): Int = x * y
``````
In real world applications, pure functions and impute functions are used together. In general pure functions are core functions and library functions while impute functions are wrappers for pure functions.

High order functions

In functional programming, a function that takes another function as an input parameter or return a function as its result is known as a Higher-Order Function (HOF).

In Scala like in any other functional programming language, functions are assigned to variables. That means you can set-up a method or a function that takes as argument other function. In fact, the function is code, stored in memory. It can not travel. What you pass arround is the reference to the function, so called function handler.

Example:

In this example, compute() will execute a call-back function called "func". This require two parameters and return one integer result. The compute() function also require two other integer arguments (a, b). Before we call compute() we define two value functions that are pure.

We define a main function that is impure. It will call the compute() function two times and print out the results. This demonstrate how to pass a function as an argument.

``````//HOF demo
object Main {
//define high order function: compute()
def compute(func: (Int, Int) => Int, a: Int, b: Int) :Int =  {
func(a, b) //call-back the parameter as a function
}

//define several values as functions
val mtp  = (x:Int, y:Int) => x * y
val add  = (x:Int, y:Int) => x + y
val div  = (x:Int, y:Int) => x / y

//define main function to execute demo
def main(args: Array[String]): Unit = {
val r2 = compute(mtp, 3, 3) // use mtp() function
println(r1) // expected: 6
println(r2) // expected: 9

val r3 = compute(div , 4, 3) // <- change this line for homework
println(r3) // expected error,  got: 1
}
}
``````

Homework: Open this example on-line, run it then change parameters in line 20 into: compute(div , 4, 0), then run it again to force division by zero. Just observe Scala friking out. We will learn later how to deal with errors. click here to open

No null Values

In theory, functional programming should be like writing a series of algebraic equations, and because you don’t use null values in algebra, you don’t use null values in functional programming. We think using Null in programming is one million dollar mistake

In mathematics we use zero = 0 and there is no concept of "null" other then this. Actually null comes from Latin word nulla that means none while zero comes from Arabic word sifr that means nothing or empty that is the same thing isn't it?

But the situation is not simple. Scala can call Java classes and it also must run with JVM so it has to deal with null values. It does in a very sofisticated manner you are not yet equipped to handle. We must postpone this topic until you learn about classes, errors and control flow statements.