In this presentation, You will get to know about Function Literal,Higher Order Function,Partial Function,Partial Applied Function,Nested Function,Closures.
1. Functions In ScalaFunctions In Scala
Satendra Kumar
Software Consultant
Knoldus Software LLP
Satendra Kumar
Software Consultant
Knoldus Software LLP
2. Topics CoveredTopics Covered
Function
Function Literal
Higher Order Function
Partial Function
Partial Applied Function
Nested Function
Closures
Function
Function Literal
Higher Order Function
Partial Function
Partial Applied Function
Nested Function
Closures
3. FunctionFunction
A function is a type of procedure or routine. Which takes the input and return
a value.
function define like:
def square(x: Int): Int = { x * x }
* Function always return a single value.
4. Function LiteralFunction Literal
Function literal a function with no name in Scala source code, specified with function literal
syntax.
For example:
(x: Int, y: Int) => x + y
Anonymous function Another name for function literal.
5. Function LiteralFunction Literal
Function literal a function with no name in Scala source code, specified with function literal
syntax.
For example:
(x: Int, y: Int) => x + y
Anonymous function Another name for function literal.
A function literal is compiled into a class that when instantiated at runtime is a function value.
Thus the distinction between function literals and values is that function literals exist in the
source code, whereas function values exist as objects at runtime. The distinction is much like
that between classes (source code) and objects (runtime).
7. Higher Order Function
def filter(p: (A) Boolean): List[A]⇒
def map[B](f: (A) ⇒ B): List[B]
def foreach(f: (A) Unit): Unit⇒
Higher-order functions are functions that can either take other functions as arguments
or return them as results.
Higher order functions:
def collect[B](pf: PartialFunction[A, B]): List[B]
def calFun(operator: String): (Int, Int) => Int
9. Higher Order Function
(1 to 100).toList.filter { (number:Int) => number % 2 == 0 }
Or
(1 to 100).toList.filter { number => number % 2 == 0 }
10. Higher Order Function
(1 to 100).toList.filter { (number:Int) => number % 2 == 0 }
Or
(1 to 100).toList.filter { number => number % 2 == 0 }
Or
(1 to 100).toList.filter { _ % 2 == 0 }
11. Higher Order Function
def calFun(operator: String): (Int, Int) => Int = {
(a: Int, b: Int) =>
operator match {
case "+" => a + b
case "-" => a - b
case "*" => a * b
case "/" => a / b
}
}
12. Partial Function
A partial function is a function that is not defined for all possible arguments of the specified
type.
In Scala :
A partial function of type PartialFunction[A, B] is a unary function where the domain does not
necessarily include all values of type A.
The function isDefinedAt allows to test dynamically if a value is in the domain of the function.
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x + " is even"
}
13. Partial Function And Function
Partial Function:
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x + " is even"
}
Function:
def isEven(x: Int): String = {
require(x % 2 == 0)
x + " is even"
}
Both are doing same thing so what is difference between Function
and Partial Function ?
14. Diff B/W Partial Function And Function
The main distinction between PartialFunction and Function is that the user of a
PartialFunction may choose to do something different with input that is declared to be
outside its domain.
For example:
val sample = 1 to 10
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x + " is even"
}
// the method collect can use isDefinedAt to select which members to
collect
val evenNumbers = sample collect isEven
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x + " is odd"
}
// the method orElse allows chaining another partial function to handle
// input outside the declared domain
val numbers = sample map (isEven orElse isOdd)
15. match
def checkNumber(a: Int):String = a match {
case x if x % 2 == 0 => x + " is even"
case x if x % 2 == 1 => x + " is odd"
case _ => "Neither even nor odd"
}
match is method or keyword ?
16. match
def checkNumber(a: Int):String = a match {
case x if x % 2 == 0 => x + " is even"
case x if x % 2 == 1 => x + " is odd"
case _ => "Neither even nor odd"
}
match is method or keyword ?
Answer => Keyword
17. match
def checkNumber(a: Int):String = a match {
case x if x % 2 == 0 => x + " is even"
case x if x % 2 == 1 => x + " is odd"
case _ => "Neither even nor odd"
}
match is method or keyword ?
Answer => Keyword
Why keyword ?
18. Why match is keyword ?
From: David Pollak <dpp <at> athena.com>
Subject: match question
Newsgroups: gmane.comp.lang.scala.debate
Date: 2008-01-21 20:30:29 GMT (6 years, 49 weeks, 5 days, 3 hours and 8 minutes ago)
Folks,
Why is 'match' a language level construct rather than a method on Any?
Wouldn't "def match[XX](func: PartialFunction[this.type, XX]): XX = ..."
result in syntactically identical code?
Thanks,
David
19. Why match is keyword ?
From: martin odersky <martin.odersky <at> epfl.ch>
Subject: Re: match question
Newsgroups: gmane.comp.lang.scala.debate
Date: 2008-01-21 21:25:02 GMT (6 years, 49 weeks, 5 days, 2 hours and 27 minutes ago)
On Jan 21, 2008 9:35 PM, Erik Engbrecht <erik.engbrecht <at> gmail.com> wrote:
> I always wondered that...
>
> Good question.
>
> On 1/21/08, David Pollak <dpp <at> athena.com> wrote:
> > Folks,
> >
> > Why is 'match' a language level construct rather than a method on Any?
> >
> > Wouldn't "def match[XX](func: PartialFunction[ this.type, XX]): XX = ..."
> > result in syntactically identical code?
> >
It used to be that way in Scala 1. I am no longer sure why we changed.
syntax highlighting? error reporting? not sure. I don't think it
matters much either way, though.
Cheers -- Martin
20. Partial Applied Function
When you invoke a function, If you send only a few arguments, then you get back a partially
applied function. This gives you the convenience of binding some arguments and leaving the
rest to be filled in later.
Example: uncurried version
scala> def sum(a:Int,b:Int,c:Int,d:Int):Int=a+b+c+d
sum: (a: Int, b: Int, c: Int, d: Int)Int
scala> val partialAppliedFun=sum(1,2,_:Int,_:Int)
partialAppliedFun: (Int, Int) => Int = <function2>
scala> partialAppliedFun(3,4)
res46: Int = 10
Example: curried version
scala> def sum(a:Int,b:Int)(c:Int)(d:Int):Int=a+b+c+d
sum: (a: Int, b: Int)(c: Int)(d: Int)Int
scala> val partialAppliedFun=sum(1,2) _
partialAppliedFun: Int => (Int => Int) = <function1>
scala> partialAppliedFun(3)(4)
res47: Int = 10
21. Uncurried Function Vs Curried Function
By Martin Odersky
Currying is mostly used if the second parameter section is a function or a by name parameter.
This has two advantages.
First, the function argument can then look like a code block enclosed in braces.
E.g.
using(new File(name)) { f =>
...
}
This reads better than the uncurried alternative:
using(new File(name), f => {
...
})
22. Uncurried Function Vs Curried Function
Second, and more importantly, type inference can usually figure out the function's parameter
type, so it does not have to be given at the call site.
For instance, if I define a max function over lists like this:
def max[T](xs: List[T])(compare: (T, T) => Boolean)
I can call it like this:
max(List(1, -3, 43, 0)) ((x, y) => x < y)
or even shorter:
max(List(1, -3, 43, 0)) (_ < _)
If I defined max as an uncurried function, this would not work, I'd have to
call it like this:
max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y)
If the last parameter is not a function or by-name parameter, I would
not advise currying. Scala's _ notatation is amost as lightweight,
more flexible, and IMO clearer.
23. Nested Function
A nested function is a function defined inside another function.
Purpose:
Nested functions are used as helper functions or as recursive functions inside another
function. This has the structural benefit of organizing the code, avoids polluting the scope,
and also allows functions to share state easily.
As nested function can access local variables of the enclosing function, sharing of state is
possible without passing parameters to the nested function or use a global variable,
simplifying code.
Also called Local function.
25. Nested Function
def processFile(filename: String, width: Int) {
def processLine(filename: String, width: Int, line: String) {
if (line.length > width)
println(filename + ": " + line)
}
val source = Source.fromFile(filename)
for (line <- source.getLines()) {
processLine(filename, width, line)
}
}
possible improvement ?
26. Nested Function
def processFile(filename: String, width: Int) {
def processLine(line: String) {
if (line.length > width)
println(filename + ": " + line)
}
val source = Source.fromFile(filename)
for (line <- source.getLines())
processLine(line)
}
27. Closures
scala> var more = 1
more: Int = 1
scala> val addMore = (x: Int) => x + more
addMore: Int => Int = <function1>
scala> addMore(10)
res6: Int = 11
The function value (the object) that’s created at runtime from this function literal is called a
closure.
The name arises from the act of “closing” the function literal by “capturing” the bindings of its free
variables.
A function literal with no free variables, such as (x: Int) => x + 1 , is called a closed term,
where a term is a bit of source code.Thus a function value created at run-time from this function
literal is not a closure in the strictest sense, because (x: Int) => x + 1 is already closed as written.
Closures mean that you can save some data inside a function that's only accessible to a
specific returning function, i.e the returning function keeps its execution environment.
28. Closures
scala> var more = 1
more: Int = 1
scala> val addMore = (x: Int) => x + more
addMore: Int => Int = <function1>
scala> addMore(10)
res6: Int = 11
scala> more=10
more: Int = 10
scala> addMore(10)
What is output ?
29. Closures
scala> var more = 1
more: Int = 1
scala> val addMore = (x: Int) => x + more
addMore: Int => Int = <function1>
scala> addMore(10)
res6: Int = 11
scala> more=10
more: Int = 10
scala> addMore(10)
res7: Int = 20
30. Closures
scala> def makeIncreaser(more: Int) = (x: Int) => x + more
makeIncreaser: (more: Int)Int => Int
scala> val inc1 = makeIncreaser(1)
inc1: Int => Int = <function1>
scala> val inc9999 = makeIncreaser(9999)
inc9999: Int => Int = <function1>
scala> inc1(10) output ?
scala> inc9999(10) output ?
31. Closures
scala> def makeIncreaser(more: Int) = (x: Int) => x + more
makeIncreaser: (more: Int)Int => Int
scala> val inc1 = makeIncreaser(1)
inc1: Int => Int = <function1>
scala> val inc9999 = makeIncreaser(9999)
inc9999: Int => Int = <function1>
scala> inc1(10)
res8: Int = 11
scala> inc9999(10)
res9: Int = 10009
Reason : the variable instance used is the one that was active at the time the closure was
created.