Function Concept
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
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:
/* 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)
A function can have several parameters that are separated by comma.
/* a function with 2 parameters */
val add = (x: Int, y: Int) => x + y
println(add(1, 2)) // 3
println(add(7, 3)) // 10
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
println(add(1)) // Expected: 2
println(add(7, 3)) // Expected: 10
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
//call method add two times
println(add(1, 2)) // 3
println(add(2, 2)) // 4
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"
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
println(addThenMultiply(1, 2)(3)) // 9
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 + "!")
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
Let's review some of the key features of functional programming paradigm.
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:
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 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.
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 r1 = compute(add, 3, 3) // use add() function
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
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.
Read next: Classes