New to programming in Scala?
Find out exactly how powerful it is in this article by Knoldus Blogs. Discover what functions are including Total Functions and PartialFunctions, have fun coding!
'If you’re new to programming in Scala(like I am), you must have heard someone or the other talking about how awesome and powerful the case keyword, Partialfunction and pattern matching in Scala are. It got me wondering about why people love them that much. So, to unravel this mystery around case, I went on an adventure to find out all there is to know about them(And boy! was it amazing?!) and I’d like to share my findings with you. So, Without further adieu, I bring to you the following:
- What are Functions?
- Total Functions and PartialFunctions
- The PartialFunction trait.
What are Functions?
Most simplistically, a function is a mapping or a transformation of an input to an output. if it helps, you can think of it as being a room with two doors; one to just enter the room(that’s where the inputs come in from) and the other for exit(where the output comes out).
Scala differentiates between methods(associated with some object) and functions(associated with some type). But that’s a story for another day. The most simple way of defining a function in Scala is by the way of function literals. For example:
If you try to disassemble the class file, you’d see that the the JVM creates a method in the Solution class `someFunctionLiteral` with the Scala.Function1 as its return type. Pretty amazing, right?
Total Functions vs PartialFunctions
Total Function is a just synonym for a function(written f: X->Y). The adjective total is written just to distinguish them from partial functions. A function is just another mathematical object that produces an output when given an input – it could be a number, a vector, or anything that can exist inside a set of things. whereas, A partial function generalises the concept of a function f: X -> Y, by not forcing f to map every element of X to an element of Y.
The PartialFunction trait
Let’s try to break this down bit by bit, shall we?
The PartialFunction trait in Scala is a pretty nifty feature, if you ask me. It lets you create functions where the domain X doesn’t necessarily map to every element of Y and not just that, it lets you dynamically test if a value is in the domain of the function.
The trait extends (A) => B, which is just another way of saying that it extends scala.Function1[A,B]. Also, PartialFunction is a trait + companion object combo. The companion object contains all the methods that we use to apply or chain PFs together. There are two primary ways to use PartialFunction in the code:
- Using the new keyword.
- Using case keywords.
Taking the longer, more verbose, route with the new keyword
- scala.Function1’s apply method.
- scala.PartialFunction’s isDefinedAt method.
Like in the example below,
deepThoughtProcessor is a PartialFunction that is defined only at number 21, to be able to calculate the answer to the ultimate question of life(42). One of the powerful things about PartialFunction is that it provides us with the ability to query the function, to see if it is defined at that particular argument or not, before actually invoking the function using the isDefinedAt method(Pretty cool! isn’t it?!).
Staying true to the roots with the case keyword
Here’s where this approach of creating PartialFunctions outshines the previous one. In the example before this one, if you try to pass an argument on which deepThoughtProcessor is not defined at(44), it would give in and return the result(88). But it’s not the same with the case approach, it would simply give you a MatchError(You don’t mess with Deep Thought).
That’s it for this blog then(getting a bit crowded in here, ain’t it?). In my next blog, I’d talk more on how PartialFunction defined using case keywords can lie and how you could take advantage of chaining PartialFunction together.!
Until next time!'
This article was written by and orginally posted on Knoldus Blog.