Manu Chadha Manu Chadha - 16 days ago 7
Scala Question

unable to understand function's signature of scala apis

I struggle at times to understand how to call a function. Could someone please help me.

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 doesnt 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?

Max Max
Answer

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
Comments