Reputation: 555
I'm trying to understand how function partial application works in Scala.
To do that, I've built this simple code:
object Test extends App {
myCustomConcat("General", "Public", "License") foreach print
GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
def myCustomConcat(strings: String*): List[Char] = {
val result = for (s <- strings) yield {
s.charAt(0)
}
result.toList
}
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ) = {
myCustomConcat("General", "Public", "License")
}
}
myCostumConcat function takes in input an array of String and it returns a list containing the first letter of each string.
So, the code
myCustomConcat("General", "Public", "License") foreach print
will print on console: GPL
Suppose now that I want to write a function to generate the GPL acronym, using (as input parameter) my previous function extracting the first letter of each string:
def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ): List[Char] = {
myCustomConcat("General", "Public", "License")
}
Running this new function with partial application:
GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
I get this error:
Error:(8, 46) type mismatch; found : Seq[String] required: String GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print
Why? Can I use partial application in this case?
Upvotes: 2
Views: 483
Reputation: 42586
All you need to do is change myCustomConcat(_)
to myCustomConcat _
, or indeed just myCustomConcat
What you are doing isn't exactly partial application - it's just using a method as a function value.
In some cases (where a function value is expected) the compiler will work out what you mean, but in other contexts you often need to tell the compiler your intention, using the _
suffix.
"partial application" means that we are supplying some, but not all, of the arguments to a function, to create a new function, for example:
def add(x: Int, y: Int) = x + y //> add: (x: Int, y: Int)Int
val addOne: Int => Int = add(1, _) //> addOne : Int => Int = <function1>
addOne(2) //> res0: Int = 3
I suppose your case could be seen as partial application, but applying none of the arguments - you can use partial application syntax here, but you need to give a _*
hint to the compiler because of the repeated parameters (String*
), which ends up a bit ugly:
myCustomConcat(_:_*)
See also: Scala type ascription for varargs using _* cause error
Upvotes: 5