Monday 21 September 2020

Scala: functions

Functions are first class citizens in Scala. ‘sum’ function takes two integer arguments and return the sum of two variables.

scala> def sum(a: Int, b : Int) = a + b
def sum(a: Int, b: Int): Int

scala> sum(10, 20)
val res2: Int = 30

you can store a function in a variable.

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


Let’s store the function ‘sum’ into a variable ‘add’.

 

def add = sum(_, _)

scala> def sum(a: Int, b : Int) = a + b
def sum(a: Int, b: Int): Int

scala> def add = sum(_, _)
def add: (Int, Int) => Int

scala> sum (10, 20)
val res4: Int = 30

scala> add(10, 20)
val res5: Int = 30


You can even use below shorthand notation to store a function into a variable.

 

def add = sum _

scala> def add = sum _
def add: (Int, Int) => Int

scala> add(10, 20)
val res6: Int = 30


Higher Order function

You can pass function as an argument to other function or method.

 

def square(x : Int) = x * x

 

I can pass square function as an argument to map function, which apply ‘square’ function to every elements of the collection.

 

Array(2, 3, 5, 7).map(square)

scala> def square(x : Int) = x * x
def square(x: Int): Int

scala> Array(2, 3, 5, 7).map(square)
val res0: Array[Int] = Array(4, 9, 25, 49)


If you do not want to define new function square, you can pass a lambda expression to map function.

scala> Array(2, 3, 5, 7).map(ele => ele * 2)
val res1: Array[Int] = Array(4, 6, 10, 14)


You can use filter function to filter the elements from a collection.

 

For example, filter all the elements that are divisible by 5.

1.to(100).filter(_ % 5 ==0)

scala> 1.to(100).filter(_ % 5 ==0)
val res17: IndexedSeq[Int] = Vector(5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100)


Define Custom Higher order function

Let’s define a higher order function apply that takes an array of integers and a function as input and apply this function to every element of the array.

 

Example

def apply(elements: Array[Int], fun: (Int) => Int) : Array[Int] =  for (ele <- elements) yield fun(ele)

 

As you see the definition of apply function, second argument is a function that takes one integer as argument and return an integer.

 

Let’s double each element in the array.

scala> def apply(elements: Array[Int], fun: (Int) => Int) : Array[Int] =  for (ele <- elements) yield fun(ele)
def apply(elements: Array[Int], fun: Int => Int): Array[Int]

scala> def square(x : Int) = x * x
def square(x: Int): Int

scala> apply(Array(2, 3, 5, 7), square)
val res3: Array[Int] = Array(4, 9, 25, 49)

 

Let’s triple each element in the array.

scala> def cubes(x: Int) = x * x * x
def cubes(x: Int): Int

scala> apply(Array(2, 3, 5, 7), cubes)
val res4: Array[Int] = Array(8, 27, 125, 343)

 

Function can produce other functions

A function can produce other functions.

 

Example

def incBy(factor: Int) = (number: Int) => factor + number

 

I can define incBy1 and incBy5 functions using incBy function.

 

val incBy1 = incBy(1)

val incBy5 = incBy(5)

 

You can call incBy1 and incBy5 functions like below.

 

incBy1(10)

incBy5(10)

scala> def incBy(factor: Int) = (number: Int) => factor + number
def incBy(factor: Int): Int => Int

scala> val incBy1 = incBy(1)
val incBy1: Int => Int = $Lambda$1045/37858242@7e5e7753

scala> incBy1(10)
val res5: Int = 11

scala> incBy1(21)
val res6: Int = 22

scala> 

scala> val incBy5 = incBy(5)
val incBy5: Int => Int = $Lambda$1045/37858242@3284f91f

scala> incBy5(10)
val res7: Int = 15

scala> incBy5(21)
val res8: Int = 26



 

Previous                                                    Next                                                    Home

No comments:

Post a Comment