(Relevant to your question before you edited it) Let's start with terminology. PartialFunction
is trait in scala that says that your function might not process all possible variations of the input:
val partialFunction: PartialFunction[Int, Int] = {
case 1 => 1
case 2 => 2
}
scala> partialFunction(1)
res43: Int = 1
scala> partialFunction(3)
scala.MatchError: 3 (of class java.lang.Integer)
It's completely unrelated to your example, which is a partial application - the article provided basically shows real-world example with email filtering.
About partial application.
Sometimes you might have a function with several parameters, let's say:
def sendMail(recipient: String, subject: String, body: String) = println(s"To: $recipient\n Subj: $subject\n Body: $body")
This function might be a part of the API, so you might not be able to change it. Now, let's say you need to send a same email to many different recipients:
object Spam{
val subject = "Hello!"
val body = "World!"
def spam(recipient: String) = sendMail(recipient, subject, body)
}
scala> Spam.spam("aaa@aa")
To: aaa@aa
Subj: Hello!
Body: World!
Another way to do that is to generate a function per subject/body, so to make it customizable:
def spammer(subject: String, body: String): String => Unit = (recipient: String) => {
sendMail(recipient, subject, body)
}
val spam1 = spammer("Hello", "World!")
spam1("emai@email.com")
It's roughly equivalent to OOP's:
class Spammer(subject: String, body: String){
def apply(recipient: String) = sendMail(recipient, subject, body)
}
val spam1 = new Spammer("Hello", "World!")
spam1("emai@email.com")
The difference is that partial application is able to deal more easily with complex cases and also has additional syntax sugar:
val spam1 = sendMail(_, "Hello", "World!")
spam1("emai@email.com")
So in simple cases you don't even need to define your own wrapper.
Returning to your more sophisticated example, you could use it this way:
scala> val incrementInt = partial1[Int, Int, Int](1, _ + _)
incrementInt: Int => Int = $$Lambda$1258/21635151@18ca65ea
scala> incrementInt(2)
res47: Int = 3
scala> val incrementList = partial1[List[Int], List[Int], List[Int]](List(0), _ ++ _)
incrementList: List[Int] => List[Int] = $$Lambda$1258/21635151@79f8af90
scala> incrementList(List(0))
res49: List[Int] = List(0, 0)
scala> incrementList(List(0, 0))
res50: List[Int] = List(0, 0, 0)
Basically abstract over addition (A, B) = C
of some fixed abstract element A
to unknown element B
. In the example above it's addition over integers, and addition over lists of zeros. You can imagine more practical example like merging two json's with some fixed pattern and so on.
You might think of partail1
as providing a unified interface to all those cases.