Functions in Scala

Variables are more useful when used in the context of functions in which a variable like x can be injected with different values by the user of a function. Let’s consider converting degrees Fahrenheit to Celsius. To convert 87, 92, and 100 from Fahrenheit to Celcius, we could do the following.

 
scala> (87 - 32) * 5 / 9.0
	res32: Double = 30.555555555555557

scala> (92 - 32) * 5 / 9.0
	res33: Double = 33.333333333333336

Obviously, there is a lot of repetition here. Functions allow us to specify the common parts of such calculations, while allowing variables to specify the parts that may be different. In the conversion case, the only thing that changes is the temperature reading in Fahrenheit. Here’s how we declare the appropriate function in Scala.

 
-------------------------------------------------------------------------
def <identifier>(<identifier>: <type>[, ... ]): <type> = <expression>
-------------------------------------------------------------------------

scala> def f2c (x : Double) =  (x - 32) * 5 / 9.0
	f2c: (x: Double)Double

Breaking this down, we have:
    (1) def is a Scala keyword indicating that a function is being defined
    (2) f2c (Fahrenheit to Celsius) is the name given to the function
    (3) (x: Double) is the parameter to the function, which is a variable named x of type Double
    (4) (x – 32) * 5/9.0 is the body of the function, which will take the value given by the user of the function	
	
scala> f2c(87)
	res34: Double = 30.555555555555557

scala> f2c(92)
	res36: Double = 33.333333333333336

=====================================================
Procedures
=====================================================
A procedure is a function that doesn’t have a return value. Any function that ends with a statement, such as a println() call, is also a procedure. If you have a simple function without an explicit return type that ends with a statement, the Scala compiler will infer the return type of the function to be Unit

 
scala> def myFunction = {
  println("Hai");
  println("Good Afternoon");
}
Output:- 
	myFunction: Unit

scala> myFunction
	Hai
	Good Afternoon

scala> def log(d: Double): Unit = println(f"Got Value : $d%.2f")
	log: (d: Double)Unit

scala> log(2.547)
	Got Value : 2.55

=====================================================
Functions With Empty Parentheses
=====================================================

scala> def hi = "Hi, Good Evening"
	hi: String

scala> hi
	res0: String = Hi, Good Evening
	
--------------------------------------------------------------------------------
def <identifier>: <type> = <expression>
--------------------------------------------------------------------------------
scala> def hi : String = "Hi, Very Good Evening"
	hi: String

scala> hi
	res1: String = Hi, Very Good Evening	

-------------------------------------------------------------------------
def <identifier>()[: <type>] = <expression>
-------------------------------------------------------------------------

scala> def message() : String = "Good Morning"
	message: ()String

scala> message()
	res0: String = Good Morning

scala> message
	res1: String = Good Morning

=====================================================
Recursive Functions
=====================================================

 
scala> def power(x : Int, y : Int) : Int = {
   if (y>=1){
     x * power(x, y-1);
   }   
   else{
     1
   }   
 }
	
scala> power(2,3)
	res2: Int = 8	

=====================================================
Calling Nested Functions
=====================================================

scala> def max(a:Int, b:Int, c:Int) = {
   def max(d:Int, e:Int) = if(d > e) d else e
   max (a, max(b,c))
 }
max: (a: Int, b: Int, c: Int)Int

scala> max (2,5,7)
	res3: Int = 7

=====================================================
Calling Functions With Named Parameters
=====================================================

-------------------------------------------------------------------------
<function name>(<parameter> = <value>)
-------------------------------------------------------------------------
scala> def greetings(prefix: String, name: String) = s"$prefix. $name"

scala> val myGreetings = greetings("Ms", "Brown")
myGreetings: String = Ms. Brown

=====================================================
Calling Functions Parameters With Default Values
=====================================================

 
scala> def greetings(prefix: String = "", name: String) = s"$prefix $name"
	greetings: (prefix: String, name: String)String

scala> val myGreetings = greetings(name="Tom");
	myGreetings: String = " Tom"

=====================================================
Calling Functions Using VarArg Parameters
=====================================================

 
scala> def sum(items: Int*): Int = {
  var sum = 0;
  for(i <- items) {
    sum = sum + i;
  }
  sum;
}

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

=====================================================
Calling Functions Using Parameter Groups
=====================================================

 
scala> def max(x: Int)(y: Int) = if (x > y) x else y
	max: (x: Int)(y: Int)Int

scala> max(10)(20)
	res5: Int = 20

=====================================================
Calling Higher-Order Functions
=====================================================

 
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String

scala> def reverser(value : String) = {
  value.reverse
  }
reverser: (value: String)String

scala> safeStringOperation(null, reverser)
	res5: String = null

scala> safeStringOperation("Apple",reverser)
	res6: String = elppA

=====================================================
Function Literals
=====================================================

scala> val getDouble = (x: Int) => x*2
	getDouble: Int => Int = <function1>

scala> getDouble(2)
	res0: Int = 4

=====================================================
Use Case-1 (Higher-Order Functions + Function Literals)
=====================================================

scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String
	
scala> safeStringOperation("Apple", (data:String)=>data.reverse)
	res2: String = elppA	

=====================================================
Use Case-2 (Higher-Order Functions + Function Literals)
=====================================================

		
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}
safeStringOperation: (value: String, func: String => String)String

scala> safeStringOperation("Apple", data=> data.reverse)
res3: String = elppA

Comments: No need to specify the data type. It is inferred from the first parameter

=====================================================
Placeholder Syntax
=====================================================

 
scala> def safeStringOperation(value: String, func: String => String) = {
  if (value==null){
   null
  }
  else{
   func(value)
  }
}

scala> safeStringOperation("Apple", _.reverse)
res4: String = elppA
Advertisements