functions in scala
TRANSCRIPT
Functions In ScalaFunctions In Scala
Satendra Kumar Software Consultant
Knoldus Software LLP
Satendra Kumar Software Consultant
Knoldus Software LLP
Topics CoveredTopics CoveredFunction
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
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.
Function Literal Function 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.
Function Literal Function 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).
Function Literal Function Literal
val fun2=(x: Int, y: Int) => x + y
val fun3 = (x: Int, y: Int, z: Int) => x + y + z
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
Higher Order Function
(1 to 100).filter { (number:Int) => number % 2 == 0 }
Higher Order Function
(1 to 100).toList.filter { (number:Int) => number % 2 == 0 }
Or
(1 to 100).toList.filter { number => number % 2 == 0 }
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 }
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 } }
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" }
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 ?
Diff B/W Partial Function And FunctionThe 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)
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 ?
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
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 ?
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
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 itmatters much either way, though.Cheers -- Martin
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+dsum: (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+dsum: (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
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 => { ...})
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.
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.
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) }
}
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 ?
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)
}
Closures
scala> var more = 1more: Int = 1
scala> val addMore = (x: Int) => x + moreaddMore: 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.
Closures
scala> var more = 1more: Int = 1
scala> val addMore = (x: Int) => x + moreaddMore: Int => Int = <function1>
scala> addMore(10)res6: Int = 11
scala> more=10more: Int = 10
scala> addMore(10) What is output ?
Closures
scala> var more = 1more: Int = 1
scala> val addMore = (x: Int) => x + moreaddMore: Int => Int = <function1>
scala> addMore(10)res6: Int = 11
scala> more=10more: Int = 10
scala> addMore(10)res7: Int = 20
Closures
scala> def makeIncreaser(more: Int) = (x: Int) => x + moremakeIncreaser: (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 ?
Closures
scala> def makeIncreaser(more: Int) = (x: Int) => x + moremakeIncreaser: (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.
Question And Option[Answer]Question And Option[Answer]
ThanksThanks