Function return type is wrong after if else expressions


#1

I have the following function which returns a list[Double] or list[list[double]] depending on the order item length:

def orderCost(orderItems: List[Double]) = {

 if (orderItems.length <= 8) orderItems else orderItems.grouped(8).toList

}

So my question is, why my function is returning List[Any] instead of List[Double] or List[List[Double]]. Is there a bug 2.11.8 which i’m using.

orderItems can be one of the below:

orderItems: List[Double] = List(5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0)
or
orderItems: List[Double] = List(5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0)

I want to sum up the return value from the function using map(._, sum) and a list can hold eight element max for my use case.

Thanks


#2

A method can have only one return type.

List[Double] it’s not the same type of List[List[Double]] and since Double andList[Double]are subtypes ofAny`

the compile infer that the general type is List[Any]

In general List[x] and List[y] are the same only if x is the same type as y.


#3

Some answers to questions that you did ask, and some answers to questions you didn’t ask

So my question is, why my function is returning List[Any] instead of List[Double] or List[List[Double]]

A method only has one return type. Your method returns a List[Double] from one branch, and a List[List[Double]] from the other branch. The lowest upper bound (LUB) of those two types is List[Any] and that’s what you get.

When is it detemined what the return type of a method is? Does leaving off the return type of a method mean it has a dynamic return type?

This is resolved at compile time. That you left off the return type doesn’t mean there is no statically known return type, just that you said to the compiler to figure it out for you.

I want to sum up the return value from the function using map(._, sum), how can I do that

the mapmethod only takes one parameter, so I don’t understand exactly what you want to do and return

What should I do instead (note, not asked)

return a List[List[Double]] for both branches.

Going literally from your example, that would be

def orderCost(orderItems: List[Double]) = {

 if (orderItems.length <= 8) List(orderItems) else orderItems.grouped(8).toList

}

but the simpler variation is

def orderCost(orderItems: List[Double]) = orderItems.grouped(8).toList

since the if branch is actually the same as the else branch.


#4

Thanks for the answer