In his latest post, Alex explains the concept of “partial” in Scala with great examples about partial functions and partially applied functions. An extremely interesting article for beginners and experienced Scala developers as well
Nearly everyone who learns Scala can get confused over the word partial used in the contexts:
- Partial functions
- Partially applied functions
Let’s look at both.
Partially applied functions
f(x1, x2) = yf(x1) = f(x2) = y
In Scala, when only some parameters are passed to a function to make another function it is said to be a partial application of that function.
|
1
|
def minus(a: Int, b: Int) = "answer=" + (a-b) |
minus50 is a partial application of minus.|
1
|
minus50(57); // outputs 7. |
Partial functions
A partial function is a function that is valid for only a subset of values of those types you might pass into it. For example, Consider the mathematical function where x is set of all number from 1 to 100:
A function is said to be partial if the function is only applied to a subset in set of element of x.
So if we only want to define the function
f(x) = x + 5
f(x')=x+5where x’ = {1,2,3,4,5,6,7}
In Scala, a PartialFunction inherits from Function and adds two interesting methods:
isDefinedAt- this allows us to check if a value is defined for the partial function.orElse- this allows partial functions to be chained. So if a value is not defined for a function it can be passed to another function. This is similar to the GoF Chain of Responsibility pattern.
Ok so open up a Scala REPL and create the following partial function which will add 5 to an integer as long as the integer is less than 7.
|
1
2
3
|
val add5Partial : PartialFunction[Int, Int] = { case d if (d > 0) && (d <= 7) => d + 5;} |
When you try this for a value less than or equal to 7, you will see the result no problem
|
1
2
|
scala > add5Partial(6);res1: 11 |
When you try it for a value greater than 7 you don’t get a nice clean answer.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
scala> myPartial(42);scala.MatchError: 42 (of class java.lang.Integer) at $anonfun$1.apply$mcII$sp(<console>:7) at .<init>(<console>:9) at .<clinit>(<console>) at .<init>(<console>:11) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704) at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920) at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43) at scala.tools.nsc.io.package$$anon$2.run(package.scala:25) at java.lang.Thread.run(Thread.java:722)</console></console></clinit></console></init></console></clinit></console></init></console> |
isDefinedAt() should now be becoming apparent. In this case, we could do:
Ok so what about orElse? Well let’s define another partial function which deals with numbers greater than 7 and less than 100. In such cases, lets’ just add 4.
Now we can just do:
Ok, let’s see how all this could be implemented in Java using Chain of Responsibility pattern. Firstly, let’s define a handler interface and an add5 and add4 implementation which will implement it.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
//Handlerpublic interface AdditionHandler { //reference to the next handler in the chain public void setNext(AdditionHandler handler); //handle request public void handleRequest(int number);}public class Add5Handler implements AdditionHandler { private AdditionHandler nextAdditionHandler = null; public void setNext(AdditionHandler hander) { this.nextAdditionHandler = handler; } public int handleRequest(int number) { if ((number > 0) && (number <= 7)) { return number + 5; } else { return nextAdditionHandler.handleRequest(number); } }}public class Add4Handler implements AdditionHandler { private AdditionHandler nextAdditionHandler = null; public void setNext(AdditionHandler hander) { this.nextAdditionHandler = handler; } public int handleRequest(int number) { if ((number > 7) && (number <= 100)) { return number + 4; } else { return nextAdditionHandler.handleRequest(number); } } } |
Now, let’s create a class which will link the handlers.
And of a course a client which actually invokes the functionality:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class AdditionClient { private AdditionProcessor processor; public AdditionClient(){ createProcessor(); } private void createProcessor() { processor = new AdditionProcessor(); processor.addHandler(new Add5Handler()); processor.addHandler(new Add4Handler()); } public void addRule(AdditionHandler handler) { processor.addHandler(handler); } public void requestReceived(int value){ System.out.println("value=" + processor.handleRequest(value)); } public static void main(String[] args) { AdditionClient client = new AdditionClient(); }} |
So Scala has some clear advantages here. Or course, people will say ‘ah but in Java you just just do…’
And yes for this specific case, this will work. But what if your functions/ commands become more complex. Are you go to hang around in if / else land? Probably not. ‘Til the next time, take care of yourselves.
Original article can be found here : http://dublintech.blogspot.gr/2013/01/scala-do-you-partially-understand-this.html

