Scala tutorials
Scala functions, closure, Pure Functions, Impure Functions and partial function
In this article we will see Scala functions, closure, Pure Functions, Impure Functions and partial function
Scala Functions(Methods)
Scala functions or methods are similar to Java but heavily used as Scala is a functional programming language. We use the def keyword while writing definition of function.
Syntax:
<access type> def <functionName>: <Retrun Type> = {
//definition of function
}
Another Syntax for Single Line Function:
def <functionName>: <Retrun Type> = <one line code>
Example of function:
object Loops { def myFirstFunction(): String = { println("My first function") "My first function" } private def myOneLineFunction() = println("I am one line function") def main(args: Array[String]): Unit = { //A function called main myFirstFunction() myOneLineFunction() } }
Output
My first function
I am one line function
Scala Closure
Closure is a way to write functions in Scala which can be saved in a variable also, it may take some variables outside the function and return some results, so in Scala a variable can hold a function, a function can take function as variable and even return function.
Example of Closure:
object FunctionsInScala { val b = 2 val c = 3 def myClosureDoubleIt(a: Int) = a*b val myClosureTripleIt= (a: Int) => a*c def main(args: Array[String]): Unit = { println("Using myClosureDoubleIt"+myClosureDoubleIt(10)) println("Using myClosureTripleIt"+myClosureTripleIt(10)) } }
Output
Using myClosureDoubleIt20
Using myClosureTripleIt30
Scala Pure Function
In Scala if a function is pure it won’t mutate or change values and will always give same output for same input.
Here are details:
- A function f is pure if, given the same output for the same input each time.
- Functions output is dependent on input and logic.
- It calculates output and does not change anything else.
- It doesn’t update input values
- It doesn’t mutate.
- It doesn’t have any “back doors” and does not read from the console etc.
Examples of Pure function:
These String methods are also pure functions:
isEmpty
length
substring
Custom Pure Method Example:
object PureMethodsExample {
def sum(a: Int, b: Int) = a+b
}
Scala Impure Functions
A function which does not give the same output for the same input, which mutates the state of input and interacts with things outside for example interaction to console etc. is called impure method.
Features of impure methods
- It can mutate states of input
- It may give different output for the same input.
- It interacts with consoles and other things outside the method.
Example of Impure Functions
println()
print()
Custom Example of Impure Functions
myImpureSum() function is changing the value of some Value outside its scope and doing println() which interacts with the console.
object FunctionsInScala {
var someValue = 10
def myImpureSum(a: Int, b: Int) = {
someValue = 20
println("Doing some sum work")
a+b+someValue
}
}
Partial function
A partial function is such a function which returns output for some input values but does not return output for every input or simply not defined for some other values. Usually a function gives output for every input but in partial functions it sometimes is not defined for certain inputs and we can check it as well.
Implementing Partial Function with appy and isDefinedAt Methods
To create a partial function we have to implement apply() and isDefinedAt() methods where apply method is used to do operation and isDefinedAt() tells if this method works for input or not.
object PartialFunctions { val doubleThePositiveNumber = new PartialFunction[Int, Int] { def apply(data: Int) = data*2 def isDefinedAt(data: Int) = data >0 } def main(args: Array[String]): Unit = { println(doubleThePositiveNumber(10)) } }
Output
20
Implementing Partial Function with Case
We can use case class as well to create partial functions, check below example function divideUsingMyInt has a case which is defined for certain inputs only.
object PartialFunctions { val divideUsingMyInt: PartialFunction[Int, Int] = { case data: Int if data != 0 => 100 / data } def main(args: Array[String]): Unit = { println(divideUsingMyInt(10)) } }
Output
10
Function Chaining, orElse and andThen in Partial Function
orElse – By using orElse we can combine and create a new partial function using two existing partial functions where one function servers some inputs and another servers another set of inputs.
andThen – By using it we can chain the inputs from one to another partial functions.
Example:
doublePostiveAndNegative partial function is created using two other partial functions and features of both are combined in this.
object PartialFunctions { val doubleThePositiveNumber = new PartialFunction[Int, Int] { def apply(data: Int) = data*2 def isDefinedAt(data: Int) = data >0 } val doubleTheNegativeNumber = new PartialFunction[Int, Int] { def apply(data: Int) = data*2 def isDefinedAt(data: Int) = data < 0 } val doublePostiveAndNegative = { doubleThePositiveNumber orElse doubleTheNegativeNumber } val tripleData = new PartialFunction[Int, Int] { def apply(data: Int) = data*3 def isDefinedAt(data: Int) = data < 0 } def main(args: Array[String]): Unit = { val orElseUsed = doublePostiveAndNegative(-10) val andThenUsed = (doublePostiveAndNegative andThen tripleData)(-1) } }
Reference
Next Article
- Higher order functions(HOD), Currying and Pattern Matching