May 14, 2021 Scala
1. Pattern matching is combined with functions
2. The combination of functions
Let's create two functions:
scala> def f(s: String) = "f(" + s + ")"
f: (String)java.lang.String
scala> def g(s: String) = "g(" + s + ")"
g: (String)java.lang.String
compose combines other functions to form a new function f (g(x))
scala> val fComposeG = f _ compose g _
fComposeG: (String) => java.lang.String = <function>
scala> fComposeG("yay")
res0: java.lang.String = f(g(yay))
AndThen is similar to compose, but the order of call is to call the first function first, and
g(f(x))
scala> val fAndThenG = f _ andThen g _
fAndThenG: (String) => java.lang.String = <function>
scala> fAndThenG("yay")
res1: java.lang.String = g(f(yay))
Case statement
So what exactly is a case statement?
This is a sub-class of a function called PartialFunction.
What is a collection of multiple case statements?
They are a combination of multiple PartialFunctions.
For a given input argument type, the function can accept any value of that type.
In other
(Int) => String
and String can receive any Int value and return a string.
For a given input argument type, the bias function can only accept certain values of that type.
A bias function
(Int) => String
and String may not accept all Int values as inputs.
IsDefinedAt is a method of PartialFunction that determines whether PartialFunction can accept a given parameter.
Note: The partial function PartialFunction is independent of some of the application functions we mentioned earlier.
Refer to Effective Scala's comments on http://twitter.github.com/effectivescala/#Functional s programming-Partial functions.
scala> val one: PartialFunction[Int, String] = { case 1 => "one" }
one: PartialFunction[Int,String] = <function1>
scala> one.isDefinedAt(1)
res0: Boolean = true
scala> one.isDefinedAt(2)
res1: Boolean = false
You can call a partial function.
scala> one(1)
res2: String = one
PartialFunctions can use orElse to form a new function, and the resulting PartialFunction reflects whether a given parameter is defined.
scala> val two: PartialFunction[Int, String] = { case 2 => "two" }
two: PartialFunction[Int,String] = <function1>
scala> val three: PartialFunction[Int, String] = { case 3 => "three" }
three: PartialFunction[Int,String] = <function1>
scala> val wildcard: PartialFunction[Int, String] = { case _ => "something else" }
wildcard: PartialFunction[Int,String] = <function1>
scala> val partial = one orElse two orElse three orElse wildcard
partial: PartialFunction[Int,String] = <function1>
scala> partial(5)
res24: String = something else
scala> partial(3)
res25: String = three
scala> partial(2)
res26: String = two
scala> partial(1)
res27: String = one
scala> partial(0)
res28: String = something else
We saw something new last week. We saw a case statement where functions should normally be used.
scala> case class PhoneExt(name: String, ext: Int)
defined class PhoneExt
scala> val extensions = List(PhoneExt("steve", 100), PhoneExt("robey", 200))
extensions: List[PhoneExt] = List(PhoneExt(steve,100), PhoneExt(robey,200))
scala> extensions.filter { case PhoneExt(name, extension) => extension < 200 }
res0: List[PhoneExt] = List(PhoneExt(steve,100))
Why does this code work?
Filter uses a function.
In this example is a predicate function
(PhoneExt) => Boolean
.
PartialFunction is a sub-type of Function, so filter can also use PartialFunction!