Reputation: 16723
I struggle at times to understand how to call a function. I am studying lists and am writing sample examples of its methods.
The andThen
is defined as follows
def andThen[C](k: (A) ⇒ C): PartialFunction[Int, C]
I understand that I have to pass a function literal to andThen
. So I created following code which works.
scala> val l = List (1,2,3,4)
l: List[Int] = List(1, 2, 3, 4)
//x:Int works
scala> val listAndThenExample = l.andThen((x:Int) => (x*2))
listAndThenExample: PartialFunction[Int,Int] = <function1>
//underscore works
scala> val listAndThenExample = l.andThen(_*2)
listAndThenExample: PartialFunction[Int,Int] = <function1>
As the list is of Integers, A has to be Int. C can be anything depending on the output of function literal.
The above makes sense.
Later I tried applyOrElse
. Its signature is as follows
def applyOrElse[A1 <: Int, B1 >: A](x: A1, default: (A1) ⇒ B1): B1
From above, I understand that A1 can be Int or its subclass (upperbound) and some B1 will be the return type (depending on what I do in default function).
If my understanding of A1 and B1 is correct then x will be either Int or its subclass and the default function literal should take Int (or subclass) and return some B1. I tried to call the function as follows but it doesn't work when I use y:Int
but works when I use _:Int
. I do not understand why.
scala> val l = List (1,2,3,4)
l: List[Int] = List(1, 2, 3, 4)
//this doesn't work
cala> val listApplyOrElse = l.applyOrElse(y:Int,(x:Int)=>println("Wrong arg "+x))
<console>:12: error: not found: value y
val listApplyOrElse = l.applyOrElse(y:Int,(x:Int)=>println("Wrong arg "+x))
^
//but underscor works
scala> val listApplyOrElse = l.applyOrElse(_:Int,(x:Int)=>println("Wrong arg "+x))
listApplyOrElse: Int => AnyVal = <function1>
Question - Why did both x:Int and _:Int worked for andThen but not for applyOrElse?
Question - what is 'A' and why is B1 related to A?
Upvotes: 1
Views: 133
Reputation: 22325
According to the documentation, applyOrElse(x, default)
is equivalent to
if (pf isDefinedAt x) pf(x) else default(x)
In this case your partial function is a list i.e. a function from indices (0 to 3) to values (1,2,3,4). So when you do
l.applyOrElse(y,(x:Int)=>println("Wrong arg "+x))
you're saying "Call l(y)
if it makes sense, otherwise println("Wrong arg"+y)
". The compiler reasonably responds, "What is y
?"
If you use an actual value it works as expected
l.applyOrElse(3 ,(x:Int)=>println("Wrong arg "+x)) // returns 4
l.applyOrElse(8 ,(x:Int)=>println("Wrong arg "+x)) // prints Wrong arg 8
Using an underscore does something completely different, you get a partially applied function (which is completely different from a partial function!)
val f = l.applyOrElse(_:Int, (x:Int)=>println("Wrong arg "+x))
f(8) // prints Wrong arg 8
Upvotes: 1
Reputation: 8529
You haven't declared y, so trying to use it is an error. _:Int
works because this is now creating a partially applied function. Notice the return type is not a value, but a function. This returned function is the applyOrElse
with the second argument already provided (but not the first).
With your andThen
example, the use of _
means something different, specifically it is a shorthand notation for a function literal.
Upvotes: 0