[Scala] - function in scala

*** Functions are the core building blocks of reusable logic like other language

I - Defining a Function

    def <function_name>(<param_1>: <type>[, ... ]): <type> = <expression>
Example :

scala> def sum(x : Int, y : Int): Int = x + y
sum: (x: Int, y: Int)Int
I defined a function sum two int number and return int number

scala> def sum(x : Int, y : Int) = x + y
sum: (x: Int, y: Int)Int
If you do not define type for function Scala will help you

II - Special things 

Procedures

def <function_name>(<param_1>: <type>[, ... ]) = <expression>
def <function_name>(<param_1>: <type>[, ... ]): Unit = <expression>
A procedure is a function that doesn’t have a return value or type of function is Unit

scala> def greet(name : String) = println("Hi "+name)
greet: (name: String)Unit


Input-less function

def <function_name>(): <type> = <expression>
def <function_name>: <type> = <expression>
Function have no input

scala> def sayHi = "Hi"
sayHi: String

scala> sayHi
res1: String = Hi

scala> def sayHiAgain() = "Hi"
sayHiAgain: ()String

scala> sayHiAgain
res2: String = Hi

scala> sayHiAgain()
res3: String = Hi

So what different between sayHi and sayHiAgain ?
scala> sayHi()
<console>:12: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
       sayHi()
            ^


Use Functions Parameters

In Scala you can call parameters by name
scala> def introduce(firstName: String, lastName: String ):String = "I'm "+firstName+" "+ lastName
introduce: (firstName: String, lastName: String)String

scala> introduce("Hoai","PT")
res12: String = I'm Hoai PT

scala> introduce(lastName = "PT",firstName = "Hoai")
res13: String = I'm Hoai PT

And set default for parameter : 

scala> def introduce(firstName: String, lastName: String = ""):String = "I'm "+firstName+" "+ lastName
introduce: (firstName: String, lastName: String)String

scala> introduce("Hoai")
res12: String = I'm Hoai 

scala> introduce(firstName = "Hoai")
res13: String = I'm Hoai 

Function Invocation with Expression Blocks

When invoking functions using a single parameter, you can choose to use an expression block surrounded with curly braces to send the parameter instead of surrounding the value with parentheses.
Here i have function to say how many Vietnamese money you have : 

scala> def vndCast (vnds : Double) : String = "you have "+vnds+" VND"
vndCast: (vnds: Double)String

But you just have 5 dollars ,how can we do now ?
Normal way :
scala> val rate : Double = 22000;
rate: Double = 22000.0

scala> val yourVND = 5*rate
yourVND: Double = 110000.0

scala> vndCast (yourVND)
res5: String = you have 110000.0 VND

The second way : 
scala> vndCast {val rate : Double = 22000 ; 5*rate }
res6: String = you have 110000.0 VND


Nested Functions

Scala allow you define function in function , rewrite vndCast :

scala> def vndCast(dollars : Int) : String = {
     |   def exchange(dollars : Int ) : Double = {
     |     val rate : Double = 22000
     |     dollars * rate
     |   }
     |   "you have " + exchange(dollars)
     | }
vndCast: (dollars: Int)String

scala> vndCast(5)
res7: String = you have 110000.0


Vararg Parameters

Scala also supports vararg parameters,to mark a function parameter as matching one or more input arguments, add an asterisk symbol (*) after the parameter’s type in the function definition.

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

sum: (items: Int*)Int

scala> sum()
res8: Int = 0

scala> sum(1)
res9: Int = 1

scala> sum(1,2,3)
res10: Int = 6


Parameter groups

Do you remember first function we have : sum(x : Int, y : Int): Int = x + y .Let rewrite it : 
scala> def sum(x : Int)(y : Int) = x + y
sum: (x: Int)(y: Int)Int

scala> sum(2)(3)
res11: Int = 5


Type Parameters

    Some time you need define a function with flexible type , how can we do ?

    If you do not set a type scala will set it
    scala> def functionNoType (a : String) = a
    functionNoType: (a: String)String

    If you set it is Any but Any is a type like String ,Int ,Long . . . etc.
    scala> def functionNoType (a : Any) = a
    functionNoType: (a: Any)Any

    scala> val myName : String = functionNoType("HoaiPT")
    <console>:11: error: type mismatch;
     found   : Any
     required: String

           val myName : String = functionNoType("HoaiPT")

    You can do by this way :
    scala> def functionNoType[A](a : A) = a
    functionNoType: [A](a: A)A

    scala> val myName : String = functionNoType[String]("HoaiPT")
    myName: String = HoaiPT

    scala> val myName : String = functionNoType("HoaiPT")

    myName: String = HoaiPT



    Comments